From 5ee5da8f812c7eb97071b2169beade04dab7f2bd Mon Sep 17 00:00:00 2001 From: Stephan Vedder Date: Thu, 6 Dec 2018 23:40:20 +0100 Subject: [PATCH 001/223] Start work on jpeg 12 bit support --- src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs | 10 +++++----- .../Formats/Jpg/JpegDecoderTests.Images.cs | 5 ++++- tests/ImageSharp.Tests/TestImages.cs | 4 +++- tests/Images/Input/Jpg/baseline/testorig12.jpg | Bin 0 -> 12394 bytes 4 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 tests/Images/Input/Jpg/baseline/testorig12.jpg diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index f6da9cb2e..5bfe88cc6 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// The only supported precision /// - public const int SupportedPrecision = 8; + public readonly int[] SupportedPrecisions = { 8, 12 }; /// /// The global configuration @@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Gets the color depth, in number of bits per pixel. /// - public int BitsPerPixel => this.ComponentCount * SupportedPrecision; + public int BitsPerPixel => this.ComponentCount * this.Frame.Precision; /// /// Gets the input stream. @@ -720,10 +720,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.InputStream.Read(this.temp, 0, remaining); - // We only support 8-bit precision. - if (this.temp[0] != SupportedPrecision) + // We only support 8-bit and 12-bit precision. + if (!SupportedPrecisions.Contains(this.temp[0])) { - throw new ImageFormatException("Only 8-Bit precision supported."); + throw new ImageFormatException("Only 8-Bit and 12-Bit precision supported."); } this.Frame = new JpegFrame diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index 40de25b30..03f1826ed 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -28,7 +28,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Issues.ExifResizeOutOfRange696, TestImages.Jpeg.Issues.InvalidAPP0721, TestImages.Jpeg.Issues.ExifGetString750Load, - TestImages.Jpeg.Issues.ExifGetString750Transform + TestImages.Jpeg.Issues.ExifGetString750Transform, + + // High depth images + TestImages.Jpeg.Baseline.Testorig12bit, }; public static string[] ProgressiveTestJpegs = diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 1144a3f7c..46f9459c5 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -135,12 +135,14 @@ namespace SixLabors.ImageSharp.Tests public const string Testorig420 = "Jpg/baseline/testorig.jpg"; public const string MultiScanBaselineCMYK = "Jpg/baseline/MultiScanBaselineCMYK.jpg"; public const string Ratio1x1 = "Jpg/baseline/ratio-1x1.jpg"; + public const string Testorig12bit = "Jpg/baseline/testorig12.jpg"; public static readonly string[] All = { Cmyk, Ycck, Exif, Floorplan, Calliphora, Turtle, GammaDalaiLamaGray, - Hiyamugi, Jpeg400, Jpeg420Exif, Jpeg444, Ratio1x1 + Hiyamugi, Jpeg400, Jpeg420Exif, Jpeg444, + Ratio1x1, Testorig12bit }; } diff --git a/tests/Images/Input/Jpg/baseline/testorig12.jpg b/tests/Images/Input/Jpg/baseline/testorig12.jpg new file mode 100644 index 0000000000000000000000000000000000000000..861aff98e2a78131bf546b82fd38b00a4f741dd2 GIT binary patch literal 12394 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 Iua1WP4;iQWivR!s literal 0 HcmV?d00001 From ede120d5aa2a5928a0f4e1b75ce86a86aebe32f5 Mon Sep 17 00:00:00 2001 From: Stephan Vedder Date: Sun, 9 Dec 2018 12:26:17 +0100 Subject: [PATCH 002/223] Work on 12-bit support --- src/ImageSharp/Common/Tuples/Vector4Pair.cs | 16 +++---- .../Jpeg/Components/Block8x8F.Generated.cs | 18 ++++---- .../Jpeg/Components/Block8x8F.Generated.tt | 18 ++++---- .../Formats/Jpeg/Components/Block8x8F.cs | 8 ++-- .../JpegColorConverter.FromCmyk.cs | 11 +++-- .../JpegColorConverter.FromGrayScale.cs | 9 ++-- .../JpegColorConverter.FromRgb.cs | 9 ++-- .../JpegColorConverter.FromYCbCrBasic.cs | 4 +- .../JpegColorConverter.FromYCbCrSimd.cs | 26 ++++++------ .../JpegColorConverter.FromYCbCrSimdAvx2.cs | 4 +- .../JpegColorConverter.FromYccK.cs | 21 ++++++---- .../ColorConverters/JpegColorConverter.cs | 42 ++++++++++++++++--- .../Jpeg/Components/Decoder/IRawJpegData.cs | 5 +++ .../Decoder/JpegBlockPostProcessor.cs | 12 +++++- .../Decoder/JpegComponentPostProcessor.cs | 3 +- .../Decoder/JpegImagePostProcessor.cs | 2 +- .../Formats/Jpeg/JpegDecoderCore.cs | 7 +++- .../Formats/Jpg/Block8x8FTests.cs | 6 +-- .../Formats/Jpg/JpegColorConverterTests.cs | 20 ++++----- 19 files changed, 151 insertions(+), 90 deletions(-) diff --git a/src/ImageSharp/Common/Tuples/Vector4Pair.cs b/src/ImageSharp/Common/Tuples/Vector4Pair.cs index cae283d62..2a42160d6 100644 --- a/src/ImageSharp/Common/Tuples/Vector4Pair.cs +++ b/src/ImageSharp/Common/Tuples/Vector4Pair.cs @@ -37,12 +37,12 @@ namespace SixLabors.ImageSharp.Tuples this.B += other.B; } - /// - /// Downscale method, specific to Jpeg color conversion. Works only if Vector{float}.Count == 4! + /// . Works only if Ve + /// Downscale method, specific to Jpeg color conversctor{float}.Count == 4! /// TODO: Move it somewhere else. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void RoundAndDownscalePreAvx2() + internal void RoundAndDownscalePreAvx2(float downscaleFactor) { ref Vector a = ref Unsafe.As>(ref this.A); a = a.FastRound(); @@ -50,8 +50,8 @@ namespace SixLabors.ImageSharp.Tuples ref Vector b = ref Unsafe.As>(ref this.B); b = b.FastRound(); - // Downscale by 1/255 - var scale = new Vector4(1 / 255f); + // Downscale by 1/factor + var scale = new Vector4(1 / downscaleFactor); this.A *= scale; this.B *= scale; } @@ -61,14 +61,14 @@ namespace SixLabors.ImageSharp.Tuples /// TODO: Move it somewhere else. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void RoundAndDownscaleAvx2() + internal void RoundAndDownscaleAvx2(float downscaleFactor) { ref Vector self = ref Unsafe.As>(ref this); Vector v = self; v = v.FastRound(); - // Downscale by 1/255 - v *= new Vector(1 / 255f); + // Downscale by 1/factor + v *= new Vector(1 / downscaleFactor); self = v; } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs index 09ed6408d..15fbb83d9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs @@ -9,10 +9,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { internal partial struct Block8x8F { - 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 the destination block. /// @@ -94,10 +90,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// Level shift by +128, clip to [0, 255] + /// Level shift by +maximum/2, clip to [0, maximum] /// - public void NormalizeColorsInplace() + public void NormalizeColorsInplace(float maximum) { + Vector4 CMin4 = new Vector4(0F); + Vector4 CMax4 = new Vector4(maximum); + Vector4 COff4 = new Vector4(maximum/2 + 1); + this.V0L = Vector4.Clamp(this.V0L + COff4, CMin4, CMax4); this.V0R = Vector4.Clamp(this.V0R + COff4, CMin4, CMax4); this.V1L = Vector4.Clamp(this.V1L + COff4, CMin4, CMax4); @@ -120,10 +120,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// AVX2-only variant for executing and in one step. /// [MethodImpl(InliningOptions.ShortMethod)] - public void NormalizeColorsAndRoundInplaceAvx2() + public void NormalizeColorsAndRoundInplaceAvx2(float maximum) { - Vector off = new Vector(128f); - Vector max = new Vector(255F); + Vector off = new Vector(maximum/2 +1); + Vector max = new Vector(maximum); ref Vector row0 = ref Unsafe.As>(ref this.V0L); row0 = NormalizeAndRound(row0, off, max); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt index f93ee6522..431ba86b0 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt @@ -22,10 +22,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { internal partial struct Block8x8F { - 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 the destination block. /// @@ -59,10 +55,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// Level shift by +128, clip to [0, 255] + /// Level shift by +maximum/2, clip to [0, maximum] /// - public void NormalizeColorsInplace() + public void NormalizeColorsInplace(float maximum) { + Vector4 CMin4 = new Vector4(0F); + Vector4 CMax4 = new Vector4(maximum); + Vector4 COff4 = new Vector4(maximum/2 + 1); + <# PushIndent(" "); @@ -83,10 +83,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// AVX2-only variant for executing and in one step. /// [MethodImpl(InliningOptions.ShortMethod)] - public void NormalizeColorsAndRoundInplaceAvx2() + public void NormalizeColorsAndRoundInplaceAvx2(float maximum) { - Vector off = new Vector(128f); - Vector max = new Vector(255F); + Vector off = new Vector(maximum/2 +1); + Vector max = new Vector(maximum); <# for (int i = 0; i < 8; i++) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 81393342d..c9c886f05 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -467,17 +467,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// Level shift by +128, clip to [0..255], and round all the values in the block. + /// Level shift by +maximum/2, clip to [0..maximum], and round all the values in the block. /// - public void NormalizeColorsAndRoundInplace() + public void NormalizeColorsAndRoundInplace(float maximum) { if (SimdUtils.IsAvx2CompatibleArchitecture) { - this.NormalizeColorsAndRoundInplaceAvx2(); + this.NormalizeColorsAndRoundInplaceAvx2(maximum); } else { - this.NormalizeColorsInplace(); + this.NormalizeColorsInplace(maximum); this.RoundInplace(); } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs index 7a14d072e..28f000019 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs @@ -10,8 +10,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal class FromCmyk : JpegColorConverter { - public FromCmyk() - : base(JpegColorSpace.Cmyk) + public FromCmyk(int precision) + : base(JpegColorSpace.Cmyk, precision) { } @@ -25,14 +25,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters var v = new Vector4(0, 0, 0, 1F); - var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + var scale = new Vector4(1 / this.MaximumValue, + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1F); for (int i = 0; i < result.Length; i++) { float c = cVals[i]; float m = mVals[i]; float y = yVals[i]; - float k = kVals[i] / 255F; + float k = kVals[i] / this.MaximumValue; v.X = c * k; v.Y = m * k; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs index 7424145c3..36bd6fca9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs @@ -12,14 +12,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal class FromGrayscale : JpegColorConverter { - public FromGrayscale() - : base(JpegColorSpace.Grayscale) + public FromGrayscale(int precision) + : base(JpegColorSpace.Grayscale, precision) { } public override void ConvertToRgba(in ComponentValues values, Span result) { - var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + var scale = new Vector4(1 / this.MaximumValue, + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1F); ref float sBase = ref MemoryMarshal.GetReference(values.Component0); ref Vector4 dBase = ref MemoryMarshal.GetReference(result); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs index 7cd97c414..13eec7aad 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs @@ -10,8 +10,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal class FromRgb : JpegColorConverter { - public FromRgb() - : base(JpegColorSpace.RGB) + public FromRgb(int precision) + : base(JpegColorSpace.RGB, precision) { } @@ -24,7 +24,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters var v = new Vector4(0, 0, 0, 1); - var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + var scale = new Vector4(1 / this.MaximumValue, + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1F); for (int i = 0; i < result.Length; i++) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs index cb71889bc..2cab95ff0 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs @@ -10,8 +10,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal class FromYCbCrBasic : JpegColorConverter { - public FromYCbCrBasic() - : base(JpegColorSpace.YCbCr) + public FromYCbCrBasic(int precision) + : base(JpegColorSpace.YCbCr, precision) { } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs index 23aa1acbe..104795710 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal class FromYCbCrSimd : JpegColorConverter { - public FromYCbCrSimd() - : base(JpegColorSpace.YCbCr) + public FromYCbCrSimd(int precision) + : base(JpegColorSpace.YCbCr, precision) { } @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters int simdCount = result.Length - remainder; if (simdCount > 0) { - ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount)); + ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), this.MaximumValue, this.HalfValue); } FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder)); @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// /// SIMD convert using buffers of sizes divisible by 8. /// - internal static void ConvertCore(in ComponentValues values, Span result) + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) { DebugGuard.IsTrue(result.Length % 8 == 0, nameof(result), "result.Length should be divisible by 8!"); @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ref Vector4Octet resultBase = ref Unsafe.As(ref MemoryMarshal.GetReference(result)); - var chromaOffset = new Vector4(-128f); + var chromaOffset = new Vector4(-halfValue); // Walking 8 elements at one step: int n = result.Length / 8; @@ -58,11 +58,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters // y = yVals[i]; Vector4Pair y = Unsafe.Add(ref yBase, i); - // cb = cbVals[i] - 128F; + // cb = cbVals[i] - halfValue); Vector4Pair cb = Unsafe.Add(ref cbBase, i); cb.AddInplace(chromaOffset); - // cr = crVals[i] - 128F; + // cr = crVals[i] - halfValue; Vector4Pair cr = Unsafe.Add(ref crBase, i); cr.AddInplace(chromaOffset); @@ -90,15 +90,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters if (Vector.Count == 4) { // TODO: Find a way to properly run & test this path on AVX2 PC-s! (Have I already mentioned that Vector is terrible?) - r.RoundAndDownscalePreAvx2(); - g.RoundAndDownscalePreAvx2(); - b.RoundAndDownscalePreAvx2(); + r.RoundAndDownscalePreAvx2(maxValue); + g.RoundAndDownscalePreAvx2(maxValue); + b.RoundAndDownscalePreAvx2(maxValue); } else if (SimdUtils.IsAvx2CompatibleArchitecture) { - r.RoundAndDownscaleAvx2(); - g.RoundAndDownscaleAvx2(); - b.RoundAndDownscaleAvx2(); + r.RoundAndDownscaleAvx2(maxValue); + g.RoundAndDownscaleAvx2(maxValue); + b.RoundAndDownscaleAvx2(maxValue); } else { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs index f0a70a6f3..469695995 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs @@ -15,8 +15,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal class FromYCbCrSimdAvx2 : JpegColorConverter { - public FromYCbCrSimdAvx2() - : base(JpegColorSpace.YCbCr) + public FromYCbCrSimdAvx2(int precision) + : base(JpegColorSpace.YCbCr, precision) { } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs index 6f940f62f..d4e151015 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs @@ -10,8 +10,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal class FromYccK : JpegColorConverter { - public FromYccK() - : base(JpegColorSpace.Ycck) + public FromYccK(int precision) + : base(JpegColorSpace.Ycck, precision) { } @@ -25,18 +25,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters var v = new Vector4(0, 0, 0, 1F); - var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + var scale = new Vector4(1 / this.MaximumValue, + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1F); for (int i = 0; i < result.Length; i++) { float y = yVals[i]; - float cb = cbVals[i] - 128F; - float cr = crVals[i] - 128F; - float k = kVals[i] / 255F; + float cb = cbVals[i] - this.HalfValue; + float cr = crVals[i] - this.HalfValue; + float k = kVals[i] / this.MaximumValue; - v.X = (255F - MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; - v.Y = (255F - MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero)) * k; - v.Z = (255F - MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; + v.X = (this.MaximumValue - MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; + v.Y = (this.MaximumValue - MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero)) * k; + v.Z = (this.MaximumValue - MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; v.W = 1F; v *= scale; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index a44ebf89d..30dbdc896 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -22,15 +22,29 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// private static readonly JpegColorConverter[] Converters = { - GetYCbCrConverter(), new FromYccK(), new FromCmyk(), new FromGrayscale(), new FromRgb() + // 8-bit converters + GetYCbCrConverter(8), + new FromYccK(8), + new FromCmyk(8), + new FromGrayscale(8), + new FromRgb(8), + // 12-bit converters + GetYCbCrConverter(12), + new FromYccK(12), + new FromCmyk(12), + new FromGrayscale(12), + new FromRgb(12), }; /// /// Initializes a new instance of the class. /// - protected JpegColorConverter(JpegColorSpace colorSpace) + protected JpegColorConverter(JpegColorSpace colorSpace, int precision) { this.ColorSpace = colorSpace; + this.Precision = precision; + this.MaximumValue = (float)Math.Pow(2, precision) - 1; + this.HalfValue = (float)Math.Ceiling(this.MaximumValue / 2); } /// @@ -38,12 +52,28 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// public JpegColorSpace ColorSpace { get; } + /// + /// Gets the Precision of this converter in bits. + /// + public int Precision { get; } + + /// + /// Gets the maximum value of a sample + /// + private float MaximumValue { get; } + + /// + /// Gets the maximum value of a sample + /// + private float HalfValue { get; } + /// /// Returns the corresponding to the given /// - public static JpegColorConverter GetConverter(JpegColorSpace colorSpace) + public static JpegColorConverter GetConverter(JpegColorSpace colorSpace, float precision) { - JpegColorConverter converter = Converters.FirstOrDefault(c => c.ColorSpace == colorSpace); + JpegColorConverter converter = Converters.FirstOrDefault(c => c.ColorSpace == colorSpace && + c.Precision == precision); if (converter is null) { @@ -63,8 +93,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// /// Returns the for the YCbCr colorspace that matches the current CPU architecture. /// - private static JpegColorConverter GetYCbCrConverter() => - FromYCbCrSimdAvx2.IsAvailable ? (JpegColorConverter)new FromYCbCrSimdAvx2() : new FromYCbCrSimd(); + private static JpegColorConverter GetYCbCrConverter(int precision) => + FromYCbCrSimdAvx2.IsAvailable ? (JpegColorConverter)new FromYCbCrSimdAvx2(precision) : new FromYCbCrSimd(precision); /// /// A stack-only struct to reference the input buffers using -s. diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs index 1454bb5b1..83d65c042 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs @@ -29,6 +29,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// JpegColorSpace ColorSpace { get; } + /// + /// Gets the number of bits used for precision. + /// + int Precision { get; } + /// /// Gets the components. /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs index da4b2847b..b034198cf 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; using SixLabors.Primitives; @@ -38,6 +39,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// private Size subSamplingDivisors; + /// + /// Defines the maximum value derived from the bitdepth + /// + private int maximumValue; + /// /// Initializes a new instance of the struct. /// @@ -48,6 +54,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder int qtIndex = component.QuantizationTableIndex; this.DequantiazationTable = ZigZag.CreateDequantizationTable(ref decoder.QuantizationTables[qtIndex]); this.subSamplingDivisors = component.SubSamplingDivisors; + this.maximumValue = (int)Math.Pow(2, decoder.Precision) - 1; this.SourceBlock = default; this.WorkspaceBlock1 = default; @@ -65,7 +72,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// The destination buffer area. public void ProcessBlockColorsInto( ref Block8x8 sourceBlock, - in BufferArea destArea) + in BufferArea destArea, + float maximumValue) { ref Block8x8F b = ref this.SourceBlock; b.LoadFrom(ref sourceBlock); @@ -78,7 +86,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder // To conform better to libjpeg we actually NEED TO loose precision here. // This is because they store blocks as Int16 between all the operations. // To be "more accurate", we need to emulate this by rounding! - this.WorkspaceBlock1.NormalizeColorsAndRoundInplace(); + this.WorkspaceBlock1.NormalizeColorsAndRoundInplace(maximumValue); this.WorkspaceBlock1.CopyTo(destArea, this.subSamplingDivisors.Width, this.subSamplingDivisors.Height); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs index 94ec600dd..66c9245a3 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs @@ -78,6 +78,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder public void CopyBlocksToColorBuffer() { var blockPp = new JpegBlockPostProcessor(this.ImagePostProcessor.RawJpeg, this.Component); + float maximumValue = (float)Math.Pow(2,this.ImagePostProcessor.RawJpeg.Precision) - 1; for (int y = 0; y < this.BlockRowsPerStep; y++) { @@ -105,7 +106,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.blockAreaSize.Width, this.blockAreaSize.Height); - blockPp.ProcessBlockColorsInto(ref block, destArea); + blockPp.ProcessBlockColorsInto(ref block, destArea, maximumValue); } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs index 7ce86b4c9..6b5995515 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs @@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder MemoryAllocator memoryAllocator = configuration.MemoryAllocator; this.ComponentProcessors = rawJpeg.Components.Select(c => new JpegComponentPostProcessor(memoryAllocator, this, c)).ToArray(); this.rgbaBuffer = memoryAllocator.Allocate(rawJpeg.ImageSizeInPixels.Width); - this.colorConverter = JpegColorConverter.GetConverter(rawJpeg.ColorSpace); + this.colorConverter = JpegColorConverter.GetConverter(rawJpeg.ColorSpace, rawJpeg.Precision); } /// diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 5bfe88cc6..fb10425bd 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -160,6 +160,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// public JpegColorSpace ColorSpace { get; private set; } + /// + public int Precision { get; private set; } + /// /// Gets the components. /// @@ -721,11 +724,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.InputStream.Read(this.temp, 0, remaining); // We only support 8-bit and 12-bit precision. - if (!SupportedPrecisions.Contains(this.temp[0])) + if (!this.SupportedPrecisions.Contains(this.temp[0])) { throw new ImageFormatException("Only 8-Bit and 12-Bit precision supported."); } + this.Precision = this.temp[0]; + this.Frame = new JpegFrame { Extended = frameMarker.Marker == JpegConstants.Markers.SOF1, diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs index 81c76390c..7e7218c9d 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs @@ -228,7 +228,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg this.PrintLinearData(input); Block8x8F dest = block; - dest.NormalizeColorsInplace(); + dest.NormalizeColorsInplace(255); float[] array = new float[64]; dest.CopyTo(array); @@ -253,11 +253,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg Block8x8F source = CreateRandomFloatBlock(-200, 200, seed); Block8x8F expected = source; - expected.NormalizeColorsInplace(); + expected.NormalizeColorsInplace(255); expected.RoundInplace(); Block8x8F actual = source; - actual.NormalizeColorsAndRoundInplaceAvx2(); + actual.NormalizeColorsAndRoundInplaceAvx2(255); this.Output.WriteLine(expected.ToString()); this.Output.WriteLine(actual.ToString()); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index 8e30eb9e5..caaad73c9 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg public void ConvertFromYCbCrBasic(int inputBufferLength, int resultBufferLength, int seed) { ValidateRgbToYCbCrConversion( - new JpegColorConverter.FromYCbCrBasic(), + new JpegColorConverter.FromYCbCrBasic(8), 3, inputBufferLength, resultBufferLength, @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg JpegColorConverter.ComponentValues values = CreateRandomValues(3, size, seed); var result = new Vector4[size]; - JpegColorConverter.FromYCbCrSimd.ConvertCore(values, result); + JpegColorConverter.FromYCbCrSimd.ConvertCore(values, result, 255, 128); for (int i = 0; i < size; i++) { @@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg public void FromYCbCrSimd(int inputBufferLength, int resultBufferLength, int seed) { ValidateRgbToYCbCrConversion( - new JpegColorConverter.FromYCbCrSimd(), + new JpegColorConverter.FromYCbCrSimd(8), 3, inputBufferLength, resultBufferLength, @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg //JpegColorConverter.FromYCbCrSimdAvx2.LogPlz = s => this.Output.WriteLine(s); ValidateRgbToYCbCrConversion( - new JpegColorConverter.FromYCbCrSimdAvx2(), + new JpegColorConverter.FromYCbCrSimdAvx2(8), 3, inputBufferLength, resultBufferLength, @@ -140,7 +140,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg JpegColorConverter.ComponentValues values = CreateRandomValues(3, count, 1); var result = new Vector4[count]; - JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrSimd() : new JpegColorConverter.FromYCbCrBasic(); + JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrSimd(8) : new JpegColorConverter.FromYCbCrBasic(8); // Warm up: converter.ConvertToRgba(values, result); @@ -161,7 +161,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var v = new Vector4(0, 0, 0, 1F); var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); - var converter = JpegColorConverter.GetConverter(JpegColorSpace.Cmyk); + var converter = JpegColorConverter.GetConverter(JpegColorSpace.Cmyk, 8); JpegColorConverter.ComponentValues values = CreateRandomValues(4, inputBufferLength, seed); var result = new Vector4[resultBufferLength]; @@ -194,7 +194,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [MemberData(nameof(CommonConversionData))] public void ConvertFromGrayScale(int inputBufferLength, int resultBufferLength, int seed) { - var converter = JpegColorConverter.GetConverter(JpegColorSpace.Grayscale); + var converter = JpegColorConverter.GetConverter(JpegColorSpace.Grayscale, 8); JpegColorConverter.ComponentValues values = CreateRandomValues(1, inputBufferLength, seed); var result = new Vector4[resultBufferLength]; @@ -216,7 +216,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [MemberData(nameof(CommonConversionData))] public void ConvertFromRgb(int inputBufferLength, int resultBufferLength, int seed) { - var converter = JpegColorConverter.GetConverter(JpegColorSpace.RGB); + var converter = JpegColorConverter.GetConverter(JpegColorSpace.RGB, 8); JpegColorConverter.ComponentValues values = CreateRandomValues(3, inputBufferLength, seed); var result = new Vector4[resultBufferLength]; @@ -243,7 +243,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var v = new Vector4(0, 0, 0, 1F); var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); - var converter = JpegColorConverter.GetConverter(JpegColorSpace.Ycck); + var converter = JpegColorConverter.GetConverter(JpegColorSpace.Ycck, 8); JpegColorConverter.ComponentValues values = CreateRandomValues(4, inputBufferLength, seed); var result = new Vector4[resultBufferLength]; @@ -308,7 +308,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg int seed) { ValidateRgbToYCbCrConversion( - JpegColorConverter.GetConverter(colorSpace), + JpegColorConverter.GetConverter(colorSpace,8), componentCount, inputBufferLength, resultBufferLength, From 5ef3f19c1f9a1e6da748db3c0543b05df93b0956 Mon Sep 17 00:00:00 2001 From: Stephan Vedder Date: Sun, 9 Dec 2018 18:26:23 +0100 Subject: [PATCH 003/223] Add missing Non-SIMD implementation --- .../Formats/Jpeg/Components/Block8x8F.Generated.cs | 5 +++-- .../Formats/Jpeg/Components/Block8x8F.Generated.tt | 5 +++-- .../JpegColorConverter.FromYCbCrBasic.cs | 10 +++++----- .../JpegColorConverter.FromYCbCrSimd.cs | 3 ++- .../JpegColorConverter.FromYCbCrSimdAvx2.cs | 12 +++++++----- .../Codecs/Jpeg/YCbCrColorConversion.cs | 6 +++--- 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs index 15fbb83d9..1f47de594 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using System.Runtime.CompilerServices; @@ -96,7 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { Vector4 CMin4 = new Vector4(0F); Vector4 CMax4 = new Vector4(maximum); - Vector4 COff4 = new Vector4(maximum/2 + 1); + Vector4 COff4 = new Vector4((float)Math.Ceiling(maximum/2)); this.V0L = Vector4.Clamp(this.V0L + COff4, CMin4, CMax4); this.V0R = Vector4.Clamp(this.V0R + COff4, CMin4, CMax4); @@ -122,7 +123,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public void NormalizeColorsAndRoundInplaceAvx2(float maximum) { - Vector off = new Vector(maximum/2 +1); + Vector off = new Vector((float)Math.Ceiling(maximum/2)); Vector max = new Vector(maximum); ref Vector row0 = ref Unsafe.As>(ref this.V0L); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt index 431ba86b0..ec4e06e42 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt @@ -11,6 +11,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using System.Runtime.CompilerServices; @@ -61,7 +62,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { Vector4 CMin4 = new Vector4(0F); Vector4 CMax4 = new Vector4(maximum); - Vector4 COff4 = new Vector4(maximum/2 + 1); + Vector4 COff4 = new Vector4((float)Math.Ceiling(maximum/2)); <# @@ -85,7 +86,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public void NormalizeColorsAndRoundInplaceAvx2(float maximum) { - Vector off = new Vector(maximum/2 +1); + Vector off = new Vector((float)Math.Ceiling(maximum/2)); Vector max = new Vector(maximum); <# diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs index 2cab95ff0..124aac122 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs @@ -17,10 +17,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters public override void ConvertToRgba(in ComponentValues values, Span result) { - ConvertCore(values, result); + ConvertCore(values, result, this.MaximumValue, this.HalfValue); } - internal static void ConvertCore(in ComponentValues values, Span result) + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) { // TODO: We can optimize a lot here with Vector and SRCS.Unsafe()! ReadOnlySpan yVals = values.Component0; @@ -29,13 +29,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters var v = new Vector4(0, 0, 0, 1); - var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + var scale = new Vector4(1 / maxValue, 1 / maxValue, 1 / maxValue, 1F); for (int i = 0; i < result.Length; i++) { float y = yVals[i]; - float cb = cbVals[i] - 128F; - float cr = crVals[i] - 128F; + float cb = cbVals[i] - halfValue; + float cr = crVals[i] - halfValue; v.X = MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero); v.Y = MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs index 104795710..5de6f2ffb 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs @@ -28,7 +28,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), this.MaximumValue, this.HalfValue); } - FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder)); + FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder), + this.MaximumValue, this.HalfValue); } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs index 469695995..c34bc17ad 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs @@ -28,16 +28,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters int simdCount = result.Length - remainder; if (simdCount > 0) { - ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount)); + ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), + this.MaximumValue, this.HalfValue); } - FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder)); + FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder), + this.MaximumValue, this.HalfValue);; } /// /// SIMD convert using buffers of sizes divisible by 8. /// - internal static void ConvertCore(in ComponentValues values, Span result) + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) { // This implementation is actually AVX specific. // An AVX register is capable of storing 8 float-s. @@ -57,7 +59,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ref Vector4Octet resultBase = ref Unsafe.As(ref MemoryMarshal.GetReference(result)); - var chromaOffset = new Vector(-128f); + var chromaOffset = new Vector(-halfValue); // Walking 8 elements at one step: int n = result.Length / 8; @@ -70,7 +72,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ref Vector ggRefAsVector = ref Unsafe.As>(ref gg); ref Vector bbRefAsVector = ref Unsafe.As>(ref bb); - var scale = new Vector(1 / 255f); + var scale = new Vector(1 / maxValue); for (int i = 0; i < n; i++) { diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs index 05edd2791..8417b32f2 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { var values = new JpegColorConverter.ComponentValues(this.input, 0); - JpegColorConverter.FromYCbCrBasic.ConvertCore(values, this.output); + JpegColorConverter.FromYCbCrBasic.ConvertCore(values, this.output, 255F, 128F); } [Benchmark] @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { var values = new JpegColorConverter.ComponentValues(this.input, 0); - JpegColorConverter.FromYCbCrSimd.ConvertCore(values, this.output); + JpegColorConverter.FromYCbCrSimd.ConvertCore(values, this.output, 255F, 128F); } [Benchmark] @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { var values = new JpegColorConverter.ComponentValues(this.input, 0); - JpegColorConverter.FromYCbCrSimdAvx2.ConvertCore(values, this.output); + JpegColorConverter.FromYCbCrSimdAvx2.ConvertCore(values, this.output, 255F, 128F); } private static Buffer2D[] CreateRandomValues( From b17bda5e9adf7f2367bb61a57956729763a0a2ed Mon Sep 17 00:00:00 2001 From: Stephan Vedder Date: Mon, 10 Dec 2018 18:39:34 +0100 Subject: [PATCH 004/223] Fix style issues --- src/ImageSharp/Common/Tuples/Vector4Pair.cs | 5 ++--- .../ColorConverters/JpegColorConverter.FromCmyk.cs | 9 +++++---- .../ColorConverters/JpegColorConverter.FromGrayScale.cs | 9 +++++---- .../ColorConverters/JpegColorConverter.FromRgb.cs | 9 +++++---- .../ColorConverters/JpegColorConverter.FromYCbCrSimd.cs | 3 +-- .../JpegColorConverter.FromYCbCrSimdAvx2.cs | 6 ++---- .../ColorConverters/JpegColorConverter.FromYccK.cs | 9 +++++---- .../Decoder/ColorConverters/JpegColorConverter.cs | 3 ++- .../Jpeg/Components/Decoder/JpegBlockPostProcessor.cs | 4 +++- src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs | 4 ++-- 10 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/ImageSharp/Common/Tuples/Vector4Pair.cs b/src/ImageSharp/Common/Tuples/Vector4Pair.cs index 2a42160d6..2e5ca3137 100644 --- a/src/ImageSharp/Common/Tuples/Vector4Pair.cs +++ b/src/ImageSharp/Common/Tuples/Vector4Pair.cs @@ -37,9 +37,8 @@ namespace SixLabors.ImageSharp.Tuples this.B += other.B; } - /// . Works only if Ve - /// Downscale method, specific to Jpeg color conversctor{float}.Count == 4! - /// TODO: Move it somewhere else. + /// . + /// Downscale method, specific to Jpeg color conversion. Works only if Vector{float}.Count == 4! /// TODO: Move it somewhere else. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void RoundAndDownscalePreAvx2(float downscaleFactor) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs index 28f000019..d4dc31fe0 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs @@ -25,10 +25,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters var v = new Vector4(0, 0, 0, 1F); - var scale = new Vector4(1 / this.MaximumValue, - 1 / this.MaximumValue, - 1 / this.MaximumValue, - 1F); + var scale = new Vector4( + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1F); for (int i = 0; i < result.Length; i++) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs index 36bd6fca9..4a5dfa632 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs @@ -19,10 +19,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters public override void ConvertToRgba(in ComponentValues values, Span result) { - var scale = new Vector4(1 / this.MaximumValue, - 1 / this.MaximumValue, - 1 / this.MaximumValue, - 1F); + var scale = new Vector4( + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1F); ref float sBase = ref MemoryMarshal.GetReference(values.Component0); ref Vector4 dBase = ref MemoryMarshal.GetReference(result); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs index 13eec7aad..516dfb39f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs @@ -24,10 +24,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters var v = new Vector4(0, 0, 0, 1); - var scale = new Vector4(1 / this.MaximumValue, - 1 / this.MaximumValue, - 1 / this.MaximumValue, - 1F); + var scale = new Vector4( + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1F); for (int i = 0; i < result.Length; i++) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs index 5de6f2ffb..10ef02a93 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs @@ -28,8 +28,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), this.MaximumValue, this.HalfValue); } - FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder), - this.MaximumValue, this.HalfValue); + FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder), this.MaximumValue, this.HalfValue); } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs index c34bc17ad..9953f78c1 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs @@ -28,12 +28,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters int simdCount = result.Length - remainder; if (simdCount > 0) { - ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), - this.MaximumValue, this.HalfValue); + ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), this.MaximumValue, this.HalfValue); } - FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder), - this.MaximumValue, this.HalfValue);; + FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder), this.MaximumValue, this.HalfValue); } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs index d4e151015..94be11e23 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs @@ -25,10 +25,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters var v = new Vector4(0, 0, 0, 1F); - var scale = new Vector4(1 / this.MaximumValue, - 1 / this.MaximumValue, - 1 / this.MaximumValue, - 1F); + var scale = new Vector4( + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1 / this.MaximumValue, + 1F); for (int i = 0; i < result.Length; i++) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index 30dbdc896..adcb49bef 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -28,6 +28,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters new FromCmyk(8), new FromGrayscale(8), new FromRgb(8), + // 12-bit converters GetYCbCrConverter(12), new FromYccK(12), @@ -63,7 +64,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters private float MaximumValue { get; } /// - /// Gets the maximum value of a sample + /// Gets the half of the maximum value of a sample /// private float HalfValue { get; } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs index b034198cf..ad94572d9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs @@ -65,11 +65,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// Processes 'sourceBlock' producing Jpeg color channel values from spectral values: /// - Dequantize /// - Applying IDCT - /// - Level shift by +128, clip to [0, 255] + /// - Level shift by +maximumValue/2, clip to [0, maximumValue] /// - Copy the resulting color values into 'destArea' scaling up the block by amount defined in /// /// The source block. /// The destination buffer area. + /// The maximum value derived from the bitdepth. + public void ProcessBlockColorsInto( ref Block8x8 sourceBlock, in BufferArea destArea, diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index fb10425bd..c52858d4c 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// The only supported precision /// - public readonly int[] SupportedPrecisions = { 8, 12 }; + private readonly int[] supportedPrecisions = { 8, 12 }; /// /// The global configuration @@ -724,7 +724,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.InputStream.Read(this.temp, 0, remaining); // We only support 8-bit and 12-bit precision. - if (!this.SupportedPrecisions.Contains(this.temp[0])) + if (!this.supportedPrecisions.Contains(this.temp[0])) { throw new ImageFormatException("Only 8-Bit and 12-Bit precision supported."); } From 4636fe687f98edca2bb546a51db07171e70564af Mon Sep 17 00:00:00 2001 From: Stephan Vedder Date: Mon, 10 Dec 2018 23:40:26 +0100 Subject: [PATCH 005/223] Fix style issues --- .../Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs | 1 - .../Jpeg/Components/Decoder/JpegComponentPostProcessor.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs index ad94572d9..fe39f4188 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs @@ -71,7 +71,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// The source block. /// The destination buffer area. /// The maximum value derived from the bitdepth. - public void ProcessBlockColorsInto( ref Block8x8 sourceBlock, in BufferArea destArea, diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs index 66c9245a3..e7f3e4fda 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder public void CopyBlocksToColorBuffer() { var blockPp = new JpegBlockPostProcessor(this.ImagePostProcessor.RawJpeg, this.Component); - float maximumValue = (float)Math.Pow(2,this.ImagePostProcessor.RawJpeg.Precision) - 1; + float maximumValue = (float)Math.Pow(2, this.ImagePostProcessor.RawJpeg.Precision) - 1; for (int y = 0; y < this.BlockRowsPerStep; y++) { From 133c85489daa305a0c5db9662e070329d8c60989 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 21 Dec 2018 17:57:24 +1100 Subject: [PATCH 006/223] Minor optimizations --- .../ColorConverters/JpegColorConverter.cs | 6 ++---- .../Jpeg/Components/Decoder/IRawJpegData.cs | 2 +- .../Decoder/JpegImagePostProcessor.cs | 17 +++++++++++++---- src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs | 3 +-- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index adcb49bef..c2e390c59 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -3,12 +3,10 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Numerics; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Tuples; -using SixLabors.Memory; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { @@ -73,8 +71,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// public static JpegColorConverter GetConverter(JpegColorSpace colorSpace, float precision) { - JpegColorConverter converter = Converters.FirstOrDefault(c => c.ColorSpace == colorSpace && - c.Precision == precision); + JpegColorConverter converter = Array.Find(Converters, c => c.ColorSpace == colorSpace + && c.Precision == precision); if (converter is null) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs index 83d65c042..ace8d7215 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs @@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// /// Gets the components. /// - IEnumerable Components { get; } + IJpegComponent[] Components { get; } /// /// Gets the quantization tables, in zigzag order. diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs index 6b5995515..438749abf 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs @@ -3,7 +3,6 @@ using System; using System.Buffers; -using System.Linq; using System.Numerics; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; @@ -57,12 +56,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { this.configuration = configuration; this.RawJpeg = rawJpeg; - IJpegComponent c0 = rawJpeg.Components.First(); + IJpegComponent c0 = rawJpeg.Components[0]; this.NumberOfPostProcessorSteps = c0.SizeInBlocks.Height / BlockRowsPerStep; this.PostProcessorBufferSize = new Size(c0.SizeInBlocks.Width * 8, PixelRowsPerStep); MemoryAllocator memoryAllocator = configuration.MemoryAllocator; - this.ComponentProcessors = rawJpeg.Components.Select(c => new JpegComponentPostProcessor(memoryAllocator, this, c)).ToArray(); + + this.ComponentProcessors = new JpegComponentPostProcessor[rawJpeg.Components.Length]; + for (int i = 0; i < rawJpeg.Components.Length; i++) + { + this.ComponentProcessors[i] = new JpegComponentPostProcessor(memoryAllocator, this, rawJpeg.Components[i]); + } + this.rgbaBuffer = memoryAllocator.Allocate(rawJpeg.ImageSizeInPixels.Width); this.colorConverter = JpegColorConverter.GetConverter(rawJpeg.ColorSpace, rawJpeg.Precision); } @@ -152,7 +157,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { int maxY = Math.Min(destination.Height, this.PixelRowCounter + PixelRowsPerStep); - Buffer2D[] buffers = this.ComponentProcessors.Select(cp => cp.ColorBuffer).ToArray(); + var buffers = new Buffer2D[this.ComponentProcessors.Length]; + for (int i = 0; i < this.ComponentProcessors.Length; i++) + { + buffers[i] = this.ComponentProcessors[i].ColorBuffer; + } for (int yy = this.PixelRowCounter; yy < maxY; yy++) { diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index af6dfd9ec..02ae022e1 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -3,7 +3,6 @@ using System; using System.Buffers.Binary; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; @@ -169,7 +168,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg public JpegComponent[] Components => this.Frame.Components; /// - IEnumerable IRawJpegData.Components => this.Components; + IJpegComponent[] IRawJpegData.Components => this.Components; /// public Block8x8F[] QuantizationTables { get; private set; } From 537dbcf78bf83ef62c5be11fe8bd2db1c598867d Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 21 Dec 2018 18:13:19 +1100 Subject: [PATCH 007/223] Update reference images and decoder --- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 2 +- tests/Images/External | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 7452d6e49..e20f1514c 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -27,7 +27,7 @@ - + diff --git a/tests/Images/External b/tests/Images/External index 69603ee5b..7ada45bc3 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 69603ee5b6f7dd64114fc44d321e50d9b2d439be +Subproject commit 7ada45bc3484f40e28a50817386ca93f293acd11 From 575c23d929ff81b41d89ef3499125c1899ec2e72 Mon Sep 17 00:00:00 2001 From: Peter Amrehn Date: Fri, 4 Jan 2019 21:37:24 +0100 Subject: [PATCH 008/223] #797 throw ImageFormatException when no StartOfFrame marker is found on a jpg image. --- src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs | 5 +++++ .../Formats/Jpg/JpegDecoderTests.Baseline.cs | 8 ++++++++ tests/ImageSharp.Tests/TestImages.cs | 1 + .../Input/Jpg/issues/Issue797-InvalidImage.jpg | Bin 0 -> 381 bytes 4 files changed, 14 insertions(+) create mode 100644 tests/Images/Input/Jpg/issues/Issue797-InvalidImage.jpg diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 02ae022e1..936fc0631 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -292,6 +292,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg case JpegConstants.Markers.SOS: if (!metadataOnly) { + if (this.Frame is null) + { + throw new ImageFormatException("no readable SOF marker found."); + } + this.ProcessStartOfScanMarker(); break; } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs index 73167a4b7..a2f57e485 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs @@ -42,5 +42,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg // TODO: We need a public ImageDecoderException class in ImageSharp! Assert.ThrowsAny(() => provider.GetImage(JpegDecoder)); } + + [Theory] + [WithFile(TestImages.Jpeg.Issues.InvalidJpegThrowsWrongException797, PixelTypes.Rgba32)] + public void LoadingImage_InvalidTagLength_ShouldThrow(TestImageProvider provider) + where TPixel : struct, IPixel + { + Assert.Throws(() => provider.GetImage()); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 6141e9e2a..460aceba0 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -167,6 +167,7 @@ namespace SixLabors.ImageSharp.Tests public const string OrderedInterleavedProgressive723C = "Jpg/issues/Issue723-Ordered-Interleaved-Progressive-C.jpg"; public const string ExifGetString750Transform = "Jpg/issues/issue750-exif-tranform.jpg"; public const string ExifGetString750Load = "Jpg/issues/issue750-exif-load.jpg"; + public const string InvalidJpegThrowsWrongException797 = "Jpg/issues/Issue797-InvalidImage.jpg"; } public static readonly string[] All = Baseline.All.Concat(Progressive.All).ToArray(); diff --git a/tests/Images/Input/Jpg/issues/Issue797-InvalidImage.jpg b/tests/Images/Input/Jpg/issues/Issue797-InvalidImage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..560d77d47c05984d9ae0d66363a9a3e79e3373ad GIT binary patch literal 381 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8bv_u0R}-11_cHMW=16jCP7AKLB{__7{nPEm>C&R03#DKP(oFJk%5VU zm6?SZCJE#V3Mm?HbS#?0oS1Y`$tV!0ObqA~bp0Uh;)3WBj0}Q`|8Fty0Ig#ZWENzw zXSn_?G`CN4>Eu-#gDGyY6h9Jt=fiuimR&;j&k|?GIo1n54W_dVT2R+L!l=dHyr-2On+Q SzLjaZz2dbUF6{aLZvp^^Po>rX literal 0 HcmV?d00001 From 59d76a0f7b465c27330af6717df479146be3dda9 Mon Sep 17 00:00:00 2001 From: Peter Amrehn Date: Sat, 5 Jan 2019 00:45:43 +0100 Subject: [PATCH 009/223] #797 - apply review remarks --- src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 936fc0631..06c844d58 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -292,11 +292,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg case JpegConstants.Markers.SOS: if (!metadataOnly) { - if (this.Frame is null) - { - throw new ImageFormatException("no readable SOF marker found."); - } - this.ProcessStartOfScanMarker(); break; } @@ -864,6 +859,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// private void ProcessStartOfScanMarker() { + if (this.Frame is null) + { + throw new ImageFormatException("No readable SOFn (Start Of Frame) marker found."); + } + int selectorsCount = this.InputStream.ReadByte(); for (int i = 0; i < selectorsCount; i++) { From 93bb37394a484c03ba84d59d60e39f90677240c7 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 9 Jan 2019 01:16:37 +1100 Subject: [PATCH 010/223] Use bounds checks in Huffman ctr. Fix #798 --- .../Jpeg/Components/Decoder/HuffmanTable.cs | 23 ++++++++++-------- .../Formats/Jpg/JpegDecoderTests.Baseline.cs | 10 +++++--- tests/ImageSharp.Tests/TestImages.cs | 1 + .../Issue798-AccessViolationException.jpg | Bin 0 -> 381 bytes 4 files changed, 20 insertions(+), 14 deletions(-) create mode 100644 tests/Images/Input/Jpg/issues/Issue798-AccessViolationException.jpg diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs index 9e134746b..9e11981b1 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs @@ -50,8 +50,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// The huffman values public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan codeLengths, ReadOnlySpan values) { - const int Length = 257; - using (IMemoryOwner huffcode = memoryAllocator.Allocate(Length)) + // We do some bounds checks in the code here to protect against AccessViolationExceptions + const int HuffCodeLength = 257; + const int MaxSizeLength = HuffCodeLength - 1; + using (IMemoryOwner huffcode = memoryAllocator.Allocate(HuffCodeLength)) { ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.GetSpan()); ref byte codeLengthsRef = ref MemoryMarshal.GetReference(codeLengths); @@ -63,7 +65,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (short i = 1; i < 17; i++) { byte length = Unsafe.Add(ref codeLengthsRef, i); - for (short j = 0; j < length; j++) + for (short j = 0; j < length && x < MaxSizeLength; j++) { Unsafe.Add(ref sizesRef, x++) = i; } @@ -84,7 +86,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder Unsafe.Add(ref valOffsetRef, k) = (int)(si - code); if (Unsafe.Add(ref sizesRef, si) == k) { - while (Unsafe.Add(ref sizesRef, si) == k) + while (Unsafe.Add(ref sizesRef, si) == k && si < HuffCodeLength) { Unsafe.Add(ref huffcodeRef, si++) = (short)code++; } @@ -100,19 +102,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder // Generate non-spec lookup tables to speed up decoding. const int FastBits = ScanDecoder.FastBits; - ref byte fastRef = ref this.Lookahead[0]; - Unsafe.InitBlockUnaligned(ref fastRef, 0xFF, 1 << FastBits); // Flag for non-accelerated + ref byte lookaheadRef = ref this.Lookahead[0]; + const uint MaxFastLength = 1 << FastBits; + Unsafe.InitBlockUnaligned(ref lookaheadRef, 0xFF, MaxFastLength); // Flag for non-accelerated for (int i = 0; i < si; i++) { int size = Unsafe.Add(ref sizesRef, i); if (size <= FastBits) { - int c = Unsafe.Add(ref huffcodeRef, i) << (FastBits - size); - int m = 1 << (FastBits - size); - for (int l = 0; l < m; l++) + int huffCode = Unsafe.Add(ref huffcodeRef, i) << (FastBits - size); + int max = 1 << (FastBits - size); + for (int left = 0; left < max; left++) { - Unsafe.Add(ref fastRef, c + l) = (byte)i; + Unsafe.Add(ref lookaheadRef, huffCode + left) = (byte)i; } } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs index a2f57e485..1c9d207cd 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs @@ -46,9 +46,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Theory] [WithFile(TestImages.Jpeg.Issues.InvalidJpegThrowsWrongException797, PixelTypes.Rgba32)] public void LoadingImage_InvalidTagLength_ShouldThrow(TestImageProvider provider) - where TPixel : struct, IPixel - { - Assert.Throws(() => provider.GetImage()); - } + where TPixel : struct, IPixel => Assert.Throws(() => provider.GetImage()); + + [Theory] + [WithFile(TestImages.Jpeg.Issues.AccessViolationException798, PixelTypes.Rgba32)] + public void LoadingImage_BadHuffman_ShouldNotThrow(TestImageProvider provider) + where TPixel : struct, IPixel => Assert.NotNull(provider.GetImage()); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 460aceba0..8d8a32fba 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -168,6 +168,7 @@ namespace SixLabors.ImageSharp.Tests public const string ExifGetString750Transform = "Jpg/issues/issue750-exif-tranform.jpg"; public const string ExifGetString750Load = "Jpg/issues/issue750-exif-load.jpg"; public const string InvalidJpegThrowsWrongException797 = "Jpg/issues/Issue797-InvalidImage.jpg"; + public const string AccessViolationException798 = "Jpg/issues/Issue798-AccessViolationException.jpg"; } public static readonly string[] All = Baseline.All.Concat(Progressive.All).ToArray(); diff --git a/tests/Images/Input/Jpg/issues/Issue798-AccessViolationException.jpg b/tests/Images/Input/Jpg/issues/Issue798-AccessViolationException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..30f61c86305f4533b01e93287ff68ca4f96aa62a GIT binary patch literal 381 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIfxk7gYRzi-8Ad9Frik zAcH-_^>3lMeVR)ruPRBLe(zrX9qr9`^CCVn2G+N1%X+iv_wBR4JEKh9Zrw25^y&0A zrjlS8weov&pBq|l4Nu>7XXETip^JL;UhN8(z1nSm_{zs5<*m}|Lnqh1yjRTgpMgL4 UXxsL!Ow;WZukCPQ&;NfD0NVq=R{#J2 literal 0 HcmV?d00001 From b74e230671356be531125a06e4791761b8d68e10 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 18 Jan 2019 07:58:54 +1100 Subject: [PATCH 011/223] Fix Color Filters (#806) * Use Matrix5x4 and fix Hue Filter * Update test references. Fix #802 * Increase tolerance to handle xplat variance. * Rename to ColorMatrix --- src/ImageSharp/Common/Helpers/Vector4Utils.cs | 37 ++ src/ImageSharp/Primitives/ColorMatrix.cs | 459 ++++++++++++++++++ src/ImageSharp/Processing/FilterExtensions.cs | 6 +- .../Processing/KnownFilterMatrices.cs | 358 +++++++------- .../Processors/Filters/FilterProcessor.cs | 36 +- .../Formats/GeneralFormatTests.cs | 3 +- .../Helpers/Vector4UtilsTests.cs | 6 +- .../Primitives/ColorMatrixTests.cs | 270 +++++++++++ .../Processors/Filters/BrightnessTest.cs | 8 +- .../Processors/Filters/ColorBlindnessTest.cs | 9 +- .../Processors/Filters/FilterTest.cs | 20 +- .../TestUtilities/ApproximateFloatComparer.cs | 28 +- tests/Images/External | 2 +- 13 files changed, 1017 insertions(+), 225 deletions(-) create mode 100644 src/ImageSharp/Primitives/ColorMatrix.cs create mode 100644 tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs diff --git a/src/ImageSharp/Common/Helpers/Vector4Utils.cs b/src/ImageSharp/Common/Helpers/Vector4Utils.cs index 75bb00b6a..5c122217d 100644 --- a/src/ImageSharp/Common/Helpers/Vector4Utils.cs +++ b/src/ImageSharp/Common/Helpers/Vector4Utils.cs @@ -5,6 +5,7 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using SixLabors.ImageSharp.Primitives; namespace SixLabors.ImageSharp { @@ -70,5 +71,41 @@ namespace SixLabors.ImageSharp UnPremultiply(ref v); } } + + /// + /// Transforms a vector by the given matrix. + /// + /// The source vector. + /// The transformation matrix. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Transform(ref Vector4 vector, ref ColorMatrix matrix) + { + float x = vector.X; + float y = vector.Y; + float z = vector.Z; + float w = vector.W; + + vector.X = (x * matrix.M11) + (y * matrix.M21) + (z * matrix.M31) + (w * matrix.M41) + matrix.M51; + vector.Y = (x * matrix.M12) + (y * matrix.M22) + (z * matrix.M32) + (w * matrix.M42) + matrix.M52; + vector.Z = (x * matrix.M13) + (y * matrix.M23) + (z * matrix.M33) + (w * matrix.M43) + matrix.M53; + vector.W = (x * matrix.M14) + (y * matrix.M24) + (z * matrix.M34) + (w * matrix.M44) + matrix.M54; + } + + /// + /// Bulk variant of + /// + /// The span of vectors + /// The transformation matrix. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Transform(Span vectors, ref ColorMatrix matrix) + { + ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); + + for (int i = 0; i < vectors.Length; i++) + { + ref Vector4 v = ref Unsafe.Add(ref baseRef, i); + Transform(ref v, ref matrix); + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/Primitives/ColorMatrix.cs b/src/ImageSharp/Primitives/ColorMatrix.cs new file mode 100644 index 000000000..af2e9465a --- /dev/null +++ b/src/ImageSharp/Primitives/ColorMatrix.cs @@ -0,0 +1,459 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +#pragma warning disable SA1117 // Parameters should be on same line or separate lines +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp.Primitives +{ + /// + /// A structure encapsulating a 5x4 matrix used for transforming the color and alpha components of an image. + /// + [StructLayout(LayoutKind.Sequential)] + public struct ColorMatrix : IEquatable + { + /// + /// Value at row 1, column 1 of the matrix. + /// + public float M11; + + /// + /// Value at row 1, column 2 of the matrix. + /// + public float M12; + + /// + /// Value at row 1, column 3 of the matrix. + /// + public float M13; + + /// + /// Value at row 1, column 4 of the matrix. + /// + public float M14; + + /// + /// Value at row 2, column 1 of the matrix. + /// + public float M21; + + /// + /// Value at row 2, column 2 of the matrix. + /// + public float M22; + + /// + /// Value at row 2, column 3 of the matrix. + /// + public float M23; + + /// + /// Value at row 2, column 4 of the matrix. + /// + public float M24; + + /// + /// Value at row 3, column 1 of the matrix. + /// + public float M31; + + /// + /// Value at row 3, column 2 of the matrix. + /// + public float M32; + + /// + /// Value at row 3, column 3 of the matrix. + /// + public float M33; + + /// + /// Value at row 3, column 4 of the matrix. + /// + public float M34; + + /// + /// Value at row 4, column 1 of the matrix. + /// + public float M41; + + /// + /// Value at row 4, column 2 of the matrix. + /// + public float M42; + + /// + /// Value at row 4, column 3 of the matrix. + /// + public float M43; + + /// + /// Value at row 4, column 4 of the matrix. + /// + public float M44; + + /// + /// Value at row 5, column 1 of the matrix. + /// + public float M51; + + /// + /// Value at row 5, column 2 of the matrix. + /// + public float M52; + + /// + /// Value at row 5, column 3 of the matrix. + /// + public float M53; + + /// + /// Value at row 5, column 4 of the matrix. + /// + public float M54; + + /// + /// Initializes a new instance of the struct. + /// + /// The value at row 1, column 1 of the matrix. + /// The value at row 1, column 2 of the matrix. + /// The value at row 1, column 3 of the matrix. + /// The value at row 1, column 4 of the matrix. + /// The value at row 2, column 1 of the matrix. + /// The value at row 2, column 2 of the matrix. + /// The value at row 2, column 3 of the matrix. + /// The value at row 2, column 4 of the matrix. + /// The value at row 3, column 1 of the matrix. + /// The value at row 3, column 2 of the matrix. + /// The value at row 3, column 3 of the matrix. + /// The value at row 3, column 4 of the matrix. + /// The value at row 4, column 1 of the matrix. + /// The value at row 4, column 2 of the matrix. + /// The value at row 4, column 3 of the matrix. + /// The value at row 4, column 4 of the matrix. + /// The value at row 5, column 1 of the matrix. + /// The value at row 5, column 2 of the matrix. + /// The value at row 5, column 3 of the matrix. + /// The value at row 5, column 4 of the matrix. + public ColorMatrix(float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44, + float m51, float m52, float m53, float m54) + { + this.M11 = m11; + this.M12 = m12; + this.M13 = m13; + this.M14 = m14; + + this.M21 = m21; + this.M22 = m22; + this.M23 = m23; + this.M24 = m24; + + this.M31 = m31; + this.M32 = m32; + this.M33 = m33; + this.M34 = m34; + + this.M41 = m41; + this.M42 = m42; + this.M43 = m43; + this.M44 = m44; + + this.M51 = m51; + this.M52 = m52; + this.M53 = m53; + this.M54 = m54; + } + + /// + /// Gets the multiplicative identity matrix. + /// + public static ColorMatrix Identity { get; } = + new ColorMatrix(1F, 0F, 0F, 0F, + 0F, 1F, 0F, 0F, + 0F, 0F, 1F, 0F, + 0F, 0F, 0F, 1F, + 0F, 0F, 0F, 0F); + + /// + /// Gets a value indicating whether the matrix is the identity matrix. + /// + public bool IsIdentity + { + get + { + // Check diagonal element first for early out. + return this.M11 == 1F && this.M22 == 1F && this.M33 == 1F && this.M44 == 1F + && this.M12 == 0F && this.M13 == 0F && this.M14 == 0F + && this.M21 == 0F && this.M23 == 0F && this.M24 == 0F + && this.M31 == 0F && this.M32 == 0F && this.M34 == 0F + && this.M41 == 0F && this.M42 == 0F && this.M43 == 0F + && this.M51 == 0F && this.M52 == 0F && this.M53 == 0F && this.M54 == 0F; + } + } + + /// + /// Adds two matrices together. + /// + /// The first source matrix. + /// The second source matrix. + /// The resulting matrix. + public static ColorMatrix operator +(ColorMatrix value1, ColorMatrix value2) + { + ColorMatrix m; + + m.M11 = value1.M11 + value2.M11; + m.M12 = value1.M12 + value2.M12; + m.M13 = value1.M13 + value2.M13; + m.M14 = value1.M14 + value2.M14; + m.M21 = value1.M21 + value2.M21; + m.M22 = value1.M22 + value2.M22; + m.M23 = value1.M23 + value2.M23; + m.M24 = value1.M24 + value2.M24; + m.M31 = value1.M31 + value2.M31; + m.M32 = value1.M32 + value2.M32; + m.M33 = value1.M33 + value2.M33; + m.M34 = value1.M34 + value2.M34; + m.M41 = value1.M41 + value2.M41; + m.M42 = value1.M42 + value2.M42; + m.M43 = value1.M43 + value2.M43; + m.M44 = value1.M44 + value2.M44; + m.M51 = value1.M51 + value2.M51; + m.M52 = value1.M52 + value2.M52; + m.M53 = value1.M53 + value2.M53; + m.M54 = value1.M54 + value2.M54; + + return m; + } + + /// + /// Subtracts the second matrix from the first. + /// + /// The first source matrix. + /// The second source matrix. + /// The result of the subtraction. + public static ColorMatrix operator -(ColorMatrix value1, ColorMatrix value2) + { + ColorMatrix m; + + m.M11 = value1.M11 - value2.M11; + m.M12 = value1.M12 - value2.M12; + m.M13 = value1.M13 - value2.M13; + m.M14 = value1.M14 - value2.M14; + m.M21 = value1.M21 - value2.M21; + m.M22 = value1.M22 - value2.M22; + m.M23 = value1.M23 - value2.M23; + m.M24 = value1.M24 - value2.M24; + m.M31 = value1.M31 - value2.M31; + m.M32 = value1.M32 - value2.M32; + m.M33 = value1.M33 - value2.M33; + m.M34 = value1.M34 - value2.M34; + m.M41 = value1.M41 - value2.M41; + m.M42 = value1.M42 - value2.M42; + m.M43 = value1.M43 - value2.M43; + m.M44 = value1.M44 - value2.M44; + m.M51 = value1.M51 - value2.M51; + m.M52 = value1.M52 - value2.M52; + m.M53 = value1.M53 - value2.M53; + m.M54 = value1.M54 - value2.M54; + + return m; + } + + /// + /// Returns a new matrix with the negated elements of the given matrix. + /// + /// The source matrix. + /// The negated matrix. + public static unsafe ColorMatrix operator -(ColorMatrix value) + { + ColorMatrix m; + + m.M11 = -value.M11; + m.M12 = -value.M12; + m.M13 = -value.M13; + m.M14 = -value.M14; + m.M21 = -value.M21; + m.M22 = -value.M22; + m.M23 = -value.M23; + m.M24 = -value.M24; + m.M31 = -value.M31; + m.M32 = -value.M32; + m.M33 = -value.M33; + m.M34 = -value.M34; + m.M41 = -value.M41; + m.M42 = -value.M42; + m.M43 = -value.M43; + m.M44 = -value.M44; + m.M51 = -value.M51; + m.M52 = -value.M52; + m.M53 = -value.M53; + m.M54 = -value.M54; + + return m; + } + + /// + /// Multiplies a matrix by another matrix. + /// + /// The first source matrix. + /// The second source matrix. + /// The result of the multiplication. + public static ColorMatrix operator *(ColorMatrix value1, ColorMatrix value2) + { + ColorMatrix m; + + // First row + m.M11 = (value1.M11 * value2.M11) + (value1.M12 * value2.M21) + (value1.M13 * value2.M31) + (value1.M14 * value2.M41); + m.M12 = (value1.M11 * value2.M12) + (value1.M12 * value2.M22) + (value1.M13 * value2.M32) + (value1.M14 * value2.M42); + m.M13 = (value1.M11 * value2.M13) + (value1.M12 * value2.M23) + (value1.M13 * value2.M33) + (value1.M14 * value2.M43); + m.M14 = (value1.M11 * value2.M14) + (value1.M12 * value2.M24) + (value1.M13 * value2.M34) + (value1.M14 * value2.M44); + + // Second row + m.M21 = (value1.M21 * value2.M11) + (value1.M22 * value2.M21) + (value1.M23 * value2.M31) + (value1.M24 * value2.M41); + m.M22 = (value1.M21 * value2.M12) + (value1.M22 * value2.M22) + (value1.M23 * value2.M32) + (value1.M24 * value2.M42); + m.M23 = (value1.M21 * value2.M13) + (value1.M22 * value2.M23) + (value1.M23 * value2.M33) + (value1.M24 * value2.M43); + m.M24 = (value1.M21 * value2.M14) + (value1.M22 * value2.M24) + (value1.M23 * value2.M34) + (value1.M24 * value2.M44); + + // Third row + m.M31 = (value1.M31 * value2.M11) + (value1.M32 * value2.M21) + (value1.M33 * value2.M31) + (value1.M34 * value2.M41); + m.M32 = (value1.M31 * value2.M12) + (value1.M32 * value2.M22) + (value1.M33 * value2.M32) + (value1.M34 * value2.M42); + m.M33 = (value1.M31 * value2.M13) + (value1.M32 * value2.M23) + (value1.M33 * value2.M33) + (value1.M34 * value2.M43); + m.M34 = (value1.M31 * value2.M14) + (value1.M32 * value2.M24) + (value1.M33 * value2.M34) + (value1.M34 * value2.M44); + + // Fourth row + m.M41 = (value1.M41 * value2.M11) + (value1.M42 * value2.M21) + (value1.M43 * value2.M31) + (value1.M44 * value2.M41); + m.M42 = (value1.M41 * value2.M12) + (value1.M42 * value2.M22) + (value1.M43 * value2.M32) + (value1.M44 * value2.M42); + m.M43 = (value1.M41 * value2.M13) + (value1.M42 * value2.M23) + (value1.M43 * value2.M33) + (value1.M44 * value2.M43); + m.M44 = (value1.M41 * value2.M14) + (value1.M42 * value2.M24) + (value1.M43 * value2.M34) + (value1.M44 * value2.M44); + + // Fifth row + m.M51 = (value1.M51 * value2.M11) + (value1.M52 * value2.M21) + (value1.M53 * value2.M31) + (value1.M54 * value2.M41) + value2.M51; + m.M52 = (value1.M51 * value2.M12) + (value1.M52 * value2.M22) + (value1.M53 * value2.M32) + (value1.M54 * value2.M52) + value2.M52; + m.M53 = (value1.M51 * value2.M13) + (value1.M52 * value2.M23) + (value1.M53 * value2.M33) + (value1.M54 * value2.M53) + value2.M53; + m.M54 = (value1.M51 * value2.M14) + (value1.M52 * value2.M24) + (value1.M53 * value2.M34) + (value1.M54 * value2.M54) + value2.M54; + + return m; + } + + /// + /// Multiplies a matrix by a scalar value. + /// + /// The source matrix. + /// The scaling factor. + /// The scaled matrix. + public static ColorMatrix operator *(ColorMatrix value1, float value2) + { + ColorMatrix m; + + m.M11 = value1.M11 * value2; + m.M12 = value1.M12 * value2; + m.M13 = value1.M13 * value2; + m.M14 = value1.M14 * value2; + m.M21 = value1.M21 * value2; + m.M22 = value1.M22 * value2; + m.M23 = value1.M23 * value2; + m.M24 = value1.M24 * value2; + m.M31 = value1.M31 * value2; + m.M32 = value1.M32 * value2; + m.M33 = value1.M33 * value2; + m.M34 = value1.M34 * value2; + m.M41 = value1.M41 * value2; + m.M42 = value1.M42 * value2; + m.M43 = value1.M43 * value2; + m.M44 = value1.M44 * value2; + m.M51 = value1.M51 * value2; + m.M52 = value1.M52 * value2; + m.M53 = value1.M53 * value2; + m.M54 = value1.M54 * value2; + + return m; + } + + /// + /// Returns a boolean indicating whether the given two matrices are equal. + /// + /// The first matrix to compare. + /// The second matrix to compare. + /// True if the given matrices are equal; False otherwise. + public static bool operator ==(ColorMatrix value1, ColorMatrix value2) => value1.Equals(value2); + + /// + /// Returns a boolean indicating whether the given two matrices are not equal. + /// + /// The first matrix to compare. + /// The second matrix to compare. + /// True if the given matrices are equal; False otherwise. + public static bool operator !=(ColorMatrix value1, ColorMatrix value2) => !value1.Equals(value2); + + /// + public override bool Equals(object obj) => obj is ColorMatrix matrix && this.Equals(matrix); + + /// + public bool Equals(ColorMatrix other) => + this.M11 == other.M11 + && this.M12 == other.M12 + && this.M13 == other.M13 + && this.M14 == other.M14 + && this.M21 == other.M21 + && this.M22 == other.M22 + && this.M23 == other.M23 + && this.M24 == other.M24 + && this.M31 == other.M31 + && this.M32 == other.M32 + && this.M33 == other.M33 + && this.M34 == other.M34 + && this.M41 == other.M41 + && this.M42 == other.M42 + && this.M43 == other.M43 + && this.M44 == other.M44 + && this.M51 == other.M51 + && this.M52 == other.M52 + && this.M53 == other.M53 + && this.M54 == other.M54; + + /// + public override int GetHashCode() + { + HashCode hash = default; + hash.Add(this.M11); + hash.Add(this.M12); + hash.Add(this.M13); + hash.Add(this.M14); + hash.Add(this.M21); + hash.Add(this.M22); + hash.Add(this.M23); + hash.Add(this.M24); + hash.Add(this.M31); + hash.Add(this.M32); + hash.Add(this.M33); + hash.Add(this.M34); + hash.Add(this.M41); + hash.Add(this.M42); + hash.Add(this.M43); + hash.Add(this.M44); + hash.Add(this.M51); + hash.Add(this.M52); + hash.Add(this.M53); + hash.Add(this.M54); + return hash.ToHashCode(); + } + + /// + public override string ToString() + { + CultureInfo ci = CultureInfo.CurrentCulture; + + return string.Format(ci, "{{ {{M11:{0} M12:{1} M13:{2} M14:{3}}} {{M21:{4} M22:{5} M23:{6} M24:{7}}} {{M31:{8} M32:{9} M33:{10} M34:{11}}} {{M41:{12} M42:{13} M43:{14} M44:{15}}} {{M51:{16} M52:{17} M53:{18} M54:{19}}} }}", + this.M11.ToString(ci), this.M12.ToString(ci), this.M13.ToString(ci), this.M14.ToString(ci), + this.M21.ToString(ci), this.M22.ToString(ci), this.M23.ToString(ci), this.M24.ToString(ci), + this.M31.ToString(ci), this.M32.ToString(ci), this.M33.ToString(ci), this.M34.ToString(ci), + this.M41.ToString(ci), this.M42.ToString(ci), this.M43.ToString(ci), this.M44.ToString(ci), + this.M51.ToString(ci), this.M52.ToString(ci), this.M53.ToString(ci), this.M54.ToString(ci)); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/FilterExtensions.cs b/src/ImageSharp/Processing/FilterExtensions.cs index bfae4ae65..70ac23286 100644 --- a/src/ImageSharp/Processing/FilterExtensions.cs +++ b/src/ImageSharp/Processing/FilterExtensions.cs @@ -1,8 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Numerics; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing.Processors.Filters; using SixLabors.Primitives; @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The filter color matrix /// The . - public static IImageProcessingContext Filter(this IImageProcessingContext source, Matrix4x4 matrix) + public static IImageProcessingContext Filter(this IImageProcessingContext source, ColorMatrix matrix) where TPixel : struct, IPixel => source.ApplyProcessor(new FilterProcessor(matrix)); @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Filter(this IImageProcessingContext source, Matrix4x4 matrix, Rectangle rectangle) + public static IImageProcessingContext Filter(this IImageProcessingContext source, ColorMatrix matrix, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new FilterProcessor(matrix), rectangle); } diff --git a/src/ImageSharp/Processing/KnownFilterMatrices.cs b/src/ImageSharp/Processing/KnownFilterMatrices.cs index cf0d19ff8..9c725d027 100644 --- a/src/ImageSharp/Processing/KnownFilterMatrices.cs +++ b/src/ImageSharp/Processing/KnownFilterMatrices.cs @@ -2,19 +2,28 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Numerics; - +using SixLabors.ImageSharp.Primitives; + +// Many of these matrices are tranlated from Chromium project where +// SkScalar[] is memory-mapped to a row-major matrix. +// The following translates to our column-major form: +// +// | 0| 1| 2| 3| 4| |0|5|10|15| |M11|M12|M13|M14| +// | 5| 6| 7| 8| 9| |1|6|11|16| |M21|M22|M23|M24| +// |10|11|12|13|14| = |2|7|12|17| = |M31|M32|M33|M34| +// |15|16|17|18|19| |3|8|13|18| |M41|M42|M43|M44| +// |4|9|14|19| |M51|M52|M53|M54| namespace SixLabors.ImageSharp.Processing { /// - /// A collection of known values for composing filters + /// A collection of known values for composing filters /// public static class KnownFilterMatrices { /// /// Gets a filter recreating Achromatomaly (Color desensitivity) color blindness /// - public static Matrix4x4 AchromatomalyFilter { get; } = new Matrix4x4 + public static ColorMatrix AchromatomalyFilter { get; } = new ColorMatrix { M11 = .618F, M12 = .163F, @@ -31,7 +40,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets a filter recreating Achromatopsia (Monochrome) color blindness. /// - public static Matrix4x4 AchromatopsiaFilter { get; } = new Matrix4x4 + public static ColorMatrix AchromatopsiaFilter { get; } = new ColorMatrix { M11 = .299F, M12 = .299F, @@ -42,97 +51,97 @@ namespace SixLabors.ImageSharp.Processing M31 = .114F, M32 = .114F, M33 = .114F, - M44 = 1 + M44 = 1F }; /// /// Gets a filter recreating Deuteranomaly (Green-Weak) color blindness. /// - public static Matrix4x4 DeuteranomalyFilter { get; } = new Matrix4x4 + public static ColorMatrix DeuteranomalyFilter { get; } = new ColorMatrix { - M11 = 0.8F, - M12 = 0.258F, - M21 = 0.2F, - M22 = 0.742F, - M23 = 0.142F, - M33 = 0.858F, - M44 = 1 + M11 = .8F, + M12 = .258F, + M21 = .2F, + M22 = .742F, + M23 = .142F, + M33 = .858F, + M44 = 1F }; /// /// Gets a filter recreating Deuteranopia (Green-Blind) color blindness. /// - public static Matrix4x4 DeuteranopiaFilter { get; } = new Matrix4x4 + public static ColorMatrix DeuteranopiaFilter { get; } = new ColorMatrix { - M11 = 0.625F, - M12 = 0.7F, - M21 = 0.375F, - M22 = 0.3F, - M23 = 0.3F, - M33 = 0.7F, - M44 = 1 + M11 = .625F, + M12 = .7F, + M21 = .375F, + M22 = .3F, + M23 = .3F, + M33 = .7F, + M44 = 1F }; /// /// Gets a filter recreating Protanomaly (Red-Weak) color blindness. /// - public static Matrix4x4 ProtanomalyFilter { get; } = new Matrix4x4 + public static ColorMatrix ProtanomalyFilter { get; } = new ColorMatrix { - M11 = 0.817F, - M12 = 0.333F, - M21 = 0.183F, - M22 = 0.667F, - M23 = 0.125F, - M33 = 0.875F, - M44 = 1 + M11 = .817F, + M12 = .333F, + M21 = .183F, + M22 = .667F, + M23 = .125F, + M33 = .875F, + M44 = 1F }; /// /// Gets a filter recreating Protanopia (Red-Blind) color blindness. /// - public static Matrix4x4 ProtanopiaFilter { get; } = new Matrix4x4 + public static ColorMatrix ProtanopiaFilter { get; } = new ColorMatrix { - M11 = 0.567F, - M12 = 0.558F, - M21 = 0.433F, - M22 = 0.442F, - M23 = 0.242F, - M33 = 0.758F, - M44 = 1 + M11 = .567F, + M12 = .558F, + M21 = .433F, + M22 = .442F, + M23 = .242F, + M33 = .758F, + M44 = 1F }; /// /// Gets a filter recreating Tritanomaly (Blue-Weak) color blindness. /// - public static Matrix4x4 TritanomalyFilter { get; } = new Matrix4x4 + public static ColorMatrix TritanomalyFilter { get; } = new ColorMatrix { - M11 = 0.967F, - M21 = 0.33F, - M22 = 0.733F, - M23 = 0.183F, - M32 = 0.267F, - M33 = 0.817F, - M44 = 1 + M11 = .967F, + M21 = .33F, + M22 = .733F, + M23 = .183F, + M32 = .267F, + M33 = .817F, + M44 = 1F }; /// /// Gets a filter recreating Tritanopia (Blue-Blind) color blindness. /// - public static Matrix4x4 TritanopiaFilter { get; } = new Matrix4x4 + public static ColorMatrix TritanopiaFilter { get; } = new ColorMatrix { - M11 = 0.95F, - M21 = 0.05F, - M22 = 0.433F, - M23 = 0.475F, - M32 = 0.567F, - M33 = 0.525F, - M44 = 1 + M11 = .95F, + M21 = .05F, + M22 = .433F, + M23 = .475F, + M32 = .567F, + M33 = .525F, + M44 = 1F }; /// /// Gets an approximated black and white filter /// - public static Matrix4x4 BlackWhiteFilter { get; } = new Matrix4x4() + public static ColorMatrix BlackWhiteFilter { get; } = new ColorMatrix() { M11 = 1.5F, M12 = 1.5F, @@ -143,24 +152,24 @@ namespace SixLabors.ImageSharp.Processing M31 = 1.5F, M32 = 1.5F, M33 = 1.5F, - M41 = -1F, - M42 = -1F, - M43 = -1F, - M44 = 1 + M44 = 1F, + M51 = -1F, + M52 = -1F, + M53 = -1F, }; /// /// Gets a filter recreating an old Kodachrome camera effect. /// - public static Matrix4x4 KodachromeFilter { get; } = new Matrix4x4 + public static ColorMatrix KodachromeFilter { get; } = new ColorMatrix { - M11 = 0.7297023F, - M22 = 0.6109577F, - M33 = 0.597218F, - M41 = 0.105F, - M42 = 0.145F, - M43 = 0.155F, - M44 = 1 + M11 = .7297023F, + M22 = .6109577F, + M33 = .597218F, + M44 = 1F, + M51 = .105F, + M52 = .145F, + M53 = .155F, } * CreateSaturateFilter(1.2F) * CreateContrastFilter(1.35F); @@ -168,15 +177,15 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets a filter recreating an old Lomograph camera effect. /// - public static Matrix4x4 LomographFilter { get; } = new Matrix4x4 + public static ColorMatrix LomographFilter { get; } = new ColorMatrix { M11 = 1.5F, M22 = 1.45F, M33 = 1.16F, - M41 = -.1F, - M42 = -.02F, - M43 = -.07F, - M44 = 1 + M44 = 1F, + M51 = -.1F, + M52 = -.02F, + M53 = -.07F, } * CreateSaturateFilter(1.1F) * CreateContrastFilter(1.33F); @@ -184,21 +193,21 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets a filter recreating an old Polaroid camera effect. /// - public static Matrix4x4 PolaroidFilter { get; } = new Matrix4x4 + public static ColorMatrix PolaroidFilter { get; } = new ColorMatrix { M11 = 1.538F, - M12 = -0.062F, - M13 = -0.262F, - M21 = -0.022F, + M12 = -.062F, + M13 = -.262F, + M21 = -.022F, M22 = 1.578F, - M23 = -0.022F, + M23 = -.022F, M31 = .216F, M32 = -.16F, M33 = 1.5831F, - M41 = 0.02F, - M42 = -0.05F, - M43 = -0.05F, - M44 = 1 + M44 = 1F, + M51 = .02F, + M52 = -.05F, + M53 = -.05F }; /// @@ -209,18 +218,18 @@ namespace SixLabors.ImageSharp.Processing /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing brighter results. /// /// The proportion of the conversion. Must be greater than or equal to 0. - /// The - public static Matrix4x4 CreateBrightnessFilter(float amount) + /// The + public static ColorMatrix CreateBrightnessFilter(float amount) { Guard.MustBeGreaterThanOrEqualTo(amount, 0, nameof(amount)); // See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc - return new Matrix4x4 + return new ColorMatrix { M11 = amount, M22 = amount, M33 = amount, - M44 = 1 + M44 = 1F }; } @@ -232,23 +241,23 @@ namespace SixLabors.ImageSharp.Processing /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing results with more contrast. /// /// The proportion of the conversion. Must be greater than or equal to 0. - /// The - public static Matrix4x4 CreateContrastFilter(float amount) + /// The + public static ColorMatrix CreateContrastFilter(float amount) { Guard.MustBeGreaterThanOrEqualTo(amount, 0, nameof(amount)); // See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc float contrast = (-.5F * amount) + .5F; - return new Matrix4x4 + return new ColorMatrix { M11 = amount, M22 = amount, M33 = amount, - M41 = contrast, - M42 = contrast, - M43 = contrast, - M44 = 1 + M44 = 1F, + M51 = contrast, + M52 = contrast, + M53 = contrast }; } @@ -257,26 +266,27 @@ namespace SixLabors.ImageSharp.Processing /// /// /// The proportion of the conversion. Must be between 0 and 1. - /// The - public static Matrix4x4 CreateGrayscaleBt601Filter(float amount) + /// The + public static ColorMatrix CreateGrayscaleBt601Filter(float amount) { - Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); + Guard.MustBeBetweenOrEqualTo(amount, 0, 1F, nameof(amount)); amount = 1F - amount; - // https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc - return new Matrix4x4 - { - M11 = .299F + (.701F * amount), - M12 = .299F - (.299F * amount), - M13 = .299F - (.299F * amount), - M21 = .587F - (.587F * amount), - M22 = .587F + (.413F * amount), - M23 = .587F - (.587F * amount), - M31 = .114F - (.114F * amount), - M32 = .114F - (.114F * amount), - M33 = .114F + (.886F * amount), - M44 = 1 - }; + ColorMatrix m = default; + m.M11 = .299F + (.701F * amount); + m.M21 = .587F - (.587F * amount); + m.M31 = 1F - (m.M11 + m.M21); + + m.M12 = .299F - (.299F * amount); + m.M22 = .587F + (.2848F * amount); + m.M32 = 1F - (m.M12 + m.M22); + + m.M13 = .299F - (.299F * amount); + m.M23 = .587F - (.587F * amount); + m.M33 = 1F - (m.M13 + m.M23); + m.M44 = 1F; + + return m; } /// @@ -284,34 +294,36 @@ namespace SixLabors.ImageSharp.Processing /// /// /// The proportion of the conversion. Must be between 0 and 1. - /// The - public static Matrix4x4 CreateGrayscaleBt709Filter(float amount) + /// The + public static ColorMatrix CreateGrayscaleBt709Filter(float amount) { - Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); + Guard.MustBeBetweenOrEqualTo(amount, 0, 1F, nameof(amount)); amount = 1F - amount; // https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc - return new Matrix4x4 - { - M11 = .2126F + (.7874F * amount), - M12 = .2126F - (.2126F * amount), - M13 = .2126F - (.2126F * amount), - M21 = .7152F - (.7152F * amount), - M22 = .7152F + (.2848F * amount), - M23 = .7152F - (.7152F * amount), - M31 = .0722F - (.0722F * amount), - M32 = .0722F - (.0722F * amount), - M33 = .0722F + (.9278F * amount), - M44 = 1 - }; + ColorMatrix m = default; + m.M11 = .2126F + (.7874F * amount); + m.M21 = .7152F - (.7152F * amount); + m.M31 = 1F - (m.M11 + m.M21); + + m.M12 = .2126F - (.2126F * amount); + m.M22 = .7152F + (.2848F * amount); + m.M32 = 1F - (m.M12 + m.M22); + + m.M13 = .2126F - (.2126F * amount); + m.M23 = .7152F - (.7152F * amount); + m.M33 = 1F - (m.M13 + m.M23); + m.M44 = 1F; + + return m; } /// /// Create a hue filter matrix using the given angle in degrees. /// /// The angle of rotation in degrees. - /// The - public static Matrix4x4 CreateHueFilter(float degrees) + /// The + public static ColorMatrix CreateHueFilter(float degrees) { // Wrap the angle round at 360. degrees %= 360; @@ -329,18 +341,20 @@ namespace SixLabors.ImageSharp.Processing // The matrix is set up to preserve the luminance of the image. // See http://graficaobscura.com/matrix/index.html // Number are taken from https://msdn.microsoft.com/en-us/library/jj192162(v=vs.85).aspx - return new Matrix4x4 + return new ColorMatrix { M11 = .213F + (cosRadian * .787F) - (sinRadian * .213F), - M12 = .213F - (cosRadian * .213F) - (sinRadian * 0.143F), - M13 = .213F - (cosRadian * .213F) - (sinRadian * .787F), M21 = .715F - (cosRadian * .715F) - (sinRadian * .715F), - M22 = .715F + (cosRadian * .285F) + (sinRadian * 0.140F), - M23 = .715F - (cosRadian * .715F) + (sinRadian * .715F), M31 = .072F - (cosRadian * .072F) + (sinRadian * .928F), - M32 = .072F - (cosRadian * .072F) - (sinRadian * 0.283F), + + M12 = .213F - (cosRadian * .213F) + (sinRadian * .143F), + M22 = .715F + (cosRadian * .285F) + (sinRadian * .140F), + M32 = .072F - (cosRadian * .072F) - (sinRadian * .283F), + + M13 = .213F - (cosRadian * .213F) - (sinRadian * .787F), + M23 = .715F - (cosRadian * .715F) + (sinRadian * .715F), M33 = .072F + (cosRadian * .928F) + (sinRadian * .072F), - M44 = 1 + M44 = 1F }; } @@ -348,23 +362,23 @@ namespace SixLabors.ImageSharp.Processing /// Create an invert filter matrix using the given amount. /// /// The proportion of the conversion. Must be between 0 and 1. - /// The - public static Matrix4x4 CreateInvertFilter(float amount) + /// The + public static ColorMatrix CreateInvertFilter(float amount) { Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); // See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc float invert = 1F - (2F * amount); - return new Matrix4x4 + return new ColorMatrix { M11 = invert, M22 = invert, M33 = invert, - M41 = amount, - M42 = amount, - M43 = amount, - M44 = 1 + M44 = 1F, + M51 = amount, + M52 = amount, + M53 = amount, }; } @@ -372,17 +386,17 @@ namespace SixLabors.ImageSharp.Processing /// Create an opacity filter matrix using the given amount. /// /// The proportion of the conversion. Must be between 0 and 1. - /// The - public static Matrix4x4 CreateOpacityFilter(float amount) + /// The + public static ColorMatrix CreateOpacityFilter(float amount) { Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); // See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc - return new Matrix4x4 + return new ColorMatrix { - M11 = 1, - M22 = 1, - M33 = 1, + M11 = 1F, + M22 = 1F, + M33 = 1F, M44 = amount }; } @@ -395,25 +409,27 @@ namespace SixLabors.ImageSharp.Processing /// Other values are linear multipliers on the effect. Values of amount over 1 are allowed, providing super-saturated results /// /// The proportion of the conversion. Must be greater than or equal to 0. - /// The - public static Matrix4x4 CreateSaturateFilter(float amount) + /// The + public static ColorMatrix CreateSaturateFilter(float amount) { Guard.MustBeGreaterThanOrEqualTo(amount, 0, nameof(amount)); // See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc - return new Matrix4x4 - { - M11 = .213F + (.787F * amount), - M12 = .213F - (.213F * amount), - M13 = .213F - (.213F * amount), - M21 = .715F - (.715F * amount), - M22 = .715F + (.285F * amount), - M23 = .715F - (.715F * amount), - M31 = 1F - ((.213F + (.787F * amount)) + (.715F - (.715F * amount))), - M32 = 1F - ((.213F - (.213F * amount)) + (.715F + (.285F * amount))), - M33 = 1F - ((.213F - (.213F * amount)) + (.715F - (.715F * amount))), - M44 = 1 - }; + ColorMatrix m = default; + m.M11 = .213F + (.787F * amount); + m.M21 = .715F - (.715F * amount); + m.M31 = 1F - (m.M11 + m.M21); + + m.M12 = .213F - (.213F * amount); + m.M22 = .715F + (.285F * amount); + m.M32 = 1F - (m.M12 + m.M22); + + m.M13 = .213F - (.213F * amount); + m.M23 = .715F - (.715F * amount); + m.M33 = 1F - (m.M13 + m.M23); + m.M44 = 1F; + + return m; } /// @@ -421,25 +437,27 @@ namespace SixLabors.ImageSharp.Processing /// The formula used matches the svg specification. /// /// The proportion of the conversion. Must be between 0 and 1. - /// The - public static Matrix4x4 CreateSepiaFilter(float amount) + /// The + public static ColorMatrix CreateSepiaFilter(float amount) { Guard.MustBeBetweenOrEqualTo(amount, 0, 1, nameof(amount)); amount = 1F - amount; // See https://cs.chromium.org/chromium/src/cc/paint/render_surface_filters.cc - return new Matrix4x4 + return new ColorMatrix { M11 = .393F + (.607F * amount), - M12 = .349F - (.349F * amount), - M13 = .272F - (.272F * amount), M21 = .769F - (.769F * amount), - M22 = .686F + (.314F * amount), - M23 = .534F - (.534F * amount), M31 = .189F - (.189F * amount), + + M12 = .349F - (.349F * amount), + M22 = .686F + (.314F * amount), M32 = .168F - (.168F * amount), + + M13 = .272F - (.272F * amount), + M23 = .534F - (.534F * amount), M33 = .131F + (.869F * amount), - M44 = 1 + M44 = 1F }; } } diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs index d3a44c066..d6a32d889 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs @@ -3,16 +3,16 @@ using System; using System.Numerics; -using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// - /// Provides methods that accept a matrix to apply free-form filters to images. + /// Provides methods that accept a matrix to apply free-form filters to images. /// /// The pixel format. internal class FilterProcessor : ImageProcessor @@ -22,38 +22,36 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// Initializes a new instance of the class. /// /// The matrix used to apply the image filter - public FilterProcessor(Matrix4x4 matrix) - { - this.Matrix = matrix; - } + public FilterProcessor(ColorMatrix matrix) => this.Matrix = matrix; /// - /// Gets the used to apply the image filter. + /// Gets the used to apply the image filter. /// - public Matrix4x4 Matrix { get; } + public ColorMatrix Matrix { get; } /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); + int startX = interest.X; - Matrix4x4 matrix = this.Matrix; + ColorMatrix matrix = this.Matrix; - ParallelHelper.IterateRows( + ParallelHelper.IterateRowsWithTempBuffer( interest, configuration, - rows => + (rows, vectorBuffer) => { for (int y = rows.Min; y < rows.Max; y++) { - Span row = source.GetPixelRowSpan(y); - - for (int x = interest.X; x < interest.Right; x++) - { - ref TPixel pixel = ref row[x]; - var vector = Vector4.Transform(pixel.ToVector4(), matrix); - pixel.FromVector4(vector); - } + Span vectorSpan = vectorBuffer.Span; + int length = vectorSpan.Length; + Span rowSpan = source.GetPixelRowSpan(y).Slice(startX, length); + PixelOperations.Instance.ToVector4(configuration, rowSpan, vectorSpan); + + Vector4Utils.Transform(vectorSpan, ref matrix); + + PixelOperations.Instance.FromVector4(configuration, vectorSpan, rowSpan); } }); } diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs index 158a085d5..aed1edfbf 100644 --- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs +++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs @@ -57,8 +57,7 @@ namespace SixLabors.ImageSharp.Tests { using (Image image = file.CreateImage()) { - var encoder = new PngEncoder { Quantizer = new WuQuantizer(KnownDiffusers.JarvisJudiceNinke, 256), ColorType = PngColorType.Palette }; - image.Save($"{path}/{file.FileName}.png", encoder); + image.Save($"{path}/{file.FileName}"); } } } diff --git a/tests/ImageSharp.Tests/Helpers/Vector4UtilsTests.cs b/tests/ImageSharp.Tests/Helpers/Vector4UtilsTests.cs index 9416be740..f2e98b131 100644 --- a/tests/ImageSharp.Tests/Helpers/Vector4UtilsTests.cs +++ b/tests/ImageSharp.Tests/Helpers/Vector4UtilsTests.cs @@ -11,6 +11,8 @@ namespace SixLabors.ImageSharp.Tests.Helpers { public class Vector4UtilsTests { + private readonly ApproximateFloatComparer ApproximateFloatComparer = new ApproximateFloatComparer(1e-6f); + [Theory] [InlineData(0)] [InlineData(1)] @@ -23,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests.Helpers Vector4Utils.Premultiply(source); - Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f)); + Assert.Equal(expected, source, this.ApproximateFloatComparer); } [Theory] @@ -38,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Helpers Vector4Utils.UnPremultiply(source); - Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f)); + Assert.Equal(expected, source, this.ApproximateFloatComparer); } } } diff --git a/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs b/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs new file mode 100644 index 000000000..2fbe260ec --- /dev/null +++ b/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs @@ -0,0 +1,270 @@ +using System; +using System.Globalization; +using SixLabors.ImageSharp.Primitives; +using SixLabors.ImageSharp.Processing; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Primitives +{ + public class ColorMatrixTests + { + private readonly ApproximateFloatComparer ApproximateFloatComparer = new ApproximateFloatComparer(1e-6f); + + [Fact] + public void ColorMatrixIdentityIsCorrect() + { + ColorMatrix val = default; + val.M11 = val.M22 = val.M33 = val.M44 = 1F; + + Assert.Equal(val, ColorMatrix.Identity, this.ApproximateFloatComparer); + } + + [Fact] + public void ColorMatrixCanDetectIdentity() + { + ColorMatrix m = ColorMatrix.Identity; + Assert.True(m.IsIdentity); + + m.M12 = 1F; + Assert.False(m.IsIdentity); + } + + [Fact] + public void ColorMatrixEquality() + { + ColorMatrix m = KnownFilterMatrices.CreateHueFilter(45F); + ColorMatrix m2 = KnownFilterMatrices.CreateHueFilter(45F); + object obj = m2; + + Assert.True(m.Equals(obj)); + Assert.True(m.Equals(m2)); + Assert.True(m == m2); + Assert.False(m != m2); + } + + [Fact] + public void ColorMatrixMultiply() + { + ColorMatrix value1 = this.CreateAllTwos(); + ColorMatrix value2 = this.CreateAllThrees(); + + ColorMatrix m; + + // First row + m.M11 = (value1.M11 * value2.M11) + (value1.M12 * value2.M21) + (value1.M13 * value2.M31) + (value1.M14 * value2.M41); + m.M12 = (value1.M11 * value2.M12) + (value1.M12 * value2.M22) + (value1.M13 * value2.M32) + (value1.M14 * value2.M42); + m.M13 = (value1.M11 * value2.M13) + (value1.M12 * value2.M23) + (value1.M13 * value2.M33) + (value1.M14 * value2.M43); + m.M14 = (value1.M11 * value2.M14) + (value1.M12 * value2.M24) + (value1.M13 * value2.M34) + (value1.M14 * value2.M44); + + // Second row + m.M21 = (value1.M21 * value2.M11) + (value1.M22 * value2.M21) + (value1.M23 * value2.M31) + (value1.M24 * value2.M41); + m.M22 = (value1.M21 * value2.M12) + (value1.M22 * value2.M22) + (value1.M23 * value2.M32) + (value1.M24 * value2.M42); + m.M23 = (value1.M21 * value2.M13) + (value1.M22 * value2.M23) + (value1.M23 * value2.M33) + (value1.M24 * value2.M43); + m.M24 = (value1.M21 * value2.M14) + (value1.M22 * value2.M24) + (value1.M23 * value2.M34) + (value1.M24 * value2.M44); + + // Third row + m.M31 = (value1.M31 * value2.M11) + (value1.M32 * value2.M21) + (value1.M33 * value2.M31) + (value1.M34 * value2.M41); + m.M32 = (value1.M31 * value2.M12) + (value1.M32 * value2.M22) + (value1.M33 * value2.M32) + (value1.M34 * value2.M42); + m.M33 = (value1.M31 * value2.M13) + (value1.M32 * value2.M23) + (value1.M33 * value2.M33) + (value1.M34 * value2.M43); + m.M34 = (value1.M31 * value2.M14) + (value1.M32 * value2.M24) + (value1.M33 * value2.M34) + (value1.M34 * value2.M44); + + // Fourth row + m.M41 = (value1.M41 * value2.M11) + (value1.M42 * value2.M21) + (value1.M43 * value2.M31) + (value1.M44 * value2.M41); + m.M42 = (value1.M41 * value2.M12) + (value1.M42 * value2.M22) + (value1.M43 * value2.M32) + (value1.M44 * value2.M42); + m.M43 = (value1.M41 * value2.M13) + (value1.M42 * value2.M23) + (value1.M43 * value2.M33) + (value1.M44 * value2.M43); + m.M44 = (value1.M41 * value2.M14) + (value1.M42 * value2.M24) + (value1.M43 * value2.M34) + (value1.M44 * value2.M44); + + // Fifth row + m.M51 = (value1.M51 * value2.M11) + (value1.M52 * value2.M21) + (value1.M53 * value2.M31) + (value1.M54 * value2.M41) + value2.M51; + m.M52 = (value1.M51 * value2.M12) + (value1.M52 * value2.M22) + (value1.M53 * value2.M32) + (value1.M54 * value2.M52) + value2.M52; + m.M53 = (value1.M51 * value2.M13) + (value1.M52 * value2.M23) + (value1.M53 * value2.M33) + (value1.M54 * value2.M53) + value2.M53; + m.M54 = (value1.M51 * value2.M14) + (value1.M52 * value2.M24) + (value1.M53 * value2.M34) + (value1.M54 * value2.M54) + value2.M54; + + Assert.Equal(m, value1 * value2, this.ApproximateFloatComparer); + } + + [Fact] + public void ColorMatrixMultiplyScalar() + { + ColorMatrix m = this.CreateAllTwos(); + Assert.Equal(this.CreateAllFours(), m * 2, this.ApproximateFloatComparer); + } + + [Fact] + public void ColorMatrixSubtract() + { + ColorMatrix m = this.CreateAllOnes() + this.CreateAllTwos(); + Assert.Equal(this.CreateAllThrees(), m); + } + + [Fact] + public void ColorMatrixNegate() + { + ColorMatrix m = this.CreateAllOnes() * -1F; + Assert.Equal(m, -this.CreateAllOnes()); + } + + [Fact] + public void ColorMatrixAdd() + { + ColorMatrix m = this.CreateAllOnes() + this.CreateAllTwos(); + Assert.Equal(this.CreateAllThrees(), m); + } + + [Fact] + public void ColorMatrixHashCode() + { +#if NETCOREAPP2_1 + ColorMatrix m = KnownFilterMatrices.CreateBrightnessFilter(.5F); + HashCode hash = default; + hash.Add(m.M11); + hash.Add(m.M12); + hash.Add(m.M13); + hash.Add(m.M14); + hash.Add(m.M21); + hash.Add(m.M22); + hash.Add(m.M23); + hash.Add(m.M24); + hash.Add(m.M31); + hash.Add(m.M32); + hash.Add(m.M33); + hash.Add(m.M34); + hash.Add(m.M41); + hash.Add(m.M42); + hash.Add(m.M43); + hash.Add(m.M44); + hash.Add(m.M51); + hash.Add(m.M52); + hash.Add(m.M53); + hash.Add(m.M54); + + Assert.Equal(hash.ToHashCode(), m.GetHashCode()); +#endif + } + + [Fact] + public void ColorMatrixToString() + { + ColorMatrix m = KnownFilterMatrices.CreateBrightnessFilter(.5F); + + CultureInfo ci = CultureInfo.CurrentCulture; + + string expected = string.Format(ci, "{{ {{M11:{0} M12:{1} M13:{2} M14:{3}}} {{M21:{4} M22:{5} M23:{6} M24:{7}}} {{M31:{8} M32:{9} M33:{10} M34:{11}}} {{M41:{12} M42:{13} M43:{14} M44:{15}}} {{M51:{16} M52:{17} M53:{18} M54:{19}}} }}", + m.M11.ToString(ci), m.M12.ToString(ci), m.M13.ToString(ci), m.M14.ToString(ci), + m.M21.ToString(ci), m.M22.ToString(ci), m.M23.ToString(ci), m.M24.ToString(ci), + m.M31.ToString(ci), m.M32.ToString(ci), m.M33.ToString(ci), m.M34.ToString(ci), + m.M41.ToString(ci), m.M42.ToString(ci), m.M43.ToString(ci), m.M44.ToString(ci), + m.M51.ToString(ci), m.M52.ToString(ci), m.M53.ToString(ci), m.M54.ToString(ci)); + + Assert.Equal(expected, m.ToString()); + } + + private ColorMatrix CreateAllOnes() + { + return new ColorMatrix + { + M11 = 1F, + M12 = 1F, + M13 = 1F, + M14 = 1F, + M21 = 1F, + M22 = 1F, + M23 = 1F, + M24 = 1F, + M31 = 1F, + M32 = 1F, + M33 = 1F, + M34 = 1F, + M41 = 1F, + M42 = 1F, + M43 = 1F, + M44 = 1F, + M51 = 1F, + M52 = 1F, + M53 = 1F, + M54 = 1F + }; + } + + private ColorMatrix CreateAllTwos() + { + return new ColorMatrix + { + M11 = 2F, + M12 = 2F, + M13 = 2F, + M14 = 2F, + M21 = 2F, + M22 = 2F, + M23 = 2F, + M24 = 2F, + M31 = 2F, + M32 = 2F, + M33 = 2F, + M34 = 2F, + M41 = 2F, + M42 = 2F, + M43 = 2F, + M44 = 2F, + M51 = 2F, + M52 = 2F, + M53 = 2F, + M54 = 2F + }; + } + + private ColorMatrix CreateAllThrees() + { + return new ColorMatrix + { + M11 = 3F, + M12 = 3F, + M13 = 3F, + M14 = 3F, + M21 = 3F, + M22 = 3F, + M23 = 3F, + M24 = 3F, + M31 = 3F, + M32 = 3F, + M33 = 3F, + M34 = 3F, + M41 = 3F, + M42 = 3F, + M43 = 3F, + M44 = 3F, + M51 = 3F, + M52 = 3F, + M53 = 3F, + M54 = 3F + }; + } + + private ColorMatrix CreateAllFours() + { + return new ColorMatrix + { + M11 = 4F, + M12 = 4F, + M13 = 4F, + M14 = 4F, + M21 = 4F, + M22 = 4F, + M23 = 4F, + M24 = 4F, + M31 = 4F, + M32 = 4F, + M33 = 4F, + M34 = 4F, + M41 = 4F, + M42 = 4F, + M43 = 4F, + M44 = 4F, + M51 = 4F, + M52 = 4F, + M53 = 4F, + M54 = 4F + }; + } + } +} diff --git a/tests/ImageSharp.Tests/Processing/Processors/Filters/BrightnessTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Filters/BrightnessTest.cs index ed790cbac..54a8dd4b7 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Filters/BrightnessTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Filters/BrightnessTest.cs @@ -8,10 +8,13 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects { using SixLabors.ImageSharp.Processing; + using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; [GroupOutput("Filters")] public class BrightnessTest { + private readonly ImageComparer imageComparer = ImageComparer.Tolerant(0.007F); + public static readonly TheoryData BrightnessValues = new TheoryData { @@ -22,9 +25,6 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects [Theory] [WithTestPatternImages(nameof(BrightnessValues), 48, 48, PixelTypes.Rgba32)] public void ApplyBrightnessFilter(TestImageProvider provider, float value) - where TPixel : struct, IPixel - { - provider.RunValidatingProcessorTest(ctx => ctx.Brightness(value), value); - } + where TPixel : struct, IPixel => provider.RunValidatingProcessorTest(ctx => ctx.Brightness(value), value, this.imageComparer); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Filters/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Filters/ColorBlindnessTest.cs index 3d48e16ec..8ac56655e 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Filters/ColorBlindnessTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Filters/ColorBlindnessTest.cs @@ -2,17 +2,19 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters { using SixLabors.ImageSharp.Processing; + using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; [GroupOutput("Filters")] public class ColorBlindnessTest { + private readonly ImageComparer imageComparer = ImageComparer.Tolerant(0.03F); + public static readonly TheoryData ColorBlindnessFilters = new TheoryData { @@ -29,9 +31,6 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters [Theory] [WithTestPatternImages(nameof(ColorBlindnessFilters), 48, 48, PixelTypes.Rgba32)] public void ApplyColorBlindnessFilter(TestImageProvider provider, ColorBlindnessMode colorBlindness) - where TPixel : struct, IPixel - { - provider.RunValidatingProcessorTest(x => x.ColorBlindness(colorBlindness), colorBlindness.ToString()); - } + where TPixel : struct, IPixel => provider.RunValidatingProcessorTest(x => x.ColorBlindness(colorBlindness), colorBlindness.ToString(), this.imageComparer); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Filters/FilterTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Filters/FilterTest.cs index 479a3c33a..68daa80ea 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Filters/FilterTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Filters/FilterTest.cs @@ -1,16 +1,13 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Numerics; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - -using SixLabors.Primitives; using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters { + using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing; [GroupOutput("Filters")] @@ -25,7 +22,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters public void ApplyFilter(TestImageProvider provider) where TPixel : struct, IPixel { - Matrix4x4 m = CreateCombinedTestFilterMatrix(); + ColorMatrix m = CreateCombinedTestFilterMatrix(); provider.RunValidatingProcessorTest(x => x.Filter(m), comparer: ValidatorComparer); } @@ -35,18 +32,17 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters public void ApplyFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { - Matrix4x4 m = CreateCombinedTestFilterMatrix(); + ColorMatrix m = CreateCombinedTestFilterMatrix(); provider.RunRectangleConstrainedValidatingProcessorTest((x, b) => x.Filter(m, b), comparer: ValidatorComparer); } - private static Matrix4x4 CreateCombinedTestFilterMatrix() + private static ColorMatrix CreateCombinedTestFilterMatrix() { - Matrix4x4 brightness = KnownFilterMatrices.CreateBrightnessFilter(0.9F); - Matrix4x4 hue = KnownFilterMatrices.CreateHueFilter(180F); - Matrix4x4 saturation = KnownFilterMatrices.CreateSaturateFilter(1.5F); - Matrix4x4 m = brightness * hue * saturation; - return m; + ColorMatrix brightness = KnownFilterMatrices.CreateBrightnessFilter(0.9F); + ColorMatrix hue = KnownFilterMatrices.CreateHueFilter(180F); + ColorMatrix saturation = KnownFilterMatrices.CreateSaturateFilter(1.5F); + return brightness * hue * saturation; } } diff --git a/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs b/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs index 47ca6cccb..872a935ff 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Numerics; +using SixLabors.ImageSharp.Primitives; namespace SixLabors.ImageSharp.Tests { @@ -11,8 +12,9 @@ namespace SixLabors.ImageSharp.Tests /// internal readonly struct ApproximateFloatComparer : IEqualityComparer, + IEqualityComparer, IEqualityComparer, - IEqualityComparer + IEqualityComparer { private readonly float Epsilon; @@ -20,7 +22,7 @@ namespace SixLabors.ImageSharp.Tests /// Initializes a new instance of the class. /// /// The comparison error difference epsilon to use. - public ApproximateFloatComparer(float epsilon = 1f) => this.Epsilon = epsilon; + public ApproximateFloatComparer(float epsilon = 1F) => this.Epsilon = epsilon; /// public bool Equals(float x, float y) @@ -34,17 +36,29 @@ namespace SixLabors.ImageSharp.Tests public int GetHashCode(float obj) => obj.GetHashCode(); /// - public bool Equals(Vector4 a, Vector4 b) => this.Equals(a.X, b.X) && this.Equals(a.Y, b.Y) && this.Equals(a.Z, b.Z) && this.Equals(a.W, b.W); + public bool Equals(Vector2 x, Vector2 y) => this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y); /// - public int GetHashCode(Vector4 obj) => obj.GetHashCode(); + public int GetHashCode(Vector2 obj) => obj.GetHashCode(); + + /// + public bool Equals(Vector4 x, Vector4 y) => this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y) && this.Equals(x.Z, y.Z) && this.Equals(x.W, y.W); /// - public bool Equals(Vector2 a, Vector2 b) => this.Equals(a.X, b.X) && this.Equals(a.Y, b.Y); + public int GetHashCode(Vector4 obj) => obj.GetHashCode(); - public int GetHashCode(Vector2 obj) + /// + public bool Equals(ColorMatrix x, ColorMatrix y) { - throw new System.NotImplementedException(); + return + this.Equals(x.M11, y.M11) && this.Equals(x.M12, y.M12) && this.Equals(x.M13, y.M13) && this.Equals(x.M14, y.M14) + && this.Equals(x.M21, y.M21) && this.Equals(x.M22, y.M22) && this.Equals(x.M23, y.M23) && this.Equals(x.M24, y.M24) + && this.Equals(x.M31, y.M31) && this.Equals(x.M32, y.M32) && this.Equals(x.M33, y.M33) && this.Equals(x.M34, y.M34) + && this.Equals(x.M41, y.M41) && this.Equals(x.M42, y.M42) && this.Equals(x.M43, y.M43) && this.Equals(x.M44, y.M44) + && this.Equals(x.M51, y.M51) && this.Equals(x.M52, y.M52) && this.Equals(x.M53, y.M53) && this.Equals(x.M54, y.M54); } + + /// + public int GetHashCode(ColorMatrix obj) => obj.GetHashCode(); } } \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index 7ada45bc3..74995302e 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 7ada45bc3484f40e28a50817386ca93f293acd11 +Subproject commit 74995302e3c9a5913f1cf09d71b15f888d0ec022 From 1996831667dd1190e6fa82ef416b06db899623b0 Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Fri, 18 Jan 2019 08:11:55 +0100 Subject: [PATCH 012/223] Decoding Bitmaps with BITFIELDS masks (#796) * decoding bitmaps with Bitfields masks * added testcases for Bitfields bitmaps * added parsing of the complete bitmap V4 header to get the color masks infos for the BITFIELDS compression * writing now explicitly a Bitamp v3 header (40 bytes) * added test image for issue #735 * fixed rescaling 5-bit / 6-bit to 0 - 255 range * BitmapEncoder now writes BMP v4 header * using MemoryMarshal.Cast to simplify parsing v4 header * added testcases for bitmap v3, v4, v5 * Bitmap encoder writes again V3 header instead of V4. Additional fields for V4 are zero anyway. * added parsing of special case for 56 bytes headers * using the alpha mask in ReadRgb32BitFields() when its present * added support for bitmasks greater then 8 bits per channel * using MagickReferenceDecoder reference decoder for the test with 10 bits pixel masks * changed bitmap constants to hex * added enum for the bitmap info header type * added support for 52 bytes header (same as 56 bytes without the alpha mask) * clarified comment with difference between imagesharp and magick decoder for Rgba321010102 * BmpEncoder now writes a V4 info header and uses BITFIELDS compression * workaround for issue that the decoder does not decode the alpha channel correctly: For V3 bitmaps, the alpha channel will be ignored during encoding * Fix #732 --- src/ImageSharp/Formats/Bmp/BmpCompression.cs | 2 - src/ImageSharp/Formats/Bmp/BmpConstants.cs | 36 ++ src/ImageSharp/Formats/Bmp/BmpDecoder.cs | 2 - src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 399 ++++++++++++++++-- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 50 ++- src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs | 252 ++++++++++- .../Formats/Bmp/BmpInfoHeaderType.cs | 48 +++ src/ImageSharp/Formats/Bmp/BmpMetaData.cs | 11 +- .../Formats/Bmp/BmpDecoderTests.cs | 107 ++++- tests/ImageSharp.Tests/TestImages.cs | 29 +- tests/Images/Input/Bmp/issue735.bmp | Bin 0 -> 1334298 bytes tests/Images/Input/Bmp/pal8v4.bmp | Bin 0 -> 9322 bytes tests/Images/Input/Bmp/pal8v5.bmp | Bin 0 -> 9338 bytes tests/Images/Input/Bmp/rgb16-565.bmp | Bin 0 -> 16450 bytes tests/Images/Input/Bmp/rgb16-565pal.bmp | Bin 0 -> 17474 bytes tests/Images/Input/Bmp/rgb16bfdef.bmp | Bin 0 -> 16450 bytes tests/Images/Input/Bmp/rgb24.bmp | Bin 0 -> 24630 bytes tests/Images/Input/Bmp/rgb32bf.bmp | Bin 0 -> 32578 bytes tests/Images/Input/Bmp/rgb32bfdef.bmp | Bin 0 -> 32578 bytes tests/Images/Input/Bmp/rgba32-1010102.bmp | Bin 0 -> 32650 bytes tests/Images/Input/Bmp/rgba32.bmp | Bin 0 -> 32650 bytes tests/Images/Input/Bmp/rgba32h56.bmp | Bin 0 -> 32582 bytes 22 files changed, 859 insertions(+), 77 deletions(-) create mode 100644 src/ImageSharp/Formats/Bmp/BmpInfoHeaderType.cs create mode 100644 tests/Images/Input/Bmp/issue735.bmp create mode 100644 tests/Images/Input/Bmp/pal8v4.bmp create mode 100644 tests/Images/Input/Bmp/pal8v5.bmp create mode 100644 tests/Images/Input/Bmp/rgb16-565.bmp create mode 100644 tests/Images/Input/Bmp/rgb16-565pal.bmp create mode 100644 tests/Images/Input/Bmp/rgb16bfdef.bmp create mode 100644 tests/Images/Input/Bmp/rgb24.bmp create mode 100644 tests/Images/Input/Bmp/rgb32bf.bmp create mode 100644 tests/Images/Input/Bmp/rgb32bfdef.bmp create mode 100644 tests/Images/Input/Bmp/rgba32-1010102.bmp create mode 100644 tests/Images/Input/Bmp/rgba32.bmp create mode 100644 tests/Images/Input/Bmp/rgba32h56.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpCompression.cs b/src/ImageSharp/Formats/Bmp/BmpCompression.cs index ef063f010..5f14d2243 100644 --- a/src/ImageSharp/Formats/Bmp/BmpCompression.cs +++ b/src/ImageSharp/Formats/Bmp/BmpCompression.cs @@ -25,7 +25,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// If the first byte is zero, the record has different meanings, depending /// on the second byte. If the second byte is zero, it is the end of the row, /// if it is one, it is the end of the image. - /// Not supported at the moment. /// RLE8 = 1, @@ -42,7 +41,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Each image row has a multiple of four elements. If the /// row has less elements, zeros will be added at the right side. - /// Not supported at the moment. /// BitFields = 3, diff --git a/src/ImageSharp/Formats/Bmp/BmpConstants.cs b/src/ImageSharp/Formats/Bmp/BmpConstants.cs index 99799b619..5cbed4af2 100644 --- a/src/ImageSharp/Formats/Bmp/BmpConstants.cs +++ b/src/ImageSharp/Formats/Bmp/BmpConstants.cs @@ -19,5 +19,41 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The list of file extensions that equate to a bmp. /// public static readonly IEnumerable FileExtensions = new[] { "bm", "bmp", "dip" }; + + /// + /// Valid magic bytes markers identifying a Bitmap file. + /// + internal static class TypeMarkers + { + /// + /// Single-image BMP file that may have been created under Windows or OS/2. + /// + public const int Bitmap = 0x4D42; + + /// + /// OS/2 Bitmap Array. + /// + public const int BitmapArray = 0x4142; + + /// + /// OS/2 Color Icon. + /// + public const int ColorIcon = 0x4943; + + /// + /// OS/2 Color Pointer. + /// + public const int ColorPointer = 0x5043; + + /// + /// OS/2 Icon. + /// + public const int Icon = 0x4349; + + /// + /// OS/2 Pointer. + /// + public const int Pointer = 0x5450; + } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs index 3d079cf61..82af2a671 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs @@ -15,8 +15,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// JPG /// PNG /// RLE4 - /// RLE8 - /// BitFields /// /// Formats will be supported in a later releases. We advise always /// to use only 24 Bit Windows bitmaps. diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 68528edcd..362fe6443 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -2,8 +2,10 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; using System.Buffers.Binary; using System.IO; +using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Memory; @@ -14,7 +16,7 @@ using SixLabors.Memory; namespace SixLabors.ImageSharp.Formats.Bmp { /// - /// Performs the bmp decoding operation. + /// Performs the bitmap decoding operation. /// /// /// A useful decoding source example can be found at @@ -22,19 +24,19 @@ namespace SixLabors.ImageSharp.Formats.Bmp internal sealed class BmpDecoderCore { /// - /// The mask for the red part of the color for 16 bit rgb bitmaps. + /// The default mask for the red part of the color for 16 bit rgb bitmaps. /// - private const int Rgb16RMask = 0x7C00; + private const int DefaultRgb16RMask = 0x7C00; /// - /// The mask for the green part of the color for 16 bit rgb bitmaps. + /// The default mask for the green part of the color for 16 bit rgb bitmaps. /// - private const int Rgb16GMask = 0x3E0; + private const int DefaultRgb16GMask = 0x3E0; /// - /// The mask for the blue part of the color for 16 bit rgb bitmaps. + /// The default mask for the blue part of the color for 16 bit rgb bitmaps. /// - private const int Rgb16BMask = 0x1F; + private const int DefaultRgb16BMask = 0x1F; /// /// RLE8 flag value that indicates following byte has special meaning. @@ -62,10 +64,15 @@ namespace SixLabors.ImageSharp.Formats.Bmp private Stream stream; /// - /// The metadata + /// The metadata. /// private ImageMetaData metaData; + /// + /// The bmp specific metadata. + /// + private BmpMetaData bmpMetaData; + /// /// The file header containing general information. /// TODO: Why is this not used? We advance the stream but do not use the values parsed. @@ -85,7 +92,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Initializes a new instance of the class. /// /// The configuration. - /// The options + /// The options. public BmpDecoderCore(Configuration configuration, IBmpDecoderOptions options) { this.configuration = configuration; @@ -119,7 +126,14 @@ namespace SixLabors.ImageSharp.Formats.Bmp case BmpCompression.RGB: if (this.infoHeader.BitsPerPixel == 32) { - this.ReadRgb32(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); + if (this.bmpMetaData.InfoHeaderType == BmpInfoHeaderType.WinVersion3) + { + this.ReadRgb32Slow(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); + } + else + { + this.ReadRgb32Fast(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); + } } else if (this.infoHeader.BitsPerPixel == 24) { @@ -146,6 +160,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.ReadRle8(pixels, palette, this.infoHeader.Width, this.infoHeader.Height, inverted); break; + + case BmpCompression.BitFields: + this.ReadBitFields(pixels, inverted); + + break; + default: throw new NotSupportedException("Does not support this kind of bitmap files."); } @@ -199,12 +219,39 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - /// Performs final shifting from a 5bit value to an 8bit one. + /// Decodes a bitmap containing BITFIELDS Compression type. For each color channel, there will be bitmask + /// which will be used to determine which bits belong to that channel. /// - /// The masked and shifted value - /// The - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static byte GetBytesFrom5BitValue(int value) => (byte)((value << 3) | (value >> 2)); + /// The pixel format. + /// The output pixel buffer containing the decoded image. + /// Whether the bitmap is inverted. + private void ReadBitFields(Buffer2D pixels, bool inverted) + where TPixel : struct, IPixel + { + if (this.infoHeader.BitsPerPixel == 16) + { + this.ReadRgb16( + pixels, + this.infoHeader.Width, + this.infoHeader.Height, + inverted, + this.infoHeader.RedMask, + this.infoHeader.GreenMask, + this.infoHeader.BlueMask); + } + else + { + this.ReadRgb32BitFields( + pixels, + this.infoHeader.Width, + this.infoHeader.Height, + inverted, + this.infoHeader.RedMask, + this.infoHeader.GreenMask, + this.infoHeader.BlueMask, + this.infoHeader.AlphaMask); + } + } /// /// Looks up color values and builds the image from de-compressed RLE8 data. @@ -240,12 +287,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - /// Produce uncompressed bitmap data from RLE8 stream + /// Produce uncompressed bitmap data from RLE8 stream. /// /// - /// RLE8 is a 2-byte run-length encoding - ///
If first byte is 0, the second byte may have special meaning - ///
Otherwise, first byte is the length of the run and second byte is the color for the run + /// RLE8 is a 2-byte run-length encoding. + ///
If first byte is 0, the second byte may have special meaning. + ///
Otherwise, first byte is the length of the run and second byte is the color for the run. ///
/// The width of the bitmap. /// Buffer for uncompressed data. @@ -382,20 +429,32 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - /// Reads the 16 bit color palette from the stream + /// Reads the 16 bit color palette from the stream. /// /// The pixel format. /// The to assign the palette to. /// The width of the bitmap. /// The height of the bitmap. /// Whether the bitmap is inverted. - private void ReadRgb16(Buffer2D pixels, int width, int height, bool inverted) + /// The bitmask for the red channel. + /// The bitmask for the green channel. + /// The bitmask for the blue channel. + private void ReadRgb16(Buffer2D pixels, int width, int height, bool inverted, int redMask = DefaultRgb16RMask, int greenMask = DefaultRgb16GMask, int blueMask = DefaultRgb16BMask) where TPixel : struct, IPixel { int padding = CalculatePadding(width, 2); int stride = (width * 2) + padding; TPixel color = default; + int rightShiftRedMask = CalculateRightShift((uint)redMask); + int rightShiftGreenMask = CalculateRightShift((uint)greenMask); + int rightShiftBlueMask = CalculateRightShift((uint)blueMask); + + // Each color channel contains either 5 or 6 Bits values. + int redMaskBits = CountBits((uint)redMask); + int greenMaskBits = CountBits((uint)greenMask); + int blueMaskBits = CountBits((uint)blueMask); + using (IManagedByteBuffer buffer = this.memoryAllocator.AllocateManagedByteBuffer(stride)) { for (int y = 0; y < height; y++) @@ -409,10 +468,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp { short temp = BitConverter.ToInt16(buffer.Array, offset); - var rgb = new Rgb24( - GetBytesFrom5BitValue((temp & Rgb16RMask) >> 10), - GetBytesFrom5BitValue((temp & Rgb16GMask) >> 5), - GetBytesFrom5BitValue(temp & Rgb16BMask)); + // Rescale values, so the values range from 0 to 255. + int r = (redMaskBits == 5) ? GetBytesFrom5BitValue((temp & redMask) >> rightShiftRedMask) : GetBytesFrom6BitValue((temp & redMask) >> rightShiftRedMask); + int g = (greenMaskBits == 5) ? GetBytesFrom5BitValue((temp & greenMask) >> rightShiftGreenMask) : GetBytesFrom6BitValue((temp & greenMask) >> rightShiftGreenMask); + int b = (blueMaskBits == 5) ? GetBytesFrom5BitValue((temp & blueMask) >> rightShiftBlueMask) : GetBytesFrom6BitValue((temp & blueMask) >> rightShiftBlueMask); + var rgb = new Rgb24((byte)r, (byte)g, (byte)b); color.FromRgb24(rgb); pixelRow[x] = color; @@ -423,7 +483,23 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - /// Reads the 24 bit color palette from the stream + /// Performs final shifting from a 5bit value to an 8bit one. + /// + /// The masked and shifted value. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static byte GetBytesFrom5BitValue(int value) => (byte)((value << 3) | (value >> 2)); + + /// + /// Performs final shifting from a 6bit value to an 8bit one. + /// + /// The masked and shifted value. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static byte GetBytesFrom6BitValue(int value) => (byte)((value << 2) | (value >> 4)); + + /// + /// Reads the 24 bit color palette from the stream. /// /// The pixel format. /// The to assign the palette to. @@ -452,14 +528,14 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - /// Reads the 32 bit color palette from the stream + /// Reads the 32 bit color palette from the stream. /// /// The pixel format. /// The to assign the palette to. /// The width of the bitmap. /// The height of the bitmap. /// Whether the bitmap is inverted. - private void ReadRgb32(Buffer2D pixels, int width, int height, bool inverted) + private void ReadRgb32Fast(Buffer2D pixels, int width, int height, bool inverted) where TPixel : struct, IPixel { int padding = CalculatePadding(width, 4); @@ -480,6 +556,228 @@ namespace SixLabors.ImageSharp.Formats.Bmp } } + /// + /// Reads the 32 bit color palette from the stream, checking the alpha component of each pixel. + /// This is a special case only used for 32bpp WinBMPv3 files, which could be in either BGR0 or BGRA format. + /// + /// The pixel format. + /// The to assign the palette to. + /// The width of the bitmap. + /// The height of the bitmap. + /// Whether the bitmap is inverted. + private void ReadRgb32Slow(Buffer2D pixels, int width, int height, bool inverted) + where TPixel : struct, IPixel + { + int padding = CalculatePadding(width, 4); + + using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, padding)) + using (IMemoryOwner bgraRow = this.memoryAllocator.Allocate(width)) + { + Span bgraRowSpan = bgraRow.GetSpan(); + long currentPosition = this.stream.Position; + bool hasAlpha = false; + + // Loop though the rows checking each pixel. We start by assuming it's + // an BGR0 image. If we hit a non-zero alpha value, then we know it's + // actually a BGRA image, and change tactics accordingly. + for (int y = 0; y < height; y++) + { + this.stream.Read(row); + + PixelOperations.Instance.FromBgra32Bytes( + this.configuration, + row.GetSpan(), + bgraRowSpan, + width); + + // Check each pixel in the row to see if it has an alpha value. + for (int x = 0; x < width; x++) + { + Bgra32 bgra = bgraRowSpan[x]; + if (bgra.A > 0) + { + hasAlpha = true; + break; + } + } + + if (hasAlpha) + { + break; + } + } + + // Reset our stream for a second pass. + this.stream.Position = currentPosition; + + // Process the pixels in bulk taking the raw alpha component value. + if (hasAlpha) + { + for (int y = 0; y < height; y++) + { + this.stream.Read(row); + + int newY = Invert(y, height, inverted); + Span pixelSpan = pixels.GetRowSpan(newY); + + PixelOperations.Instance.FromBgra32Bytes( + this.configuration, + row.GetSpan(), + pixelSpan, + width); + } + + return; + } + + // Slow path. We need to set each alpha component value to fully opaque. + for (int y = 0; y < height; y++) + { + this.stream.Read(row); + PixelOperations.Instance.FromBgra32Bytes( + this.configuration, + row.GetSpan(), + bgraRowSpan, + width); + + int newY = Invert(y, height, inverted); + Span pixelSpan = pixels.GetRowSpan(newY); + + for (int x = 0; x < width; x++) + { + Bgra32 bgra = bgraRowSpan[x]; + bgra.A = byte.MaxValue; + ref TPixel pixel = ref pixelSpan[x]; + pixel.FromBgra32(bgra); + } + } + } + } + + /// + /// Decode an 32 Bit Bitmap containing a bitmask for each color channel. + /// + /// The pixel format. + /// The output pixel buffer containing the decoded image. + /// The width of the image. + /// The height of the image. + /// Whether the bitmap is inverted. + /// The bitmask for the red channel. + /// The bitmask for the green channel. + /// The bitmask for the blue channel. + /// The bitmask for the alpha channel. + private void ReadRgb32BitFields(Buffer2D pixels, int width, int height, bool inverted, int redMask, int greenMask, int blueMask, int alphaMask) + where TPixel : struct, IPixel + { + TPixel color = default; + int padding = CalculatePadding(width, 4); + int stride = (width * 4) + padding; + + int rightShiftRedMask = CalculateRightShift((uint)redMask); + int rightShiftGreenMask = CalculateRightShift((uint)greenMask); + int rightShiftBlueMask = CalculateRightShift((uint)blueMask); + int rightShiftAlphaMask = CalculateRightShift((uint)alphaMask); + + int bitsRedMask = CountBits((uint)redMask); + int bitsGreenMask = CountBits((uint)greenMask); + int bitsBlueMask = CountBits((uint)blueMask); + int bitsAlphaMask = CountBits((uint)alphaMask); + float invMaxValueRed = 1.0f / (0xFFFFFFFF >> (32 - bitsRedMask)); + float invMaxValueGreen = 1.0f / (0xFFFFFFFF >> (32 - bitsGreenMask)); + float invMaxValueBlue = 1.0f / (0xFFFFFFFF >> (32 - bitsBlueMask)); + uint maxValueAlpha = 0xFFFFFFFF >> (32 - bitsAlphaMask); + float invMaxValueAlpha = 1.0f / maxValueAlpha; + + bool unusualBitMask = false; + if (bitsRedMask > 8 || bitsGreenMask > 8 || bitsBlueMask > 8 || invMaxValueAlpha > 8) + { + unusualBitMask = true; + } + + using (IManagedByteBuffer buffer = this.memoryAllocator.AllocateManagedByteBuffer(stride)) + { + for (int y = 0; y < height; y++) + { + this.stream.Read(buffer.Array, 0, stride); + int newY = Invert(y, height, inverted); + Span pixelRow = pixels.GetRowSpan(newY); + + int offset = 0; + for (int x = 0; x < width; x++) + { + uint temp = BitConverter.ToUInt32(buffer.Array, offset); + + if (unusualBitMask) + { + uint r = (uint)(temp & redMask) >> rightShiftRedMask; + uint g = (uint)(temp & greenMask) >> rightShiftGreenMask; + uint b = (uint)(temp & blueMask) >> rightShiftBlueMask; + float alpha = alphaMask != 0 ? invMaxValueAlpha * ((uint)(temp & alphaMask) >> rightShiftAlphaMask) : 1.0f; + var vector4 = new Vector4( + r * invMaxValueRed, + g * invMaxValueGreen, + b * invMaxValueBlue, + alpha); + color.FromVector4(vector4); + } + else + { + byte r = (byte)((temp & redMask) >> rightShiftRedMask); + byte g = (byte)((temp & greenMask) >> rightShiftGreenMask); + byte b = (byte)((temp & blueMask) >> rightShiftBlueMask); + byte a = alphaMask != 0 ? (byte)((temp & alphaMask) >> rightShiftAlphaMask) : (byte)255; + color.FromRgba32(new Rgba32(r, g, b, a)); + } + + pixelRow[x] = color; + offset += 4; + } + } + } + } + + /// + /// Calculates the necessary right shifts for a given color bitmask (the 0 bits to the right). + /// + /// The color bit mask. + /// Number of bits to shift right. + private static int CalculateRightShift(uint n) + { + int count = 0; + while (n > 0) + { + if ((1 & n) == 0) + { + count++; + } + else + { + break; + } + + n >>= 1; + } + + return count; + } + + /// + /// Counts none zero bits. + /// + /// A color mask. + /// The none zero bits. + private static int CountBits(uint n) + { + int count = 0; + while (n != 0) + { + count++; + n &= n - 1; + } + + return count; + } + /// /// Reads the from the stream. /// @@ -508,20 +806,54 @@ namespace SixLabors.ImageSharp.Formats.Bmp // read the rest of the header this.stream.Read(buffer, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize); + BmpInfoHeaderType inofHeaderType = BmpInfoHeaderType.WinVersion2; if (headerSize == BmpInfoHeader.CoreSize) { // 12 bytes + inofHeaderType = BmpInfoHeaderType.WinVersion2; this.infoHeader = BmpInfoHeader.ParseCore(buffer); } else if (headerSize == BmpInfoHeader.Os22ShortSize) { // 16 bytes + inofHeaderType = BmpInfoHeaderType.Os2Version2Short; this.infoHeader = BmpInfoHeader.ParseOs22Short(buffer); } - else if (headerSize >= BmpInfoHeader.Size) + else if (headerSize == BmpInfoHeader.SizeV3) + { + // == 40 bytes + inofHeaderType = BmpInfoHeaderType.WinVersion3; + this.infoHeader = BmpInfoHeader.ParseV3(buffer); + + // if the info header is BMP version 3 and the compression type is BITFIELDS, + // color masks for each color channel follow the info header. + if (this.infoHeader.Compression == BmpCompression.BitFields) + { + byte[] bitfieldsBuffer = new byte[12]; + this.stream.Read(bitfieldsBuffer, 0, 12); + Span data = bitfieldsBuffer.AsSpan(); + this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)); + this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)); + this.infoHeader.BlueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)); + } + } + else if (headerSize == BmpInfoHeader.AdobeV3Size) + { + // == 52 bytes + inofHeaderType = BmpInfoHeaderType.AdobeVersion3; + this.infoHeader = BmpInfoHeader.ParseAdobeV3(buffer, withAlpha: false); + } + else if (headerSize == BmpInfoHeader.AdobeV3WithAlphaSize) + { + // == 56 bytes + inofHeaderType = BmpInfoHeaderType.AdobeVersion3WithAlpha; + this.infoHeader = BmpInfoHeader.ParseAdobeV3(buffer, withAlpha: true); + } + else if (headerSize >= BmpInfoHeader.SizeV4) { - // >= 40 bytes - this.infoHeader = BmpInfoHeader.Parse(buffer); + // >= 108 bytes + inofHeaderType = headerSize == BmpInfoHeader.SizeV4 ? BmpInfoHeaderType.WinVersion4 : BmpInfoHeaderType.WinVersion5; + this.infoHeader = BmpInfoHeader.ParseV4(buffer); } else { @@ -548,13 +880,14 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.metaData = meta; short bitsPerPixel = this.infoHeader.BitsPerPixel; - BmpMetaData bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance); + this.bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance); + this.bmpMetaData.InfoHeaderType = inofHeaderType; // We can only encode at these bit rates so far. if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24) || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel32)) { - bmpMetaData.BitsPerPixel = (BmpBitsPerPixel)bitsPerPixel; + this.bmpMetaData.BitsPerPixel = (BmpBitsPerPixel)bitsPerPixel; } // skip the remaining header because we can't read those parts diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index a67c581eb..27a38bc0d 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -23,6 +23,26 @@ namespace SixLabors.ImageSharp.Formats.Bmp ///
private int padding; + /// + /// The mask for the alpha channel of the color for a 32 bit rgba bitmaps. + /// + private const int Rgba32AlphaMask = 0xFF << 24; + + /// + /// The mask for the red part of the color for a 32 bit rgba bitmaps. + /// + private const int Rgba32RedMask = 0xFF << 16; + + /// + /// The mask for the green part of the color for a 32 bit rgba bitmaps. + /// + private const int Rgba32GreenMask = 0xFF << 8; + + /// + /// The mask for the blue part of the color for a 32 bit rgba bitmaps. + /// + private const int Rgba32BlueMask = 0xFF; + private readonly MemoryAllocator memoryAllocator; private Configuration configuration; @@ -92,8 +112,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp } } + int infoHeaderSize = BmpInfoHeader.SizeV4; var infoHeader = new BmpInfoHeader( - headerSize: BmpInfoHeader.Size, + headerSize: infoHeaderSize, height: image.Height, width: image.Width, bitsPerPixel: bpp, @@ -102,26 +123,37 @@ namespace SixLabors.ImageSharp.Formats.Bmp clrUsed: 0, clrImportant: 0, xPelsPerMeter: hResolution, - yPelsPerMeter: vResolution); + yPelsPerMeter: vResolution) + { + RedMask = Rgba32RedMask, + GreenMask = Rgba32GreenMask, + BlueMask = Rgba32BlueMask, + Compression = BmpCompression.BitFields + }; + + if (this.bitsPerPixel == BmpBitsPerPixel.Pixel32) + { + infoHeader.AlphaMask = Rgba32AlphaMask; + } var fileHeader = new BmpFileHeader( - type: 19778, // BM - fileSize: 54 + infoHeader.ImageSize, + type: BmpConstants.TypeMarkers.Bitmap, + fileSize: BmpFileHeader.Size + infoHeaderSize + infoHeader.ImageSize, reserved: 0, - offset: 54); + offset: BmpFileHeader.Size + infoHeaderSize); #if NETCOREAPP2_1 - Span buffer = stackalloc byte[40]; + Span buffer = stackalloc byte[infoHeaderSize]; #else - byte[] buffer = new byte[40]; + byte[] buffer = new byte[infoHeaderSize]; #endif fileHeader.WriteTo(buffer); stream.Write(buffer, 0, BmpFileHeader.Size); - infoHeader.WriteTo(buffer); + infoHeader.WriteV4Header(buffer); - stream.Write(buffer, 0, 40); + stream.Write(buffer, 0, infoHeaderSize); this.WriteImage(stream, image.Frames.RootFrame); diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs index 5177bc325..316df4acc 100644 --- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs @@ -16,11 +16,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct BmpInfoHeader { - /// - /// Defines the size of the BITMAPINFOHEADER data structure in the bitmap file. - /// - public const int Size = 40; - /// /// Defines the size of the BITMAPCOREHEADER data structure in the bitmap file. /// @@ -31,10 +26,30 @@ namespace SixLabors.ImageSharp.Formats.Bmp ///
public const int Os22ShortSize = 16; + /// + /// Defines the size of the BITMAPINFOHEADER (BMP Version 3) data structure in the bitmap file. + /// + public const int SizeV3 = 40; + + /// + /// Special case of the BITMAPINFOHEADER V3 used by adobe where the color bitmasks are part of the info header instead of following it. + /// + public const int AdobeV3Size = 52; + + /// + /// Special case of the BITMAPINFOHEADER V3 used by adobe where the color bitmasks (including the alpha channel) are part of the info header instead of following it. + /// + public const int AdobeV3WithAlphaSize = 56; + + /// + /// Defines the size of the BITMAPINFOHEADER (BMP Version 4) data structure in the bitmap file. + /// + public const int SizeV4 = 108; + /// /// Defines the size of the biggest supported header data structure in the bitmap file. /// - public const int MaxHeaderSize = Size; + public const int MaxHeaderSize = SizeV4; /// /// Defines the size of the field. @@ -52,7 +67,24 @@ namespace SixLabors.ImageSharp.Formats.Bmp int xPelsPerMeter = 0, int yPelsPerMeter = 0, int clrUsed = 0, - int clrImportant = 0) + int clrImportant = 0, + int redMask = 0, + int greenMask = 0, + int blueMask = 0, + int alphaMask = 0, + int csType = 0, + int redX = 0, + int redY = 0, + int redZ = 0, + int greenX = 0, + int greenY = 0, + int greenZ = 0, + int blueX = 0, + int blueY = 0, + int blueZ = 0, + int gammeRed = 0, + int gammeGreen = 0, + int gammeBlue = 0) { this.HeaderSize = headerSize; this.Width = width; @@ -65,6 +97,23 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.YPelsPerMeter = yPelsPerMeter; this.ClrUsed = clrUsed; this.ClrImportant = clrImportant; + this.RedMask = redMask; + this.GreenMask = greenMask; + this.BlueMask = blueMask; + this.AlphaMask = alphaMask; + this.CsType = csType; + this.RedX = redX; + this.RedY = redY; + this.RedZ = redZ; + this.GreenX = greenX; + this.GreenY = greenY; + this.GreenZ = greenZ; + this.BlueX = blueX; + this.BlueY = blueY; + this.BlueZ = blueZ; + this.GammaRed = gammeRed; + this.GammaGreen = gammeGreen; + this.GammaBlue = gammeBlue; } /// @@ -130,23 +179,92 @@ namespace SixLabors.ImageSharp.Formats.Bmp public int ClrImportant { get; set; } /// - /// Parses the full BITMAPINFOHEADER header (40 bytes). + /// Gets or sets red color mask. This is used with the BITFIELDS decoding. /// - /// The data to parse. - /// Parsed header - /// - public static BmpInfoHeader Parse(ReadOnlySpan data) - { - if (data.Length != Size) - { - throw new ArgumentException(nameof(data), $"Must be {Size} bytes. Was {data.Length} bytes."); - } + public int RedMask { get; set; } - return MemoryMarshal.Cast(data)[0]; - } + /// + /// Gets or sets green color mask. This is used with the BITFIELDS decoding. + /// + public int GreenMask { get; set; } + + /// + /// Gets or sets blue color mask. This is used with the BITFIELDS decoding. + /// + public int BlueMask { get; set; } + + /// + /// Gets or sets alpha color mask. This is not used yet. + /// + public int AlphaMask { get; set; } + + /// + /// Gets or sets the Color space type. Not used yet. + /// + public int CsType { get; set; } + + /// + /// Gets or sets the X coordinate of red endpoint. Not used yet. + /// + public int RedX { get; set; } + + /// + /// Gets or sets the Y coordinate of red endpoint. Not used yet. + /// + public int RedY { get; set; } + + /// + /// Gets or sets the Z coordinate of red endpoint. Not used yet. + /// + public int RedZ { get; set; } + + /// + /// Gets or sets the X coordinate of green endpoint. Not used yet. + /// + public int GreenX { get; set; } + + /// + /// Gets or sets the Y coordinate of green endpoint. Not used yet. + /// + public int GreenY { get; set; } + + /// + /// Gets or sets the Z coordinate of green endpoint. Not used yet. + /// + public int GreenZ { get; set; } + + /// + /// Gets or sets the X coordinate of blue endpoint. Not used yet. + /// + public int BlueX { get; set; } /// - /// Parses the BITMAPCOREHEADER consisting of the headerSize, width, height, planes, and bitsPerPixel fields (12 bytes). + /// Gets or sets the Y coordinate of blue endpoint. Not used yet. + /// + public int BlueY { get; set; } + + /// + /// Gets or sets the Z coordinate of blue endpoint. Not used yet. + /// + public int BlueZ { get; set; } + + /// + /// Gets or sets the Gamma red coordinate scale value. Not used yet. + /// + public int GammaRed { get; set; } + + /// + /// Gets or sets the Gamma green coordinate scale value. Not used yet. + /// + public int GammaGreen { get; set; } + + /// + /// Gets or sets the Gamma blue coordinate scale value. Not used yet. + /// + public int GammaBlue { get; set; } + + /// + /// Parses the BITMAPCOREHEADER (BMP Version 2) consisting of the headerSize, width, height, planes, and bitsPerPixel fields (12 bytes). /// /// The data to parse. /// Parsed header @@ -163,7 +281,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Parses a short variant of the OS22XBITMAPHEADER. It is identical to the BITMAPCOREHEADER, except that the width and height - /// are 4 bytes instead of 2. + /// are 4 bytes instead of 2, resulting in 16 bytes total. /// /// The data to parse. /// Parsed header @@ -178,7 +296,97 @@ namespace SixLabors.ImageSharp.Formats.Bmp bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(14, 2))); } - public unsafe void WriteTo(Span buffer) + /// + /// Parses the full BMP Version 3 BITMAPINFOHEADER header (40 bytes). + /// + /// The data to parse. + /// The parsed header. + /// + public static BmpInfoHeader ParseV3(ReadOnlySpan data) + { + return new BmpInfoHeader( + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), + height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), + planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), + bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(14, 2)), + compression: (BmpCompression)BinaryPrimitives.ReadInt32LittleEndian(data.Slice(16, 4)), + imageSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(20, 4)), + xPelsPerMeter: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(24, 4)), + yPelsPerMeter: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(28, 4)), + clrUsed: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(32, 4)), + clrImportant: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(36, 4))); + } + + /// + /// Special case of the BITMAPINFOHEADER V3 used by adobe where the color bitmasks are part of the info header instead of following it. + /// 52 bytes without the alpha mask, 56 bytes with the alpha mask. + /// + /// The data to parse. + /// Indicates, if the alpha bitmask is present. + /// The parsed header. + /// + public static BmpInfoHeader ParseAdobeV3(ReadOnlySpan data, bool withAlpha = true) + { + return new BmpInfoHeader( + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), + height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), + planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), + bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(14, 2)), + compression: (BmpCompression)BinaryPrimitives.ReadInt32LittleEndian(data.Slice(16, 4)), + imageSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(20, 4)), + xPelsPerMeter: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(24, 4)), + yPelsPerMeter: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(28, 4)), + clrUsed: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(32, 4)), + clrImportant: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(36, 4)), + redMask: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(40, 4)), + greenMask: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(44, 4)), + blueMask: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(48, 4)), + alphaMask: withAlpha ? BinaryPrimitives.ReadInt32LittleEndian(data.Slice(52, 4)) : 0); + } + + /// + /// Parses the full BMP Version 4 BITMAPINFOHEADER header (108 bytes). + /// + /// The data to parse. + /// The parsed header. + /// + public static BmpInfoHeader ParseV4(ReadOnlySpan data) + { + if (data.Length != SizeV4) + { + throw new ArgumentException(nameof(data), $"Must be {SizeV4} bytes. Was {data.Length} bytes."); + } + + return MemoryMarshal.Cast(data)[0]; + } + + /// + /// Writes a bitmap version 3 (Microsoft Windows NT) header to a buffer (40 bytes). + /// + /// The buffer to write to. + public void WriteV3Header(Span buffer) + { + buffer.Clear(); + BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(0, 4), SizeV3); + BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(4, 4), this.Width); + BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(8, 4), this.Height); + BinaryPrimitives.WriteInt16LittleEndian(buffer.Slice(12, 2), this.Planes); + BinaryPrimitives.WriteInt16LittleEndian(buffer.Slice(14, 2), this.BitsPerPixel); + BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(16, 4), (int)this.Compression); + BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(20, 4), this.ImageSize); + BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(24, 4), this.XPelsPerMeter); + BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(28, 4), this.YPelsPerMeter); + BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(32, 4), this.ClrUsed); + BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(36, 4), this.ClrImportant); + } + + /// + /// Writes a complete Bitmap V4 header to a buffer. + /// + /// The buffer to write to. + public unsafe void WriteV4Header(Span buffer) { ref BmpInfoHeader dest = ref Unsafe.As(ref MemoryMarshal.GetReference(buffer)); diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeaderType.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeaderType.cs new file mode 100644 index 000000000..a4ce0115f --- /dev/null +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeaderType.cs @@ -0,0 +1,48 @@ +namespace SixLabors.ImageSharp.Formats.Bmp +{ + /// + /// Enum value for the different bitmap info header types. The enum value is the number of bytes for the specific bitmap header. + /// + public enum BmpInfoHeaderType + { + /// + /// Bitmap Core or BMP Version 2 header (Microsoft Windows 2.x). + /// + WinVersion2 = 12, + + /// + /// Short variant of the OS/2 Version 2 bitmap header. + /// + Os2Version2Short = 16, + + /// + /// BMP Version 3 header (Microsoft Windows 3.x or Microsoft Windows NT). + /// + WinVersion3 = 40, + + /// + /// Adobe variant of the BMP Version 3 header. + /// + AdobeVersion3 = 52, + + /// + /// Adobe variant of the BMP Version 3 header with an alpha mask. + /// + AdobeVersion3WithAlpha = 56, + + /// + /// BMP Version 2.x header (IBM OS/2 2.x). + /// + Os2Version2 = 64, + + /// + /// BMP Version 4 header (Microsoft Windows 95). + /// + WinVersion4 = 108, + + /// + /// BMP Version 5 header (Windows NT 5.0, 98 or later). + /// + WinVersion5 = 124, + } +} diff --git a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs index 8b33e30fa..2d8685617 100644 --- a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs +++ b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs @@ -19,7 +19,16 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Initializes a new instance of the class. /// /// The metadata to create an instance from. - private BmpMetaData(BmpMetaData other) => this.BitsPerPixel = other.BitsPerPixel; + private BmpMetaData(BmpMetaData other) + { + this.BitsPerPixel = other.BitsPerPixel; + this.InfoHeaderType = other.InfoHeaderType; + } + + /// + /// Gets or sets the bitmap info header type. + /// + public BmpInfoHeaderType InfoHeaderType { get; set; } /// /// Gets or sets the number of bits per pixel. diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 251475567..60e45ae35 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -4,6 +4,9 @@ using System.IO; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; + using Xunit; // ReSharper disable InconsistentNaming @@ -19,6 +22,8 @@ namespace SixLabors.ImageSharp.Tests public static readonly string[] AllBmpFiles = All; + public static readonly string[] BitfieldsBmpFiles = BitFields; + public static readonly TheoryData RatioFiles = new TheoryData { @@ -34,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests { using (Image image = provider.GetImage(new BmpDecoder())) { - image.DebugSave(provider, "bmp"); + image.DebugSave(provider); if (TestEnvironment.IsWindows) { @@ -44,17 +49,47 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [WithFile(F, CommonNonDefaultPixelTypes)] - public void BmpDecoder_IsNotBoundToSinglePixelType(TestImageProvider provider) + [WithFileCollection(nameof(BitfieldsBmpFiles), PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeBitfields(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage(new BmpDecoder())) { - image.DebugSave(provider, "bmp"); + image.DebugSave(provider); image.CompareToOriginal(provider); } } + [Theory] + [WithFile(Bit32Rgba, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeBitmap_WithAlphaChannel(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, new MagickReferenceDecoder()); + } + } + + [Theory] + [WithFile(Rgba321010102, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeBitfields_WithUnusualBitmasks(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + + // Choosing large tolerance of 6.1 here, because for some reason with the MagickReferenceDecoder the alpha channel + // seems to be wrong. This bitmap has an alpha channel of two bits. In many cases this alpha channel has a value of 3, + // which should be remapped to 255 for RGBA32, but the magick decoder has a value of 191 set. + // The total difference without the alpha channel is still: 0.0204% + // Exporting the image as PNG with GIMP yields to the same result as the imagesharp implementation. + image.CompareToOriginal(provider, ImageComparer.TolerantPercentage(6.1f), new MagickReferenceDecoder()); + } + } + [Theory] [WithFile(WinBmpv2, PixelTypes.Rgba32)] public void BmpDecoder_CanDecodeBmpv2(TestImageProvider provider) @@ -62,7 +97,67 @@ namespace SixLabors.ImageSharp.Tests { using (Image image = provider.GetImage(new BmpDecoder())) { - image.DebugSave(provider, "png"); + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFile(WinBmpv3, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeBmpv3(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFile(Rgba32bf56, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeAdobeBmpv3(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, new MagickReferenceDecoder()); + } + } + + [Theory] + [WithFile(WinBmpv4, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeBmpv4(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFile(WinBmpv5, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeBmpv5(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFile(F, CommonNonDefaultPixelTypes)] + public void BmpDecoder_IsNotBoundToSinglePixelType(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); image.CompareToOriginal(provider); } } @@ -74,7 +169,7 @@ namespace SixLabors.ImageSharp.Tests { using (Image image = provider.GetImage(new BmpDecoder())) { - image.DebugSave(provider, "png"); + image.DebugSave(provider); image.CompareToOriginal(provider); } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 8d8a32fba..5ecc26657 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -205,12 +205,36 @@ namespace SixLabors.ImageSharp.Tests public const string Bit16 = "Bmp/test16.bmp"; public const string Bit16Inverted = "Bmp/test16-inverted.bmp"; public const string Bit32Rgb = "Bmp/rgb32.bmp"; - + public const string Bit32Rgba = "Bmp/rgba32.bmp"; + // Note: This format can be called OS/2 BMPv1, or Windows BMPv2 public const string WinBmpv2 = "Bmp/pal8os2v1_winv2.bmp"; + public const string WinBmpv3 = "Bmp/rgb24.bmp"; + public const string WinBmpv4 = "Bmp/pal8v4.bmp"; + public const string WinBmpv5 = "Bmp/pal8v5.bmp"; public const string Bit8Palette4 = "Bmp/pal8-0.bmp"; public const string Os2v2Short = "Bmp/pal8os2v2-16.bmp"; + // Bitmap images with compression type BITFIELDS + public const string Rgb32bfdef = "Bmp/rgb32bfdef.bmp"; + public const string Rgb32bf = "Bmp/rgb32bf.bmp"; + public const string Rgb16565 = "Bmp/rgb16-565.bmp"; + public const string Rgb16bfdef = "Bmp/rgb16bfdef.bmp"; + public const string Rgb16565pal = "Bmp/rgb16-565pal.bmp"; + public const string Issue735 = "Bmp/issue735.bmp"; + public const string Rgba32bf56 = "Bmp/rgba32h56.bmp"; + public const string Rgba321010102 = "Bmp/rgba32-1010102.bmp"; + + public static readonly string[] BitFields + = { + Rgb32bfdef, + Rgb32bf, + Rgb16565, + Rgb16bfdef, + Rgb16565pal, + Issue735, + }; + public static readonly string[] All = { Car, @@ -225,7 +249,8 @@ namespace SixLabors.ImageSharp.Tests Bit8, Bit8Inverted, Bit16, - Bit16Inverted + Bit16Inverted, + Bit32Rgb }; } diff --git a/tests/Images/Input/Bmp/issue735.bmp b/tests/Images/Input/Bmp/issue735.bmp new file mode 100644 index 0000000000000000000000000000000000000000..31fadfcf5ad3513de36517603b39c2ce618d9fe2 GIT binary patch literal 1334298 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

B^TrIxe7B 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 Z8GA6-z_oBqq6aMNTT>=42(&8%{vWj_xZ3~# literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/pal8v4.bmp b/tests/Images/Input/Bmp/pal8v4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..34ebb8030c5f579b9f2a5fdcf95e506fa9e65cf3 GIT binary patch literal 9322 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 RsyqOayU{so7lFE0Q9 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/pal8v5.bmp b/tests/Images/Input/Bmp/pal8v5.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c54647a31a7c336ceb253275a24d65c737e65304 GIT binary patch literal 9338 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 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/rgb16-565pal.bmp b/tests/Images/Input/Bmp/rgb16-565pal.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e7632e344b26db844253fff783bca63a6fd944fb GIT binary patch literal 17474 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

3ti*QE>6#EL7i&iwR zY+Kd2`nv(}fyTqD5C%ve^LWcD8v{ol*LbfgUjw2KDL$Yo#D*FinZx{?V3Qo2mXrCJ zW5WwB&JlhV*@%NBIkM0F>i=u{f$*Gv zw%yzJ@1T(xJ5L5A?z$X!V>f$GUXWt`dxasQea)e5`#Zx1)c>pclgj!(!#<-t<359w z;7VvE{1Rv>zLZ{CR0=C2lrhQ#WvJ)m=d9<_=jigla(20_93u=C<_f!nwiTfjc@^@C z1L_C0D0+tssV0XlXjVt;!kr@A=u3~Tirjc?8)NtJ{ZX`NM$F0BMCRoaH%_uo<;C&h zi%$#Bh!UF5wk38ZeIE^cp{L>1h|x%2^V62qHlrPVT~B*e`;I31l1>Lyhs>t#jm%|! zNtm6yH!U~w3uiWOZ*i{hi)glZuOwIYMb1*(o#@FerfP08Rg=k74V%dx0RK7l^I8}5 zE*f4kNw&Cbb;T~lDb?-j(rc@(Z%o^EWB1Md>9h<6>*TG(+m|zMu-RF8*}NRZ{O^eF zHgnqYI`aq2uWG;5&wjg~JyT)-%U_ADq*QV%Ayv34S{1(vT8*!!R~J>oY6vxq8bJ-} z1^ET*h4clwHn5gmE33tbfoC7k^RA|7-KNw(p(t0rCH?zT01qt*6v;>me_3FKI9NFQENaqF#|-v0h1Ep_>Am*iEt~OmlE^ZgW?&tvFPiCzgwWhMM*u{lP{M(;?H< ztu^eS&YJE+mknDD+cbQ;)*kIJ_z|7sBTnfijl44Ire2nQK7wx`7+o=@Zmf8m#874= z9}8AM6W}ipW05P&6D(iYjCEY$n&9=qcPw!QDIwrRh%I$rt*iZ>)jT9Ix4WeKWz zo}ilY1l0%=`bObz!M0FZxGj)YTq~`W-wJ(=e@%Z~^cwbt@P_e5@CNmk{Fe1r`WF2z z@E!Y|>>Z{pxGlG>tIbvtD#??`B@P-`ZAbliM)OT^)19oH?OmMl?yk!gtX{Z@u-$Es zdzi-&&*NUF79}mdvgGE{tY!J$d>?^t#qzop;+2wBveoi&U?ub{ycRJIxzhZsWv$IP z$Ca*Uy=r~O5m%DV2GoYkrG`dwnBNlSCWoeRGQV-=@H&Fsn{gul@m8lW}V89VJ$_XNA-{b_lb-#K=? z{l$60?;<<#eo3C}yIiWcH{FvD399*+pqkEv{*fu`|A+o_8t1hy=wCFtWSTtvvh@}F z6z5d;tIMvfzP>4K`;9#}!_tpr9A}-nm2~?`=1q21R(>`=N03`_r|zzpqnLmGfcaJJ zANtup{=?pxAX7x)|AhTS`NaJM`HcHa`^^6g{eu5O|5Ee?)RyOzB_dg!+z70OCc*0vM#$CXNtSgs zMvkjplf3GDjfksBNda{s_SCS*e5O3XJ~=EcKU2=J=Y?yr})#{B~AKp<>SrHELr|1 a{%66Limtk^;%}1giun(O|9ACD|NjBiCyNsR literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/rgb16bfdef.bmp b/tests/Images/Input/Bmp/rgb16bfdef.bmp new file mode 100644 index 0000000000000000000000000000000000000000..30fe8bb8d6c920dda30b65f074ed9ef85945a610 GIT binary patch literal 16450 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"mu_?!W|wJoS$3E0bUAL9>vh!xeBTvde0)4S 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

1=bCn| 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 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/rgba32-1010102.bmp b/tests/Images/Input/Bmp/rgba32-1010102.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1a918cebf5caf486faafaf3488ef4be712b09aab GIT binary patch literal 32650 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 INi+2S0m0w)Jpcdz literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/rgba32.bmp b/tests/Images/Input/Bmp/rgba32.bmp new file mode 100644 index 0000000000000000000000000000000000000000..829c7c7e345cb6543affe69ce00f17b16a71ab31 GIT binary patch literal 32650 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 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/rgba32h56.bmp b/tests/Images/Input/Bmp/rgba32h56.bmp new file mode 100644 index 0000000000000000000000000000000000000000..343baa3300f331aaeabeb40d8fcd2f232393e815 GIT binary patch literal 32582 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 Date: Sun, 20 Jan 2019 07:54:47 +0100 Subject: [PATCH 013/223] Added support for RLE4 encoded bitmaps (#812) --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 132 +++++++++++++++++- .../Formats/Bmp/BmpDecoderTests.cs | 2 +- .../Formats/Bmp/BmpEncoderTests.cs | 2 +- tests/ImageSharp.Tests/TestImages.cs | 10 +- tests/Images/Input/Bmp/pal4rle.bmp | Bin 0 -> 3836 bytes 5 files changed, 135 insertions(+), 11 deletions(-) create mode 100644 tests/Images/Input/Bmp/pal4rle.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 362fe6443..8ca698b87 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -157,7 +157,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp break; case BmpCompression.RLE8: - this.ReadRle8(pixels, palette, this.infoHeader.Width, this.infoHeader.Height, inverted); + case BmpCompression.RLE4: + this.ReadRle(this.infoHeader.Compression, pixels, palette, this.infoHeader.Width, this.infoHeader.Height, inverted); break; @@ -254,22 +255,31 @@ namespace SixLabors.ImageSharp.Formats.Bmp } ///

- /// Looks up color values and builds the image from de-compressed RLE8 data. + /// Looks up color values and builds the image from de-compressed RLE8 or RLE4 data. /// Compressed RLE8 stream is uncompressed by + /// Compressed RLE4 stream is uncompressed by /// /// The pixel format. + /// The compression type. Either RLE4 or RLE8. /// The to assign the palette to. /// The containing the colors. /// The width of the bitmap. /// The height of the bitmap. /// Whether the bitmap is inverted. - private void ReadRle8(Buffer2D pixels, byte[] colors, int width, int height, bool inverted) + private void ReadRle(BmpCompression compression, Buffer2D pixels, byte[] colors, int width, int height, bool inverted) where TPixel : struct, IPixel { TPixel color = default; using (Buffer2D buffer = this.memoryAllocator.Allocate2D(width, height, AllocationOptions.Clean)) { - this.UncompressRle8(width, buffer.GetSpan()); + if (compression == BmpCompression.RLE8) + { + this.UncompressRle8(width, buffer.GetSpan()); + } + else + { + this.UncompressRle4(width, buffer.GetSpan()); + } for (int y = 0; y < height; y++) { @@ -287,12 +297,122 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - /// Produce uncompressed bitmap data from RLE8 stream. + /// Produce uncompressed bitmap data from a RLE4 stream. + /// + /// + /// RLE4 is a 2-byte run-length encoding. + ///
If first byte is 0, the second byte may have special meaning. + ///
Otherwise, the first byte is the length of the run and second byte contains two color indexes. + ///
+ /// The width of the bitmap. + /// Buffer for uncompressed data. + private void UncompressRle4(int w, Span buffer) + { +#if NETCOREAPP2_1 + Span cmd = stackalloc byte[2]; +#else + byte[] cmd = new byte[2]; +#endif + int count = 0; + + while (count < buffer.Length) + { + if (this.stream.Read(cmd, 0, cmd.Length) != 2) + { + throw new Exception("Failed to read 2 bytes from the stream"); + } + + if (cmd[0] == RleCommand) + { + switch (cmd[1]) + { + case RleEndOfBitmap: + return; + + case RleEndOfLine: + int extra = count % w; + if (extra > 0) + { + count += w - extra; + } + + break; + + case RleDelta: + int dx = this.stream.ReadByte(); + int dy = this.stream.ReadByte(); + count += (w * dy) + dx; + + break; + + default: + // If the second byte > 2, we are in 'absolute mode'. + // The second byte contains the number of color indexes that follow. + int max = cmd[1]; + int bytesToRead = (max + 1) / 2; + + byte[] run = new byte[bytesToRead]; + + this.stream.Read(run, 0, run.Length); + + int idx = 0; + for (int i = 0; i < max; i++) + { + byte twoPixels = run[idx]; + if (i % 2 == 0) + { + byte leftPixel = (byte)((twoPixels >> 4) & 0xF); + buffer[count++] = leftPixel; + } + else + { + byte rightPixel = (byte)(twoPixels & 0xF); + buffer[count++] = rightPixel; + idx++; + } + } + + // Absolute mode data is aligned to two-byte word-boundary + int padding = bytesToRead & 1; + + this.stream.Skip(padding); + + break; + } + } + else + { + int max = cmd[0]; + + // The second byte contains two color indexes, one in its high-order 4 bits and one in its low-order 4 bits. + byte twoPixels = cmd[1]; + byte rightPixel = (byte)(twoPixels & 0xF); + byte leftPixel = (byte)((twoPixels >> 4) & 0xF); + + for (int idx = 0; idx < max; idx++) + { + if (idx % 2 == 0) + { + buffer[count] = leftPixel; + } + else + { + buffer[count] = rightPixel; + } + + count++; + } + } + } + } + + /// + /// Produce uncompressed bitmap data from a RLE8 stream. /// /// /// RLE8 is a 2-byte run-length encoding. ///
If first byte is 0, the second byte may have special meaning. - ///
Otherwise, first byte is the length of the run and second byte is the color for the run. + ///
Otherwise, the first byte is the length of the run and second byte is the color for the run. ///
/// The width of the bitmap. /// Buffer for uncompressed data. diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 60e45ae35..0ebfbf311 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Tests { { TestImages.Bmp.Car, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, { TestImages.Bmp.V5Header, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, - { TestImages.Bmp.RLE, 2835, 2835, PixelResolutionUnit.PixelsPerMeter } + { TestImages.Bmp.RLE8, 2835, 2835, PixelResolutionUnit.PixelsPerMeter } }; [Theory] diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index b9f855cf1..f818be8a9 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests { { TestImages.Bmp.Car, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, { TestImages.Bmp.V5Header, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, - { TestImages.Bmp.RLE, 2835, 2835, PixelResolutionUnit.PixelsPerMeter } + { TestImages.Bmp.RLE8, 2835, 2835, PixelResolutionUnit.PixelsPerMeter } }; public static readonly TheoryData BmpBitsPerPixelFiles = diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 5ecc26657..6e6c7ce47 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -195,7 +195,8 @@ namespace SixLabors.ImageSharp.Tests public const string NegHeight = "Bmp/neg_height.bmp"; public const string CoreHeader = "Bmp/BitmapCoreHeaderQR.bmp"; public const string V5Header = "Bmp/BITMAPV5HEADER.bmp"; - public const string RLE = "Bmp/RunLengthEncoded.bmp"; + public const string RLE8 = "Bmp/RunLengthEncoded.bmp"; + public const string RLE4 = "Bmp/pal4rle.bmp"; public const string RLEInverted = "Bmp/RunLengthEncoded-inverted.bmp"; public const string Bit1 = "Bmp/pal1.bmp"; public const string Bit1Pal1 = "Bmp/pal1p1.bmp"; @@ -209,6 +210,7 @@ namespace SixLabors.ImageSharp.Tests // Note: This format can be called OS/2 BMPv1, or Windows BMPv2 public const string WinBmpv2 = "Bmp/pal8os2v1_winv2.bmp"; + public const string WinBmpv3 = "Bmp/rgb24.bmp"; public const string WinBmpv4 = "Bmp/pal8v4.bmp"; public const string WinBmpv5 = "Bmp/pal8v5.bmp"; @@ -218,8 +220,8 @@ namespace SixLabors.ImageSharp.Tests // Bitmap images with compression type BITFIELDS public const string Rgb32bfdef = "Bmp/rgb32bfdef.bmp"; public const string Rgb32bf = "Bmp/rgb32bf.bmp"; - public const string Rgb16565 = "Bmp/rgb16-565.bmp"; public const string Rgb16bfdef = "Bmp/rgb16bfdef.bmp"; + public const string Rgb16565 = "Bmp/rgb16-565.bmp"; public const string Rgb16565pal = "Bmp/rgb16-565pal.bmp"; public const string Issue735 = "Bmp/issue735.bmp"; public const string Rgba32bf56 = "Bmp/rgba32h56.bmp"; @@ -241,7 +243,9 @@ namespace SixLabors.ImageSharp.Tests F, NegHeight, CoreHeader, - V5Header, RLE, + V5Header, + RLE4, + RLE8, RLEInverted, Bit1, Bit1Pal1, diff --git a/tests/Images/Input/Bmp/pal4rle.bmp b/tests/Images/Input/Bmp/pal4rle.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a5672aebd6247351172b0f602197611554de8e1f GIT binary patch literal 3836 zcmb`J(NE*p6~@2V_&Sbn3u>v1^8d9M89K`5N3ASRxOtsJJ-JFoZtD*y*Jx`{#Oy{ zUyq-4_V3xZ*mGEb#_I{6m+h=SCV^N!PG9RA=}4?nNrDk%iD$7r4`q7HBV{MVR({Ia>8~~-$H5udLK)s(8_qz zec;W{5of%#T^M*7u>%z7b;c~uTHaICB~pj<90$f4HskU6xho^m`qEC14$?Q8Zrn6# z_$J=%c0+fr1)-a9K-HP0D@Z2zgotKMTpp~h6%UIYEc8z^&F{5UdzL280u@S!9)$m$y2{hE zhn{0iq5MeOylAUjE)j~y(q(3N~tI>JZEc4hr{$!oL^0WatUX-YvR9rNO#}h1rwWEijNjbvP(*p#&(?gf}T&wvt zzq{vI((2Pj6SA{R*X9bPaG3(Wua1w7u?Vh2V8PopyFvj2rBp2|s}{AUVJXomM;IdE zB#Y`PuFS;*ZquId-5PAJi!ch5rPZ^Jh59}3bbV5g1WU{{jabJ=;GV$&&$TCd<#(>p zeIc|9o<#6!N*oI@U3>w2n@qSU6J*G8!~~vB!tlusXjwu zRmYiMP5jnsP42Ve(Is<}8;ztmKC>rud%odqem^Atq=w;>E8 zdUq1m4hL#3cj8Rz64PVoD6_gEqBGgd^{<%Sh?62Jejs~r#$Cc!joGSvCVMUtISQ#_ zBxXlpA$?agUBWZ!snYWx<$GBwv5K3a8`IB3Lg5J(WnKsw(4Fk0OH3G-1XRR*Anmze zrYBEJfzUv^MNSwYAsIswt~3yq>6ad7m-0>MQJD9!kjA(`vkfXrCpH-~rhxaPHCS2r z@}7*RXI{8C{tdZ2&Y1lR7t=*s^uI*@tWiAfHKk^Wbj>JKKK{rlKYCTq7yTQY#mfo1 zJ+bn`&bSKh zQ$D9?F%r?_;J}_F5L6U=e^RE3b8Wvnrdl z{VpGAb=ofe6m=}r%rvv}o0K?#KRQu_&4@X!I0Uny#Z)ymB1Z6v0c0Um>OTF*DlaAz zEzP+a@fV52kXGzerIM(_tj{Z~Ndej*?*z)%P7DP*ut_ZAQV&A=a^^~CrOJxj_FPyI zj1iQgD>^gkZd!p~@!375Tsi-dzAG?%u}tQr52WP&KwY`7{<`7MHBPg0def+|m|HQP zOV#jri(rmy#cU0pqm-?YPqZxh+K*Nhdc3tX<>BcYg&g1enlxq(8)&v#Uet<)@$Kz+ z+sj()#iMw1!&6q_C4#}giw03UzPj2CsoY9LnETGy9+={gm7#w;%WuPsx8tp%kClvz zzdP)P)Qz{lKSw5%_jIPv#n&)ym#apsKG;eR%({$Sz_|LtgPkVQHR=zV3EyJXiAAe? zAnR1fjQiS<`cP4hYZ9)Lb8=<9U1?V~8Xx@R<8l=$zKLPn;7>i(Q-}FseOP}j&-UxA za?8!4EKzL7FmGV=dVJo~17pbN!|UXV&+SZA zec)Ot^>mH?yslW-^QUV=u_WUtWcbR#A9Cd~;oHRDOg?t1S=*`Z_=%r%dz}}5L1(yo^J|3n z+`ehw68j_84DCZ*CYQXk=))2pBi2`f)kkPvL*Tx5O6#S!&9}{W(M5a_C%2vL&i19W zSXy$^JNV(?BsdA)N7wOnoLuqrnQu(9P484!y=z~WDbICg)q^j!u@S5NF%cMa{ zJz^zmk>W3vi2H)!z|qSu%GSo_CePFh=>Ej$z^Zn3I{bdA`D!N}>%qw%es^fSe)ERo z*E|9ezhU~c6icUF*1P0^krdvwvrIT06d21a7mTLxe)yBwsHfQ|JI=cEcKz-8MOfJ6 kubxT1!yr1BTg4r$B>(Ik_P%2fe|wF>8+b|b*^18n8}acBDF6Tf literal 0 HcmV?d00001 From b03d41bbb92e57bc2eab3285decd8f4d07856963 Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Wed, 23 Jan 2019 13:22:58 +0100 Subject: [PATCH 014/223] Adds support for OS/2 version 2 bitmaps (#813) * Added support for OS/2 version 2 bitmaps * throw NotSupportedException, if the file header type is not BM * renamed Os2v2 to Os2v2Size * Added BmpThrowHelper similar to the JpegThrowHelper --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 41 ++++++++----- src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs | 54 +++++++++++++++++- src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs | 28 +++++++++ .../Formats/Bmp/BmpDecoderTests.cs | 18 +++++- tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Bmp/pal8os2v2.bmp | Bin 0 -> 9278 bytes 6 files changed, 126 insertions(+), 16 deletions(-) create mode 100644 src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs create mode 100644 tests/Images/Input/Bmp/pal8os2v2.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 8ca698b87..6bfdfa3a2 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -168,7 +168,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp break; default: - throw new NotSupportedException("Does not support this kind of bitmap files."); + BmpThrowHelper.ThrowNotSupportedException("Does not support this kind of bitmap files."); + + break; } return image; @@ -319,7 +321,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp { if (this.stream.Read(cmd, 0, cmd.Length) != 2) { - throw new Exception("Failed to read 2 bytes from the stream"); + BmpThrowHelper.ThrowImageFormatException("Failed to read 2 bytes from the stream while uncompressing RLE4 bitmap."); } if (cmd[0] == RleCommand) @@ -429,7 +431,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp { if (this.stream.Read(cmd, 0, cmd.Length) != 2) { - throw new Exception("Failed to read 2 bytes from stream"); + BmpThrowHelper.ThrowImageFormatException("Failed to read 2 bytes from stream while uncompressing RLE8 bitmap."); } if (cmd[0] == RleCommand) @@ -913,7 +915,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp int headerSize = BinaryPrimitives.ReadInt32LittleEndian(buffer); if (headerSize < BmpInfoHeader.CoreSize) { - throw new NotSupportedException($"ImageSharp does not support this BMP file. HeaderSize: {headerSize}."); + BmpThrowHelper.ThrowNotSupportedException($"ImageSharp does not support this BMP file. HeaderSize is '{headerSize}'."); } int skipAmount = 0; @@ -926,23 +928,23 @@ namespace SixLabors.ImageSharp.Formats.Bmp // read the rest of the header this.stream.Read(buffer, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize); - BmpInfoHeaderType inofHeaderType = BmpInfoHeaderType.WinVersion2; + BmpInfoHeaderType infoHeaderType = BmpInfoHeaderType.WinVersion2; if (headerSize == BmpInfoHeader.CoreSize) { // 12 bytes - inofHeaderType = BmpInfoHeaderType.WinVersion2; + infoHeaderType = BmpInfoHeaderType.WinVersion2; this.infoHeader = BmpInfoHeader.ParseCore(buffer); } else if (headerSize == BmpInfoHeader.Os22ShortSize) { // 16 bytes - inofHeaderType = BmpInfoHeaderType.Os2Version2Short; + infoHeaderType = BmpInfoHeaderType.Os2Version2Short; this.infoHeader = BmpInfoHeader.ParseOs22Short(buffer); } else if (headerSize == BmpInfoHeader.SizeV3) { // == 40 bytes - inofHeaderType = BmpInfoHeaderType.WinVersion3; + infoHeaderType = BmpInfoHeaderType.WinVersion3; this.infoHeader = BmpInfoHeader.ParseV3(buffer); // if the info header is BMP version 3 and the compression type is BITFIELDS, @@ -960,24 +962,30 @@ namespace SixLabors.ImageSharp.Formats.Bmp else if (headerSize == BmpInfoHeader.AdobeV3Size) { // == 52 bytes - inofHeaderType = BmpInfoHeaderType.AdobeVersion3; + infoHeaderType = BmpInfoHeaderType.AdobeVersion3; this.infoHeader = BmpInfoHeader.ParseAdobeV3(buffer, withAlpha: false); } else if (headerSize == BmpInfoHeader.AdobeV3WithAlphaSize) { // == 56 bytes - inofHeaderType = BmpInfoHeaderType.AdobeVersion3WithAlpha; + infoHeaderType = BmpInfoHeaderType.AdobeVersion3WithAlpha; this.infoHeader = BmpInfoHeader.ParseAdobeV3(buffer, withAlpha: true); } + else if (headerSize == BmpInfoHeader.Os2v2Size) + { + // == 64 bytes + infoHeaderType = BmpInfoHeaderType.Os2Version2; + this.infoHeader = BmpInfoHeader.ParseOs2Version2(buffer); + } else if (headerSize >= BmpInfoHeader.SizeV4) { // >= 108 bytes - inofHeaderType = headerSize == BmpInfoHeader.SizeV4 ? BmpInfoHeaderType.WinVersion4 : BmpInfoHeaderType.WinVersion5; + infoHeaderType = headerSize == BmpInfoHeader.SizeV4 ? BmpInfoHeaderType.WinVersion4 : BmpInfoHeaderType.WinVersion5; this.infoHeader = BmpInfoHeader.ParseV4(buffer); } else { - throw new NotSupportedException($"ImageSharp does not support this BMP file. HeaderSize: {headerSize}."); + BmpThrowHelper.ThrowNotSupportedException($"ImageSharp does not support this BMP file. HeaderSize '{headerSize}'."); } // Resolution is stored in PPM. @@ -1001,7 +1009,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp short bitsPerPixel = this.infoHeader.BitsPerPixel; this.bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance); - this.bmpMetaData.InfoHeaderType = inofHeaderType; + this.bmpMetaData.InfoHeaderType = infoHeaderType; // We can only encode at these bit rates so far. if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24) @@ -1027,6 +1035,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.stream.Read(buffer, 0, BmpFileHeader.Size); this.fileHeader = BmpFileHeader.Parse(buffer); + + if (this.fileHeader.Type != BmpConstants.TypeMarkers.Bitmap) + { + BmpThrowHelper.ThrowNotSupportedException($"ImageSharp does not support this BMP file. File header bitmap type marker '{this.fileHeader.Type}'."); + } } /// @@ -1080,7 +1093,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp // 256 * 4 if (colorMapSize > 1024) { - throw new ImageFormatException($"Invalid bmp colormap size '{colorMapSize}'"); + BmpThrowHelper.ThrowImageFormatException($"Invalid bmp colormap size '{colorMapSize}'"); } palette = new byte[colorMapSize]; diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs index 316df4acc..6da5f73e3 100644 --- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs @@ -41,6 +41,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public const int AdobeV3WithAlphaSize = 56; + /// + /// Size of a IBM OS/2 2.x bitmap header. + /// + public const int Os2v2Size = 64; + /// /// Defines the size of the BITMAPINFOHEADER (BMP Version 4) data structure in the bitmap file. /// @@ -117,7 +122,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - /// Gets or sets the size of this header + /// Gets or sets the size of this header. /// public int HeaderSize { get; set; } @@ -346,6 +351,53 @@ namespace SixLabors.ImageSharp.Formats.Bmp alphaMask: withAlpha ? BinaryPrimitives.ReadInt32LittleEndian(data.Slice(52, 4)) : 0); } + /// + /// Parses a OS/2 version 2 bitmap header (64 bytes). Only the first 40 bytes are parsed which are + /// very similar to the Bitmap v3 header. The other 24 bytes are ignored, but they do not hold any + /// useful information for decoding the image. + /// + /// The data to parse. + /// The parsed header. + /// + public static BmpInfoHeader ParseOs2Version2(ReadOnlySpan data) + { + var infoHeader = new BmpInfoHeader( + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), + height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), + planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), + bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(14, 2))); + + int compression = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(16, 4)); + + // The compression value in OS/2 bitmap has a different meaning than in windows bitmaps. + // Map the OS/2 value to the windows values. + switch (compression) + { + case 0: + infoHeader.Compression = BmpCompression.RGB; + break; + case 1: + infoHeader.Compression = BmpCompression.RLE8; + break; + case 2: + infoHeader.Compression = BmpCompression.RLE4; + break; + default: + BmpThrowHelper.ThrowImageFormatException($"Compression type is not supported. ImageSharp only supports uncompressed, RLE4 and RLE8."); + break; + } + + infoHeader.ImageSize = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(20, 4)); + infoHeader.XPelsPerMeter = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(24, 4)); + infoHeader.YPelsPerMeter = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(28, 4)); + infoHeader.ClrUsed = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(32, 4)); + infoHeader.ClrImportant = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(36, 4)); + + // The following 24 bytes of the header are omitted. + return infoHeader; + } + /// /// Parses the full BMP Version 4 BITMAPINFOHEADER header (108 bytes). /// diff --git a/src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs b/src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs new file mode 100644 index 000000000..dae044ddb --- /dev/null +++ b/src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs @@ -0,0 +1,28 @@ +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.Formats.Bmp +{ + internal static class BmpThrowHelper + { + /// + /// Cold path optimization for throwing -s + /// + /// The error message for the exception. + [MethodImpl(MethodImplOptions.NoInlining)] + public static void ThrowImageFormatException(string errorMessage) + { + throw new ImageFormatException(errorMessage); + } + + /// + /// Cold path optimization for throwing -s + /// + /// The error message for the exception. + [MethodImpl(MethodImplOptions.NoInlining)] + public static void ThrowNotSupportedException(string errorMessage) + { + throw new NotSupportedException(errorMessage); + } + } +} diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 0ebfbf311..5d7d35dd5 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -214,12 +214,28 @@ namespace SixLabors.ImageSharp.Tests { using (Image image = provider.GetImage(new BmpDecoder())) { - image.DebugSave(provider, "png"); + image.DebugSave(provider); // TODO: Neither System.Drawing not MagickReferenceDecoder // can correctly decode this file. // image.CompareToOriginal(provider); } } + + [Theory] + [WithFile(Os2v2, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_Os2v2Header(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + + // TODO: System.Drawing can not decode this image. MagickReferenceDecoder can decode it, + // but i think incorrectly. I have loaded the image with GIMP and exported as PNG. + // The results are the same as the image sharp implementation. + // image.CompareToOriginal(provider, new MagickReferenceDecoder()); + } + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 6e6c7ce47..d83fe4907 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -216,6 +216,7 @@ namespace SixLabors.ImageSharp.Tests public const string WinBmpv5 = "Bmp/pal8v5.bmp"; public const string Bit8Palette4 = "Bmp/pal8-0.bmp"; public const string Os2v2Short = "Bmp/pal8os2v2-16.bmp"; + public const string Os2v2 = "Bmp/pal8os2v2.bmp"; // Bitmap images with compression type BITFIELDS public const string Rgb32bfdef = "Bmp/rgb32bfdef.bmp"; diff --git a/tests/Images/Input/Bmp/pal8os2v2.bmp b/tests/Images/Input/Bmp/pal8os2v2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1324a40d00a417649e67f2c4eb8f23f9f7ee1c3d GIT binary patch literal 9278 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 SzpTmwAld81-vt=wE$hEMUm(B$ literal 0 HcmV?d00001 From 2849fd9c1dc19a7338235f6c33f4970e5a12dee3 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 25 Jan 2019 16:32:45 +1100 Subject: [PATCH 015/223] Update dependencies + fix stylecop (#816) --- .gitmodules | 3 + ImageSharp.sln | 5 +- .../ImageSharp.Drawing.csproj | 97 ++++++++++--------- .../Helpers/SimdUtils.ExtendedIntrinsics.cs | 5 +- src/ImageSharp/Common/Helpers/TestHelpers.cs | 2 +- .../ParallelExecutionSettings.cs | 2 +- .../Common/ParallelUtils/ParallelHelper.cs | 2 +- src/ImageSharp/Common/Tuples/Octet.cs | 5 +- src/ImageSharp/Common/Tuples/Vector4Pair.cs | 5 +- .../Formats/Bmp/BmpInfoHeaderType.cs | 5 +- src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs | 5 +- .../Formats/Gif/Sections/IGifExtension.cs | 5 +- .../Jpeg/Components/Decoder/ScanDecoder.cs | 3 +- .../Encoder/YCbCrForwardConverter{TPixel}.cs | 5 +- .../Formats/Jpeg/JpegEncoderCore.cs | 37 ++++++- .../Formats/Png/Chunks/PhysicalChunkData.cs | 5 +- .../Formats/Png/Filters/UpFilter.cs | 3 +- src/ImageSharp/Formats/Png/PngConstants.cs | 3 +- src/ImageSharp/ImageSharp.csproj | 21 ++-- src/ImageSharp/Memory/RowInterval.cs | 2 +- .../MetaData/Profiles/Exif/ExifConstants.cs | 6 +- .../MetaData/Profiles/Exif/ExifTags.cs | 2 +- .../TagDataEntries/IccLut16TagDataEntry.cs | 7 +- .../ICC/TagDataEntries/IccLut8TagDataEntry.cs | 7 +- .../Utils/Vector4Converters.Default.cs | 5 +- .../Utils/Vector4Converters.RgbaCompatible.cs | 5 +- standards | 1 + 27 files changed, 167 insertions(+), 86 deletions(-) create mode 160000 standards diff --git a/.gitmodules b/.gitmodules index e7972649f..37ef701cd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,6 @@ path = tests/Images/External url = https://github.com/SixLabors/Imagesharp.Tests.Images.git branch = master +[submodule "standards"] + path = standards + url = https://github.com/SixLabors/Standards diff --git a/ImageSharp.sln b/ImageSharp.sln index 8f3bc6860..3c3817bf6 100644 --- a/ImageSharp.sln +++ b/ImageSharp.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 15.0.26730.12 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{C317F1B1-D75E-4C6D-83EB-80367343E0D7}" ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig + standards\.editorconfig = standards\.editorconfig .travis.yml = .travis.yml appveyor.yml = appveyor.yml .github\ISSUE_TEMPLATE\ask-question.md = .github\ISSUE_TEMPLATE\ask-question.md @@ -15,12 +15,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt .github\CONTRIBUTING.md = .github\CONTRIBUTING.md .github\ISSUE_TEMPLATE\feature-request.md = .github\ISSUE_TEMPLATE\feature-request.md features.md = features.md - ImageSharp.ruleset = ImageSharp.ruleset ImageSharp.sln.DotSettings = ImageSharp.sln.DotSettings NuGet.config = NuGet.config .github\PULL_REQUEST_TEMPLATE.md = .github\PULL_REQUEST_TEMPLATE.md README.md = README.md run-tests.ps1 = run-tests.ps1 + standards\SixLabors.ruleset = standards\SixLabors.ruleset + standards\stylecop.json = standards\stylecop.json EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{815C0625-CD3D-440F-9F80-2D83856AB7AE}" diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index a6f529ee3..f4906d25e 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -1,50 +1,53 @@  - - SixLabors.ImageSharp.Drawing - SixLabors and contributors - Six Labors - Copyright (c) Six Labors and contributors. - SixLabors.ImageSharp - An extension to ImageSharp that allows the drawing of images, paths, and text. - en + + SixLabors.ImageSharp.Drawing + SixLabors and contributors + Six Labors + Copyright (c) Six Labors and contributors. + SixLabors.ImageSharp + An extension to ImageSharp that allows the drawing of images, paths, and text. + en - $(packageversion) - 0.0.1 - netstandard1.3;netstandard2.0 - 7.3 - true - true - SixLabors.ImageSharp.Drawing - SixLabors.ImageSharp.Drawing - Image Draw Shape Path Font - https://raw.githubusercontent.com/SixLabors/Branding/master/icons/imagesharp/sixlabors.imagesharp.128.png - https://github.com/SixLabors/ImageSharp - http://www.apache.org/licenses/LICENSE-2.0 - git - https://github.com/SixLabors/ImageSharp - full - portable - True - - - - - - - - - - - - - All - - - - ..\..\ImageSharp.ruleset - SixLabors.ImageSharp - - - true - + $(packageversion) + 0.0.1 + netstandard1.3;netstandard2.0 + 7.3 + true + true + SixLabors.ImageSharp.Drawing + SixLabors.ImageSharp.Drawing + Image Draw Shape Path Font + https://raw.githubusercontent.com/SixLabors/Branding/master/icons/imagesharp/sixlabors.imagesharp.128.png + https://github.com/SixLabors/ImageSharp + http://www.apache.org/licenses/LICENSE-2.0 + git + https://github.com/SixLabors/ImageSharp + full + portable + True + + + + + + + + + + + + + + + + + + + ..\..\standards\SixLabors.ruleset + SixLabors.ImageSharp + + + + true + \ No newline at end of file diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs index 9aeb20931..83216aaa7 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/ImageSharp/Common/Helpers/TestHelpers.cs b/src/ImageSharp/Common/Helpers/TestHelpers.cs index fd16a577a..d330233c4 100644 --- a/src/ImageSharp/Common/Helpers/TestHelpers.cs +++ b/src/ImageSharp/Common/Helpers/TestHelpers.cs @@ -1,4 +1,4 @@ -// Copyright(c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. namespace SixLabors.ImageSharp.Common.Helpers diff --git a/src/ImageSharp/Common/ParallelUtils/ParallelExecutionSettings.cs b/src/ImageSharp/Common/ParallelUtils/ParallelExecutionSettings.cs index 0b45719c3..40163bc78 100644 --- a/src/ImageSharp/Common/ParallelUtils/ParallelExecutionSettings.cs +++ b/src/ImageSharp/Common/ParallelUtils/ParallelExecutionSettings.cs @@ -1,4 +1,4 @@ -// Copyright(c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System.Threading.Tasks; diff --git a/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs b/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs index 782333219..a930b8390 100644 --- a/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs +++ b/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs @@ -1,4 +1,4 @@ -// Copyright(c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; diff --git a/src/ImageSharp/Common/Tuples/Octet.cs b/src/ImageSharp/Common/Tuples/Octet.cs index 539b74e32..23faf08ae 100644 --- a/src/ImageSharp/Common/Tuples/Octet.cs +++ b/src/ImageSharp/Common/Tuples/Octet.cs @@ -1,4 +1,7 @@ -using System.Runtime.CompilerServices; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.Tuples diff --git a/src/ImageSharp/Common/Tuples/Vector4Pair.cs b/src/ImageSharp/Common/Tuples/Vector4Pair.cs index 2e5ca3137..b3a32deee 100644 --- a/src/ImageSharp/Common/Tuples/Vector4Pair.cs +++ b/src/ImageSharp/Common/Tuples/Vector4Pair.cs @@ -1,4 +1,7 @@ -using System.Numerics; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeaderType.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeaderType.cs index a4ce0115f..a92a19d9b 100644 --- a/src/ImageSharp/Formats/Bmp/BmpInfoHeaderType.cs +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeaderType.cs @@ -1,4 +1,7 @@ -namespace SixLabors.ImageSharp.Formats.Bmp +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Bmp { /// /// Enum value for the different bitmap info header types. The enum value is the number of bytes for the specific bitmap header. diff --git a/src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs b/src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs index dae044ddb..443471404 100644 --- a/src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs +++ b/src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Formats.Bmp diff --git a/src/ImageSharp/Formats/Gif/Sections/IGifExtension.cs b/src/ImageSharp/Formats/Gif/Sections/IGifExtension.cs index 2fdc233b0..c8bd28674 100644 --- a/src/ImageSharp/Formats/Gif/Sections/IGifExtension.cs +++ b/src/ImageSharp/Formats/Gif/Sections/IGifExtension.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; namespace SixLabors.ImageSharp.Formats.Gif { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs index 48abca2a4..a1c1b023e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs @@ -474,7 +474,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder Unsafe.Add(ref blockDataRef, zig) = (short)this.ExtendReceive(s); } } - } while (k < 64); + } + while (k < 64); } private void DecodeBlockProgressiveDC( diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs index d775425c5..301079b6a 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index 0dcbd8fef..b3f30f815 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -547,7 +547,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private void WriteDefineHuffmanTables(int componentCount) { // Table identifiers. - Span headers = stackalloc byte[] { 0x00, 0x10, 0x01, 0x11 }; + Span headers = stackalloc byte[] + { + 0x00, + 0x10, + 0x01, + 0x11 + }; int markerlen = 2; HuffmanSpec[] specs = HuffmanSpec.TheHuffmanSpecs; @@ -786,16 +792,37 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private void WriteStartOfFrame(int width, int height, int componentCount) { // "default" to 4:2:0 - Span subsamples = stackalloc byte[] { 0x22, 0x11, 0x11 }; - Span chroma = stackalloc byte[] { 0x00, 0x01, 0x01 }; + Span subsamples = stackalloc byte[] + { + 0x22, + 0x11, + 0x11 + }; + + Span chroma = stackalloc byte[] + { + 0x00, + 0x01, + 0x01 + }; switch (this.subsample) { case JpegSubsample.Ratio444: - subsamples = stackalloc byte[] { 0x11, 0x11, 0x11 }; + subsamples = stackalloc byte[] + { + 0x11, + 0x11, + 0x11 + }; break; case JpegSubsample.Ratio420: - subsamples = stackalloc byte[] { 0x22, 0x11, 0x11 }; + subsamples = stackalloc byte[] + { + 0x22, + 0x11, + 0x11 + }; break; } diff --git a/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs b/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs index 6ab0dd657..1d0e280bd 100644 --- a/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs +++ b/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; using System.Buffers.Binary; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.MetaData; diff --git a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs index c6a297e33..5d9dc6a89 100644 --- a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs @@ -57,7 +57,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters // Up(x) = Raw(x) - Prior(x) resultBaseRef = 2; - for (int x = 0; x < scanline.Length; /* Note: ++x happens in the body to avoid one add operation */) { + for (int x = 0; x < scanline.Length; /* Note: ++x happens in the body to avoid one add operation */) + { byte scan = Unsafe.Add(ref scanBaseRef, x); byte above = Unsafe.Add(ref prevBaseRef, x); ++x; diff --git a/src/ImageSharp/Formats/Png/PngConstants.cs b/src/ImageSharp/Formats/Png/PngConstants.cs index 62a7b74ab..e1f978e1a 100644 --- a/src/ImageSharp/Formats/Png/PngConstants.cs +++ b/src/ImageSharp/Formats/Png/PngConstants.cs @@ -26,7 +26,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// public static readonly IEnumerable FileExtensions = new[] { "png" }; - public static readonly byte[] HeaderBytes = { + public static readonly byte[] HeaderBytes = + { 0x89, // Set the high bit. 0x50, // P 0x4E, // N diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 1cdee81a2..6ab609d5c 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -31,20 +31,17 @@ $(DefineConstants);SUPPORTS_EXTENDED_INTRINSICS - + - + + + + - - - - All - - @@ -52,14 +49,16 @@ - + - ..\..\ImageSharp.ruleset + ..\..\standards\SixLabors.ruleset SixLabors.ImageSharp + true + TextTemplatingFileGenerator @@ -122,6 +121,7 @@ TextTemplatingFileGenerator + True @@ -199,6 +199,7 @@ PorterDuffFunctions.Generated.tt + diff --git a/src/ImageSharp/Memory/RowInterval.cs b/src/ImageSharp/Memory/RowInterval.cs index 0750e0368..501ed5e69 100644 --- a/src/ImageSharp/Memory/RowInterval.cs +++ b/src/ImageSharp/Memory/RowInterval.cs @@ -1,4 +1,4 @@ -// Copyright(c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using SixLabors.Primitives; diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifConstants.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifConstants.cs index 555cadafe..fb2a893d1 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifConstants.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifConstants.cs @@ -5,14 +5,16 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif { internal static class ExifConstants { - public static readonly byte[] LittleEndianByteOrderMarker = { + public static readonly byte[] LittleEndianByteOrderMarker = + { (byte)'I', (byte)'I', 0x2A, 0x00, }; - public static readonly byte[] BigEndianByteOrderMarker = { + public static readonly byte[] BigEndianByteOrderMarker = + { (byte)'M', (byte)'M', 0x00, diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs index e497fc7fa..e999d00b8 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs @@ -238,7 +238,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif LensMake, LensModel, LensSerialNumber - }; + }; /// /// The collection of GPS tags diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs index dd180b299..415f6941e 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs @@ -13,7 +13,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// internal sealed class IccLut16TagDataEntry : IccTagDataEntry, IEquatable { - private static readonly float[,] IdentityMatrix = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; + private static readonly float[,] IdentityMatrix = + { + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 } + }; /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs index b345d14a5..04a49e316 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs @@ -13,7 +13,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// internal sealed class IccLut8TagDataEntry : IccTagDataEntry, IEquatable { - private static readonly float[,] IdentityMatrix = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; + private static readonly float[,] IdentityMatrix = + { + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 } + }; /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs index 139dbfa10..e784e3b5a 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs index 5609e606d..06c33d79c 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; diff --git a/standards b/standards new file mode 160000 index 000000000..dd83f6496 --- /dev/null +++ b/standards @@ -0,0 +1 @@ +Subproject commit dd83f649638c6333984a757c01be6ec294e6b63c From 9c48c190a2ccbb5f48160fbc45a0ef7a48f52e20 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 29 Jan 2019 10:16:31 +1100 Subject: [PATCH 016/223] Track input stream position on load. (#820) --- src/ImageSharp/IO/DoubleBufferedStreamReader.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ImageSharp/IO/DoubleBufferedStreamReader.cs b/src/ImageSharp/IO/DoubleBufferedStreamReader.cs index 94a2f2cbf..8530ecec5 100644 --- a/src/ImageSharp/IO/DoubleBufferedStreamReader.cs +++ b/src/ImageSharp/IO/DoubleBufferedStreamReader.cs @@ -42,6 +42,7 @@ namespace SixLabors.ImageSharp.IO public DoubleBufferedStreamReader(MemoryAllocator memoryAllocator, Stream stream) { this.stream = stream; + this.Position = (int)stream.Position; this.length = (int)stream.Length; this.managedBuffer = memoryAllocator.AllocateManagedByteBuffer(ChunkLength, AllocationOptions.Clean); this.bufferChunk = this.managedBuffer.Array; From 6a60638d5c39ecb3e8c203109e61648fd973ca7b Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Tue, 5 Feb 2019 02:41:26 +0100 Subject: [PATCH 017/223] Fix Decoding 8-Bit grayscale png's with alpha (#830) --- .../Formats/Png/PngScanlineProcessor.cs | 3 +- .../Formats/Png/PngDecoderTests.cs | 30 ++++++++++++++++++ tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Png/rollsroyce.png | Bin 0 -> 25400 bytes 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/Images/Input/Png/rollsroyce.png diff --git a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs index 4242b2d55..40c284117 100644 --- a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs +++ b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs @@ -240,9 +240,9 @@ namespace SixLabors.ImageSharp.Formats.Png else { Rgba32 rgba32 = default; + int offset = 0; for (int x = pixelOffset; x < header.Width; x += increment) { - int offset = x * bytesPerPixel; byte luminance = Unsafe.Add(ref scanlineSpanRef, offset); byte alpha = Unsafe.Add(ref scanlineSpanRef, offset + bytesPerSample); rgba32.R = luminance; @@ -252,6 +252,7 @@ namespace SixLabors.ImageSharp.Formats.Png pixel.FromRgba32(rgba32); Unsafe.Add(ref rowSpanRef, x) = pixel; + offset += bytesPerPixel; } } } diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index f51f9b6c5..1452f233b 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -67,6 +67,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png TestImages.Png.GrayTrns16BitInterlaced }; + public static readonly string[] TestImagesGrayAlpha8Bit = + { + TestImages.Png.GrayAlpha8Bit, + TestImages.Png.GrayAlpha8Bit2 + }; + public static readonly TheoryData RatioFiles = new TheoryData { @@ -123,6 +129,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } } + [Theory] + [WithFileCollection(nameof(TestImagesGrayAlpha8Bit), PixelTypes.Rgba32)] + public void Decoder_Gray8bitWithAlpha(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new PngDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, ImageComparer.Exact); + } + } + [Theory] [WithFileCollection(nameof(TestImagesGray16Bit), PixelTypes.Rgb48)] public void Decode_Gray16Bit(TestImageProvider provider) @@ -159,6 +177,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } } + [Theory] + [WithFile(TestImages.Png.GrayAlpha8Bit2, PixelTypes)] + public void Decoder_CanDecodeGrey8bitWithAlpha(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new PngDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, ImageComparer.Exact); + } + } + [Fact] public void Decode_IgnoreMetadataIsFalse_TextChunckIsRead() { diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index d83fe4907..92773df7e 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -29,6 +29,7 @@ namespace SixLabors.ImageSharp.Tests public const string Gray4Bpp = "Png/gray_4bpp.png"; public const string Gray16Bit = "Png/gray-16.png"; public const string GrayAlpha8Bit = "Png/gray-alpha-8.png"; + public const string GrayAlpha8Bit2 = "Png/rollsroyce.png"; public const string GrayAlpha16Bit = "Png/gray-alpha-16.png"; public const string GrayTrns16BitInterlaced = "Png/gray-16-tRNS-interlaced.png"; public const string Rgb24BppTrans = "Png/rgb-8-tRNS.png"; diff --git a/tests/Images/Input/Png/rollsroyce.png b/tests/Images/Input/Png/rollsroyce.png new file mode 100644 index 0000000000000000000000000000000000000000..7067372a2c247d4dd78d021e5f34d7a51af22a78 GIT binary patch literal 25400 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⪙6N+Jhf@*qv_Y#mrlPc<@jWQ_@LMoP5 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 literal 0 HcmV?d00001 From 637f76707b488f48d084a01326d89ce48db9fd0b Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Tue, 5 Feb 2019 05:33:16 +0100 Subject: [PATCH 018/223] Respecting fileHeader Offset, skipping bytes if necessary (#819) --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 11 +++++++++++ .../Formats/Bmp/BmpDecoderTests.cs | 12 ++++++++++++ tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Bmp/pal8offs.bmp | Bin 0 -> 9354 bytes 4 files changed, 24 insertions(+) create mode 100644 tests/Images/Input/Bmp/pal8offs.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 6bfdfa3a2..496a6df4a 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -1103,6 +1103,17 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.infoHeader.VerifyDimensions(); + int skipAmount = this.fileHeader.Offset - (int)this.stream.Position; + if ((skipAmount + (int)this.stream.Position) > this.stream.Length) + { + BmpThrowHelper.ThrowImageFormatException($"Invalid fileheader offset found. Offset is greater than the stream length."); + } + + if (skipAmount > 0) + { + this.stream.Skip(skipAmount); + } + return bytesPerColorMapEntry; } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 5d7d35dd5..e7b5aeaea 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -150,6 +150,18 @@ namespace SixLabors.ImageSharp.Tests } } + [Theory] + [WithFile(Pal8Offset, PixelTypes.Rgba32)] + public void BmpDecoder_RespectsFileHeaderOffset(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + [Theory] [WithFile(F, CommonNonDefaultPixelTypes)] public void BmpDecoder_IsNotBoundToSinglePixelType(TestImageProvider provider) diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 92773df7e..b4b75bfd8 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -218,6 +218,7 @@ namespace SixLabors.ImageSharp.Tests public const string Bit8Palette4 = "Bmp/pal8-0.bmp"; public const string Os2v2Short = "Bmp/pal8os2v2-16.bmp"; public const string Os2v2 = "Bmp/pal8os2v2.bmp"; + public const string Pal8Offset = "Bmp/pal8offs.bmp"; // Bitmap images with compression type BITFIELDS public const string Rgb32bfdef = "Bmp/rgb32bfdef.bmp"; diff --git a/tests/Images/Input/Bmp/pal8offs.bmp b/tests/Images/Input/Bmp/pal8offs.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8673e9740bef6f23bbb24e584c7585b3290b6662 GIT binary patch literal 9354 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 X@!8^Y$}g(&07&+F@x1`!oMrt7!#N>9 literal 0 HcmV?d00001 From 13ff434b9e1114a956d9b7807c2a771df653f0da Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Thu, 7 Feb 2019 00:57:43 +0100 Subject: [PATCH 019/223] Fix Decoding interlaced grayscale (#831) --- .../Formats/Png/PngScanlineProcessor.cs | 4 ++-- .../Formats/Png/PngDecoderTests.cs | 20 ++++++++++-------- tests/ImageSharp.Tests/TestImages.cs | 5 ++++- tests/Images/Input/Png/iftbbn0g01.png | Bin 0 -> 214 bytes tests/Images/Input/Png/iftbbn0g02.png | Bin 0 -> 211 bytes tests/Images/Input/Png/iftbbn0g04.png | Bin 0 -> 489 bytes 6 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 tests/Images/Input/Png/iftbbn0g01.png create mode 100644 tests/Images/Input/Png/iftbbn0g02.png create mode 100644 tests/Images/Input/Png/iftbbn0g04.png diff --git a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs index 40c284117..c23694951 100644 --- a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs +++ b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs @@ -145,9 +145,9 @@ namespace SixLabors.ImageSharp.Formats.Png { byte scaledLuminanceTrans = (byte)(luminanceTrans.PackedValue * scaleFactor); Rgba32 rgba32 = default; - for (int x = pixelOffset; x < header.Width; x += increment) + for (int x = pixelOffset, o = 0; x < header.Width; x += increment, o++) { - byte luminance = (byte)(Unsafe.Add(ref scanlineSpanRef, x) * scaleFactor); + byte luminance = (byte)(Unsafe.Add(ref scanlineSpanRef, o) * scaleFactor); rgba32.R = luminance; rgba32.G = luminance; rgba32.B = luminance; diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 1452f233b..eca7a2543 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -67,10 +67,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png TestImages.Png.GrayTrns16BitInterlaced }; - public static readonly string[] TestImagesGrayAlpha8Bit = + public static readonly string[] TestImagesGray8BitInterlaced = { - TestImages.Png.GrayAlpha8Bit, - TestImages.Png.GrayAlpha8Bit2 + TestImages.Png.GrayAlpha1BitInterlaced, + TestImages.Png.GrayAlpha2BitInterlaced, + TestImages.Png.Gray4BitInterlaced, + TestImages.Png.GrayAlpha8BitInterlaced }; public static readonly TheoryData RatioFiles = @@ -130,8 +132,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } [Theory] - [WithFileCollection(nameof(TestImagesGrayAlpha8Bit), PixelTypes.Rgba32)] - public void Decoder_Gray8bitWithAlpha(TestImageProvider provider) + [WithFileCollection(nameof(TestImagesGray8BitInterlaced), PixelTypes.Rgba32)] + public void Decoder_Gray8bitInterlaced(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage(new PngDecoder())) @@ -166,8 +168,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } [Theory] - [WithFile(TestImages.Png.Splash, PixelTypes)] - public void Decoder_IsNotBoundToSinglePixelType(TestImageProvider provider) + [WithFile(TestImages.Png.GrayAlpha8BitInterlaced, PixelTypes)] + public void Decoder_CanDecodeGrey8bitWithAlpha(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage(new PngDecoder())) @@ -178,8 +180,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } [Theory] - [WithFile(TestImages.Png.GrayAlpha8Bit2, PixelTypes)] - public void Decoder_CanDecodeGrey8bitWithAlpha(TestImageProvider provider) + [WithFile(TestImages.Png.Splash, PixelTypes)] + public void Decoder_IsNotBoundToSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage(new PngDecoder())) diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index b4b75bfd8..51e2d084c 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -29,7 +29,10 @@ namespace SixLabors.ImageSharp.Tests public const string Gray4Bpp = "Png/gray_4bpp.png"; public const string Gray16Bit = "Png/gray-16.png"; public const string GrayAlpha8Bit = "Png/gray-alpha-8.png"; - public const string GrayAlpha8Bit2 = "Png/rollsroyce.png"; + public const string GrayAlpha8BitInterlaced = "Png/rollsroyce.png"; + public const string GrayAlpha1BitInterlaced = "Png/iftbbn0g01.png"; + public const string GrayAlpha2BitInterlaced = "Png/iftbbn0g02.png"; + public const string Gray4BitInterlaced = "Png/iftbbn0g04.png"; public const string GrayAlpha16Bit = "Png/gray-alpha-16.png"; public const string GrayTrns16BitInterlaced = "Png/gray-16-tRNS-interlaced.png"; public const string Rgb24BppTrans = "Png/rgb-8-tRNS.png"; diff --git a/tests/Images/Input/Png/iftbbn0g01.png b/tests/Images/Input/Png/iftbbn0g01.png new file mode 100644 index 0000000000000000000000000000000000000000..6eb27d10e8d587875d1abf309b32591d573b7ea0 GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^3Lwk~Bp7wr%FhF7rjj7PUvHOsv8mycFdT%?VwTS?8OI)lN`3ceUp%TVw%dl6lUjrI}dZ;WI290Fis=;*St8< zcEdA2&o2}xQqNf*wpHxg%7n}A0<)ygNO@lVqqDNOhvVa?ztx`@lQdM8DRV!O1Uiku M)78&qol`;+0Qf*sZU6uP literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Png/iftbbn0g02.png b/tests/Images/Input/Png/iftbbn0g02.png new file mode 100644 index 0000000000000000000000000000000000000000..46ba4977792db7242ca14bd6b484424bd133284e GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^3Lwk`Bp9=o@yY{frjj7PU0gxFlL!dbcw$T{zIjBs)WP z{>HX0@k_>q?fVNd4~VM8l(NdkN663XEIFvVY7gtm6|BD9hhnzgmdK II;Vst00?1CAOHXW literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Png/iftbbn0g04.png b/tests/Images/Input/Png/iftbbn0g04.png new file mode 100644 index 0000000000000000000000000000000000000000..e9db0ad50d0b43fece4191d0cee877d179727461 GIT binary patch literal 489 zcmVD%0+%?m8{ukIf_cfIf76xL6xMlh8HQXmr+U zgHu`IDZOwFPOi$inM8OmiUyAd5k7MDe1U}Iu)(d(&>%vO8rB9Gb=|oYUkFP$XI4Do zX6~_Ke8jVOD<*u?tE>+_?9bDmOZF~l?DS9Q-I+;sMk8Z$C!TQ23#yh*E-ghTInPVs z*|xdA%+#v;V}>n6)vXhXb|8g!X74vFQKbno5O|crC(GG9EgGq@;NrY{=@*NYxi0E! zB%%y^wk*YUUDRfRM9F$Wg&JvHlu0O}w0@G_FsAR9i4ti2M*m>CU04jY``*&DX{P^i fh!0!%U-(c literal 0 HcmV?d00001 From 892bba1ed1418dce4bfe555695f3814fbae39764 Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Mon, 11 Feb 2019 05:33:03 +0100 Subject: [PATCH 020/223] Add support for Decoding BI_ALPHABITFIELDS (#832) * Adds support for BI_ALPHABITFIELDS * Fix for decoding bitmaps with a less than full sized palette --- src/ImageSharp/Formats/Bmp/BmpCompression.cs | 10 +++++-- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 17 ++++++++++-- .../Formats/Bmp/BmpDecoderTests.cs | 26 ++++++++++++++++++ tests/ImageSharp.Tests/TestImages.cs | 2 ++ tests/Images/Input/Bmp/pal8os2sp.bmp | Bin 0 -> 8974 bytes tests/Images/Input/Bmp/rgba32abf.bmp | Bin 0 -> 32582 bytes 6 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 tests/Images/Input/Bmp/pal8os2sp.bmp create mode 100644 tests/Images/Input/Bmp/rgba32abf.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpCompression.cs b/src/ImageSharp/Formats/Bmp/BmpCompression.cs index 5f14d2243..be275019e 100644 --- a/src/ImageSharp/Formats/Bmp/BmpCompression.cs +++ b/src/ImageSharp/Formats/Bmp/BmpCompression.cs @@ -34,7 +34,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// If the first byte is zero, the record has different meanings, depending /// on the second byte. If the second byte is zero, it is the end of the row, /// if it is one, it is the end of the image. - /// Not supported at the moment. /// RLE4 = 2, @@ -54,6 +53,13 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The bitmap contains a PNG image. /// Not supported at the moment. ///
- PNG = 5 + PNG = 5, + + /// + /// Introduced with Windows CE. + /// Specifies that the bitmap is not compressed and that the color table consists of four DWORD color + /// masks that specify the red, green, blue, and alpha components of each pixel. + /// + BI_ALPHABITFIELDS = 6 } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 496a6df4a..d33ada286 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -75,7 +75,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// The file header containing general information. - /// TODO: Why is this not used? We advance the stream but do not use the values parsed. /// private BmpFileHeader fileHeader; @@ -163,6 +162,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp break; case BmpCompression.BitFields: + case BmpCompression.BI_ALPHABITFIELDS: this.ReadBitFields(pixels, inverted); break; @@ -947,7 +947,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp infoHeaderType = BmpInfoHeaderType.WinVersion3; this.infoHeader = BmpInfoHeader.ParseV3(buffer); - // if the info header is BMP version 3 and the compression type is BITFIELDS, + // If the info header is BMP version 3 and the compression type is BITFIELDS, // color masks for each color channel follow the info header. if (this.infoHeader.Compression == BmpCompression.BitFields) { @@ -958,6 +958,16 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)); this.infoHeader.BlueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)); } + else if (this.infoHeader.Compression == BmpCompression.BI_ALPHABITFIELDS) + { + byte[] bitfieldsBuffer = new byte[16]; + this.stream.Read(bitfieldsBuffer, 0, 16); + Span data = bitfieldsBuffer.AsSpan(); + this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)); + this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)); + this.infoHeader.BlueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)); + this.infoHeader.AlphaMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(12, 4)); + } } else if (headerSize == BmpInfoHeader.AdobeV3Size) { @@ -1078,6 +1088,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp int colorMapSizeBytes = this.fileHeader.Offset - BmpFileHeader.Size - this.infoHeader.HeaderSize; int colorCountForBitDepth = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel); bytesPerColorMapEntry = colorMapSizeBytes / colorCountForBitDepth; + + // Edge case for less-than-full-sized palette: bytesPerColorMapEntry should be at least 3. + bytesPerColorMapEntry = Math.Max(bytesPerColorMapEntry, 3); colorMapSize = colorMapSizeBytes; } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index e7b5aeaea..ad47ed1e7 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -60,6 +60,20 @@ namespace SixLabors.ImageSharp.Tests } } + [Theory] + [WithFile(RgbaAlphaBitfields, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeAlphaBitfields(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + + // TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file. + // image.CompareToOriginal(provider); + } + } + [Theory] [WithFile(Bit32Rgba, PixelTypes.Rgba32)] public void BmpDecoder_CanDecodeBitmap_WithAlphaChannel(TestImageProvider provider) @@ -114,6 +128,18 @@ namespace SixLabors.ImageSharp.Tests } } + [Theory] + [WithFile(LessThanFullSizedPalette, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeLessThanFullPalete(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, new MagickReferenceDecoder()); + } + } + [Theory] [WithFile(Rgba32bf56, PixelTypes.Rgba32)] public void BmpDecoder_CanDecodeAdobeBmpv3(TestImageProvider provider) diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 51e2d084c..3a497683a 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -221,6 +221,7 @@ namespace SixLabors.ImageSharp.Tests public const string Bit8Palette4 = "Bmp/pal8-0.bmp"; public const string Os2v2Short = "Bmp/pal8os2v2-16.bmp"; public const string Os2v2 = "Bmp/pal8os2v2.bmp"; + public const string LessThanFullSizedPalette = "Bmp/pal8os2sp.bmp"; public const string Pal8Offset = "Bmp/pal8offs.bmp"; // Bitmap images with compression type BITFIELDS @@ -232,6 +233,7 @@ namespace SixLabors.ImageSharp.Tests public const string Issue735 = "Bmp/issue735.bmp"; public const string Rgba32bf56 = "Bmp/rgba32h56.bmp"; public const string Rgba321010102 = "Bmp/rgba32-1010102.bmp"; + public const string RgbaAlphaBitfields = "Bmp/rgba32abf.bmp"; public static readonly string[] BitFields = { diff --git a/tests/Images/Input/Bmp/pal8os2sp.bmp b/tests/Images/Input/Bmp/pal8os2sp.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e532c89863c0ab16ecd69655235386c3ede893f0 GIT binary patch literal 8974 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 Fe*x!$9?}2+ literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/rgba32abf.bmp b/tests/Images/Input/Bmp/rgba32abf.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d9bb0189c47f7510a11afd9240eb2796cf37dcc1 GIT binary patch literal 32582 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 ZuHWhR`buT}L4VZ0s-l0>|J0xK{{x0L5l{dC literal 0 HcmV?d00001 From 4c0b0123a807d6b7722baac59664fe484ca28f31 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 11 Feb 2019 23:25:00 +1100 Subject: [PATCH 021/223] Reorder target frameworks (#833) --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 2 +- src/ImageSharp/ImageSharp.csproj | 2 +- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index f4906d25e..638687ae5 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -10,7 +10,7 @@ $(packageversion) 0.0.1 - netstandard1.3;netstandard2.0 + netcoreapp2.1;netstandard1.3;netstandard2.0 7.3 true true diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 6ab609d5c..f7f9e1d5f 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -10,7 +10,7 @@ $(packageversion) 0.0.1 - netstandard1.3;netstandard2.0;netcoreapp2.1;net472 + netcoreapp2.1;netstandard1.3;netstandard2.0;net472 true true SixLabors.ImageSharp diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index e20f1514c..73f97bab3 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,6 +1,6 @@  - net462;net472;netcoreapp2.1 + netcoreapp2.1;net462;net472 True latest full From ff31b5f8d41f32dcf8d58e297c0bc1aef83191ad Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Fri, 15 Feb 2019 10:08:21 +0100 Subject: [PATCH 022/223] Some changes to make the usages of GDI in benchmarks and tests more stable, this should hopefully prevent "a generic error occurred in GDI+". Hopefully I didn't miss one... (#835) --- .../Drawing/DrawBeziers.cs | 16 +-- .../Drawing/DrawLines.cs | 14 ++- .../Drawing/DrawPolygon.cs | 14 ++- .../ImageSharp.Benchmarks/Drawing/DrawText.cs | 7 +- .../Drawing/DrawTextOutline.cs | 12 +- .../Drawing/FillWithPattern.cs | 6 +- .../ReferenceCodecs/SystemDrawingBridge.cs | 113 ++++++++++-------- 7 files changed, 104 insertions(+), 78 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs index edbbceb62..34dd9d4dc 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs @@ -26,13 +26,15 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - Pen pen = new Pen(System.Drawing.Color.HotPink, 10); - graphics.DrawBeziers(pen, new[] { - new PointF(10, 500), - new PointF(30, 10), - new PointF(240, 30), - new PointF(300, 500) - }); + using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + { + graphics.DrawBeziers(pen, new[] { + new PointF(10, 500), + new PointF(30, 10), + new PointF(240, 30), + new PointF(300, 500) + }); + } } using (MemoryStream ms = new MemoryStream()) diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs index 894683599..091f36762 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs @@ -26,12 +26,14 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - var pen = new Pen(System.Drawing.Color.HotPink, 10); - graphics.DrawLines(pen, new[] { - new PointF(10, 10), - new PointF(550, 50), - new PointF(200, 400) - }); + using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + { + graphics.DrawLines(pen, new[] { + new PointF(10, 10), + new PointF(550, 50), + new PointF(200, 400) + }); + } } using (var ms = new MemoryStream()) diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs index 5fbd9f112..ab8a7134e 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs @@ -26,12 +26,14 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - Pen pen = new Pen(System.Drawing.Color.HotPink, 10); - graphics.DrawPolygon(pen, new[] { - new PointF(10, 10), - new PointF(550, 50), - new PointF(200, 400) - }); + using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + { + graphics.DrawPolygon(pen, new[] { + new PointF(10, 10), + new PointF(550, 50), + new PointF(200, 400) + }); + } } using (MemoryStream ms = new MemoryStream()) diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs index 624b54278..60c58dadc 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs @@ -35,9 +35,10 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - Pen pen = new Pen(System.Drawing.Color.HotPink, 10); - var font = new Font("Arial", 12, GraphicsUnit.Point); - graphics.DrawString(TextToRender, font, System.Drawing.Brushes.HotPink, new RectangleF(10, 10, 780, 780)); + using (var font = new Font("Arial", 12, GraphicsUnit.Point)) + { + graphics.DrawString(TextToRender, font, System.Drawing.Brushes.HotPink, new RectangleF(10, 10, 780, 780)); + } } } } diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs index ba6d055e3..2d6505a91 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs @@ -34,11 +34,13 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - Pen pen = new Pen(System.Drawing.Color.HotPink, 10); - var font = new Font("Arial", 12, GraphicsUnit.Point); - var gp = new GraphicsPath(); - gp.AddString(TextToRender, font.FontFamily, (int)font.Style, font.Size, new RectangleF(10, 10, 780, 780), new StringFormat()); - graphics.DrawPath(pen, gp); + using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + using (var font = new Font("Arial", 12, GraphicsUnit.Point)) + using (var gp = new GraphicsPath()) + { + gp.AddString(TextToRender, font.FontFamily, (int)font.Style, font.Size, new RectangleF(10, 10, 780, 780), new StringFormat()); + graphics.DrawPath(pen, gp); + } } } } diff --git a/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs b/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs index 5f8f2ff06..372361988 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs @@ -26,8 +26,10 @@ namespace SixLabors.ImageSharp.Benchmarks using (Graphics graphics = Graphics.FromImage(destination)) { graphics.SmoothingMode = SmoothingMode.AntiAlias; - HatchBrush brush = new HatchBrush(HatchStyle.BackwardDiagonal, Color.HotPink); - graphics.FillRectangle(brush, new Rectangle(0, 0, 800, 800)); // can't find a way to flood fill with a brush + using (var brush = new HatchBrush(HatchStyle.BackwardDiagonal, Color.HotPink)) + { + graphics.FillRectangle(brush, new Rectangle(0, 0, 800, 800)); // can't find a way to flood fill with a brush + } } using (MemoryStream ms = new MemoryStream()) { diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs index 7e87c23db..79c19f2be 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs @@ -39,32 +39,39 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs } BitmapData data = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat); - byte* sourcePtrBase = (byte*)data.Scan0; + var image = new Image(w, h); + try + { + byte* sourcePtrBase = (byte*)data.Scan0; - long sourceRowByteCount = data.Stride; - long destRowByteCount = w * sizeof(Bgra32); + long sourceRowByteCount = data.Stride; + long destRowByteCount = w * sizeof(Bgra32); - var image = new Image(w, h); - Configuration configuration = image.GetConfiguration(); + Configuration configuration = image.GetConfiguration(); - using (IMemoryOwner workBuffer = Configuration.Default.MemoryAllocator.Allocate(w)) - { - fixed (Bgra32* destPtr = &workBuffer.GetReference()) + using (IMemoryOwner workBuffer = Configuration.Default.MemoryAllocator.Allocate(w)) { - for (int y = 0; y < h; y++) + fixed (Bgra32* destPtr = &workBuffer.GetReference()) { - Span row = image.Frames.RootFrame.GetPixelRowSpan(y); - - byte* sourcePtr = sourcePtrBase + (data.Stride * y); - - Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); - PixelOperations.Instance.FromBgra32( - configuration, - workBuffer.GetSpan().Slice(0, w), - row); + for (int y = 0; y < h; y++) + { + Span row = image.Frames.RootFrame.GetPixelRowSpan(y); + + byte* sourcePtr = sourcePtrBase + (data.Stride * y); + + Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); + PixelOperations.Instance.FromBgra32( + configuration, + workBuffer.GetSpan().Slice(0, w), + row); + } } } } + finally + { + bmp.UnlockBits(data); + } return image; } @@ -91,33 +98,36 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs } BitmapData data = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat); - byte* sourcePtrBase = (byte*)data.Scan0; + var image = new Image(w, h); + try + { + byte* sourcePtrBase = (byte*)data.Scan0; - long sourceRowByteCount = data.Stride; - long destRowByteCount = w * sizeof(Bgr24); + long sourceRowByteCount = data.Stride; + long destRowByteCount = w * sizeof(Bgr24); - var image = new Image(w, h); - Configuration configuration = image.GetConfiguration(); + Configuration configuration = image.GetConfiguration(); - using (IMemoryOwner workBuffer = Configuration.Default.MemoryAllocator.Allocate(w)) - { - fixed (Bgr24* destPtr = &workBuffer.GetReference()) + using (IMemoryOwner workBuffer = Configuration.Default.MemoryAllocator.Allocate(w)) { - for (int y = 0; y < h; y++) + fixed (Bgr24* destPtr = &workBuffer.GetReference()) { - Span row = image.Frames.RootFrame.GetPixelRowSpan(y); + for (int y = 0; y < h; y++) + { + Span row = image.Frames.RootFrame.GetPixelRowSpan(y); - byte* sourcePtr = sourcePtrBase + (data.Stride * y); + byte* sourcePtr = sourcePtrBase + (data.Stride * y); - Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); - PixelOperations.Instance.FromBgr24( - configuration, - workBuffer.GetSpan().Slice(0, w), - row); + Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); + PixelOperations.Instance.FromBgr24(configuration, workBuffer.GetSpan().Slice(0, w), row); + } } } } - + finally + { + bmp.UnlockBits(data); + } return image; } @@ -131,27 +141,32 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs var resultBitmap = new Bitmap(w, h, PixelFormat.Format32bppArgb); var fullRect = new Rectangle(0, 0, w, h); BitmapData data = resultBitmap.LockBits(fullRect, ImageLockMode.ReadWrite, resultBitmap.PixelFormat); - byte* destPtrBase = (byte*)data.Scan0; + try + { + byte* destPtrBase = (byte*)data.Scan0; - long destRowByteCount = data.Stride; - long sourceRowByteCount = w * sizeof(Bgra32); + long destRowByteCount = data.Stride; + long sourceRowByteCount = w * sizeof(Bgra32); - using (IMemoryOwner workBuffer = image.GetConfiguration().MemoryAllocator.Allocate(w)) - { - fixed (Bgra32* sourcePtr = &workBuffer.GetReference()) + using (IMemoryOwner workBuffer = image.GetConfiguration().MemoryAllocator.Allocate(w)) { - for (int y = 0; y < h; y++) + fixed (Bgra32* sourcePtr = &workBuffer.GetReference()) { - Span row = image.Frames.RootFrame.GetPixelRowSpan(y); - PixelOperations.Instance.ToBgra32(configuration, row, workBuffer.GetSpan()); - byte* destPtr = destPtrBase + (data.Stride * y); - - Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); + for (int y = 0; y < h; y++) + { + Span row = image.Frames.RootFrame.GetPixelRowSpan(y); + PixelOperations.Instance.ToBgra32(configuration, row, workBuffer.GetSpan()); + byte* destPtr = destPtrBase + (data.Stride * y); + + Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); + } } } } - - resultBitmap.UnlockBits(data); + finally + { + resultBitmap.UnlockBits(data); + } return resultBitmap; } From 5a9b84e9a63fce97516af4d3427f95793960537e Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 15 Feb 2019 21:55:16 +1100 Subject: [PATCH 023/223] Remove hardcoded subsampling. Fix #817 (#834) --- .../Jpeg/Components/Decoder/JpegComponent.cs | 38 +++++------------- .../Formats/Jpg/JpegDecoderTests.Images.cs | 1 + tests/ImageSharp.Tests/TestImages.cs | 3 +- tests/Images/External | 2 +- .../Jpg/baseline/ycck-subsample-1222.jpg | Bin 0 -> 31527 bytes 5 files changed, 14 insertions(+), 30 deletions(-) create mode 100644 tests/Images/Input/Jpg/baseline/ycck-subsample-1222.jpg diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs index ef03582d6..cfed5d535 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs @@ -2,8 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; using SixLabors.Memory; @@ -12,9 +10,9 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { /// - /// Represents a single frame component + /// Represents a single frame component. /// - internal class JpegComponent : IDisposable, IJpegComponent + internal sealed class JpegComponent : IDisposable, IJpegComponent { private readonly MemoryAllocator memoryAllocator; @@ -31,12 +29,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } /// - /// Gets the component Id + /// Gets the component Id. /// public byte Id { get; } /// - /// Gets or sets DC coefficient predictor + /// Gets or sets DC coefficient predictor. /// public int DcPredictor { get; set; } @@ -69,22 +67,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder public Size SamplingFactors { get; set; } /// - /// Gets the number of blocks per line + /// Gets the number of blocks per line. /// public int WidthInBlocks { get; private set; } /// - /// Gets the number of blocks per column + /// Gets the number of blocks per column. /// public int HeightInBlocks { get; private set; } /// - /// Gets or sets the index for the DC Huffman table + /// Gets or sets the index for the DC Huffman table. /// public int DCHuffmanTableId { get; set; } /// - /// Gets or sets the index for the AC Huffman table + /// Gets or sets the index for the AC Huffman table. /// public int ACHuffmanTableId { get; set; } @@ -109,24 +107,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder int blocksPerColumnForMcu = this.Frame.McusPerColumn * this.VerticalSamplingFactor; this.SizeInBlocks = new Size(blocksPerLineForMcu, blocksPerColumnForMcu); - // For 4-component images (either CMYK or YCbCrK), we only support two - // hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22]. - // Theoretically, 4-component JPEG images could mix and match hv values - // but in practice, those two combinations are the only ones in use, - // and it simplifies the applyBlack code below if we can assume that: - // - for CMYK, the C and K channels have full samples, and if the M - // and Y channels subsample, they subsample both horizontally and - // vertically. - // - for YCbCrK, the Y and K channels have full samples. - if (this.Index == 0 || this.Index == 3) - { - this.SubSamplingDivisors = new Size(1, 1); - } - else - { - JpegComponent c0 = this.Frame.Components[0]; - this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors); - } + JpegComponent c0 = this.Frame.Components[0]; + this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors); int totalNumberOfBlocks = blocksPerColumnForMcu * (blocksPerLineForMcu + 1); int width = this.WidthInBlocks + 1; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index 03f1826ed..9f34d7d09 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -21,6 +21,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Baseline.Jpeg444, TestImages.Jpeg.Baseline.Bad.BadEOF, TestImages.Jpeg.Baseline.MultiScanBaselineCMYK, + TestImages.Jpeg.Baseline.YcckSubsample1222, TestImages.Jpeg.Baseline.Bad.BadRST, TestImages.Jpeg.Issues.MultiHuffmanBaseline394, TestImages.Jpeg.Issues.ExifDecodeOutOfRange694, diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 3a497683a..e28caf627 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -140,13 +140,14 @@ namespace SixLabors.ImageSharp.Tests public const string MultiScanBaselineCMYK = "Jpg/baseline/MultiScanBaselineCMYK.jpg"; public const string Ratio1x1 = "Jpg/baseline/ratio-1x1.jpg"; public const string Testorig12bit = "Jpg/baseline/testorig12.jpg"; + public const string YcckSubsample1222 = "Jpg/baseline/ycck-subsample-1222.jpg"; public static readonly string[] All = { Cmyk, Ycck, Exif, Floorplan, Calliphora, Turtle, GammaDalaiLamaGray, Hiyamugi, Jpeg400, Jpeg420Exif, Jpeg444, - Ratio1x1, Testorig12bit + Ratio1x1, Testorig12bit, YcckSubsample1222 }; } diff --git a/tests/Images/External b/tests/Images/External index 74995302e..32dc8aec1 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 74995302e3c9a5913f1cf09d71b15f888d0ec022 +Subproject commit 32dc8aec1109b681f056264e6bde1f3a76f08aba diff --git a/tests/Images/Input/Jpg/baseline/ycck-subsample-1222.jpg b/tests/Images/Input/Jpg/baseline/ycck-subsample-1222.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7e112d69c8586ae7dbc08afb7c5585892c014a4e GIT binary patch literal 31527 zcmbq)1x#E~_vheNv_PSFVG08U3I&RLk--P|VnqjccUqw604;6<3=YL9?ogyS!$5J0 zyGxgE|H&qs>~6BV=e^vVE#$tlm8FG z!p6iw$H2uydwMKI0ziA32^|v?3mpp+4Fd}e4IKj$fJKT;#)QN3{FRgjE;+9m1+%nE zNMau4J4j6z9*g;J*B3IYR6xGa7PKn0)=PyzrX0CzWFNc*GipW**7FgWP{ zeW;{=C2E`zqFWzGhT|4}&qB0KUg=)0Yt=Bd1N|84#{k}YLDeS<`oMa~5#mvukKZXY zz~A|ELI=N7!VNqIcYmcszzCd9@_RNH;D!&5gh)rt&oLI3_-Ikwy?k0(;2it^-}?Sf z-`11N(?G-Q%;k%}Ru9Kz*XX3^Qv#D{6$FEf-HLDz9OS=mdeYCB5V&w~7{c*IvwbS< zOg0g7FNQ?#(z{*!VDe__u9lzyFKa*mXjF0trgOM|c?%)rU>b^Xqt-AHA+txQ3huB| zu_CLx75GuH#R>MreFkHcDrVjzE+(!nd!rnjgdmk|7bV07D@yB}x~msE>$C}n!8h!L z03jVkRB#tPqM#g^yn4bUTAZV1HyT$v)$Fj%ocLJv55UhvZPn8ho|$%O^qT3UB|vEBb#S$Qsk{^uj?roy64} za}=Cxsyexehbk_RiEu}QQ2A!Q^3ok&8D&~1e7e%3&v@_5*EVxbgRwX)y`P1&3(k{h)VWSEXEfnIpRX{O z+rJ9lN+IzUWUi^aq?8Ruu-Y{Sf%_#i^0l|tS|PP5aefTGM=}|dnO8W=DZ;16^GR{q zv24~m5_Tg|&PpY??yG^17bXNO)-Ky^p5&`cy$swI`h&2-);5fhc;0}=i&tO3L`U*d zx5-CWaH9Z_MxrTa9nx55Yv%mTZNOK>=~hP^8cgQ^`Ff>>6&Gq+28}08R1W|D=!4_9 z1jtgdLbNd@NX_^3qfmg@q#!Ud97M^`3xUO91Dctm9fKT%v0_XfUznz)w3oVR@e9M6 zc?;3htR`V3K@1vrl?^PX)gh%vZ1fUpNOM0YzEmm<9eYC+C%W4yjja`c#l9UhtG2M^ z?O?l@HO7Uiw0tcy=(Mk%+;Ph?%UO&NHg`9V;^xW7aAAgj~F!3twz3&X1R%F?bU66KTi$|_Jl z*|#Z@_A17?@Nc+oG>wcvJbhhiRBe@!OCN{*P=^Tf2*Y65zE3$H94s=c$cmZ+uQ4UB z@n$l5DV#r)L=6wF$J<3~rBUwi>S$F-?HCd+5Wo1r@1wgzy_T{JKcF{J@nCzC?WY@v zrz$ycWNbI6D!Fkxtvz<;STDuv=%yb=g|X%F5#!Ep#!%B<%Yu7I%yDs7#WtHH#K8PGtQSK4P1+Xm_c@9nOnIA!3 z>d-eEB^Bw(`@M!Yr{bqE|N-dC!&U}A$1GLvZmDL)~YsQb;f-qPKFrx>n zcl`tkqW5EzXNv?Pp!!hBm45(=%^gw#FFc54!`c$(3hj-{W#tm5U(=3HVz&9@8MK4# z`mb$l6j_kI`aeLnT~x6+|B_$nYzZ=biU>PBVZ~0Vda}MEYrw{hT{PH-5#1$Imr&&7 z`1e(zMg@XLU|od}h~^&s{Qj3EqGiYn#{pQ;l}o2k_zQ5=eTM@G;G+F-o% zK0lmT{EhI(kA0E`RW4lBhAt6ie!PVoq3piQL%i5NgH^dY8TGYSpJH6=#?9BA5)z6m z2b?(x7|c1A|N8^$7}t7L^Hp?d>Fq zjK#SEdv#e=jZBa9?DX)DjQ8A#$kZ_B{NfIrlbi`XwF|T0RbP}?DYQBg>_8a%~?Emu1+F4nZKJX(pnWsY{Gn=Q;qQR z=<%fTKD*U^lCcgE#-K!>CveP_nE%^!y}-4B+TlBtj=iQ9D!48O%`B?g`j6gMSOM1eU__Bm*-Y&G<37@Xq-42FO| zE6@#<?NaEVaJPA51*lm&LE42WflXlsXHMuuRv^*WO8m8GiI0^V`N_81?Vpm4A@&B_>#> za-Y9 zKHo7FZ3)YL1IjpLb?r3cBQ>LZAQ6?qSMqaUX+R-MHqe z$MVSJSe~t-)9CM6n&gv%gNBHfJ!0Nw5JbxaEj$$Lxsf1={qxtAtnbe8O);mK&b8I9 zNkOZP;q*jC;I|gu@Fn7n>)l__Rvkkrk<_oHiWJ4d0aNsG7Zw$b#$wYnL3-tMnl5t; zIYpdhP!$Q_ObTdXy}~Lyg#*Yz->ywR6PG$kYq;aVV%?(7D?VR#oGi{2_QR%;FEv*~ zhMsJ6z_9JR9Sexqf5HQ7@FVGYFb);fTFPIOgp06s);wgz9e?-h;2E;QrtL2!+%F?V z;s9_beV6_$eUEB1K|D+Vfbp4bOWj6X^{&2weZ`W*u9FJCOym1!?S)1w^-Pg8!I3>G z_mSsSu1S&6_^DLLhSx2+Gto;VT=+3=*yIv`rS8_fw?VX;+Es$-$9`4EQ7FfTIVYX^b=+inv6{z7{_Myld{R}sH>UQrLk@6D z5{VKrB9Cw-BiDHsFKO?8&)PL7Ch_~1o-cx3HG|B++W>l-1fdY=T#m;hZc2hE1-ip6 zLvwQ_)aa^uLg<&ZLA`H@04{yOWCfl5ffvU|2#E`W>&WRK(#wp?h?M6lHZ&|3LIkQE zSVV#BbD)2K4qbK)HVGv=u)4FH7J3=>s#^o{W0Cfxzn_DZU}{gTiINS61`@U@`z%Qk zW4686`^%fBUB6+?AGtnHn?9Gi_&2zlSvlba$v;5q*8cuuK&j`tt8Gc3yr^_J6n7*2 z=H>(^aK=ClGG?zWr%^|Ko%;PNH|G#N0vte&%`0-Y`&MQ1&zGSN5+2&=Ilr)R6paoA z)MM#SRE6;b635adL6WA;2RrZRg$BAX%HP3(l}%kj_rTc8>kpGS-bE+MCKSaHRH?43q5s2dtZF3>Z>pM3p*c#cDemd%OTlB3(FRwgAI!d6e$!28*TCjA20 z$m%=s*W$2)u^_w7D7%}a2+=OHwstv}uN`d;QET}|WB!95KB~r&QcGnP#|dtgCG9_d z@rk$%Ek>E2@WjA{I^md_2|P~s&=#Sa;@>*XJjIFrmfFeiq)(v<3jl6tSOfCemWxh3J8Ngr^WYR#<4{apJ_~f zvlAf_zOAnJ#Y|y~xBGjdZxv7MZHuP>VvK)(WN1+kpfugaKWna(OzVkS55!;XV2p&k zr@*Llrg%~w$K*c%QJdqe*z4&e7S!v(W~8ZteJAWhNphP>kM7GsrdDJ|D~j`lcB$Vk zsi%XIz1whNW}F!Da@AfF(*Sx%|7!ZKW}bEYTD^hOuL148Z7WiGf%gdTX)&`P!d{@P z!Neioqt;K;B96R}V@G`E=z#m=#ngcY56O&&O0DZOtl?J*i+6Z}XyNn3B%$@Ds^VMI zwW^|*-?!F>TPufvj(qda4SVbjoAB@qTzQg&1P?hZI%m^;-KRgO^rdc=lSS&RpmK@u zFs46Mb$u+xT$v-Q4J8i?6?qx)X(i1NM-V|S(k8Srdu#_bQUK|=&Clh}e~U^GC=>6m z_!!D7MDgki^%)WIF2%Qq2!K=x^m@a^cvRF2J^N-u$HIwrRX#cqdX~d8%5F;xB0^7+ zqAOj8Howx8s!yQDxShdjtfja*8q`?Ub^zZ61VI*y`hyuWS6=-Kye|y{A+Re#%yz1nMYmxH?&54GLD}du7JO%03csUmw@Z84Ita)jJ=xA+$IV`wb-x63ED|a@=%RPNW`8)!WP7 zr4vhl3~G$u(O<(IS+{E^m{@%uBBVQbwomb^bIc5qOmgRNxrOLF-!DA7PMrLvmd28h zr1bHHd}L*(Q>V~c>22lNoM(%@r!alsXE%M(gbV^NL#@;`PV8u=m#S6yuKiEGLPgLf_f4avQx?c`Va)qI8ld(?^ z_eM`Xmj#sAo}goZz-aS7>H3stTprpzFRWMJt;Z{SNCz37%j+!f29`Ag4sKZ_KTqZf zlBM8QzFmvqVgmZ9hi}{w`xAZt2bk7G7=X7Wiraz`OU^gDc*#f3EEbdLuJIT{Bime5wCdY+y1A>cinT!jRGIFnA?ix$Yc|{H#nyL16I~U&D;*Cieq@J z^N5U?BvLDxQ5g1rd84|2O_L7gcZz zBln()xvzB7%x@4&N(g>}G;*V2kYcy#8L;mS!UErhCDt{4<^iw%-qfI-t*VVYK96s! zyxmYel5YAo9oZXY*5~1O6=fpDEua|@T$fTvI-Yl6TSPKBv=OIZ3JW`Ak0@;kDTmt` zS_;g^kPe{U^!Sc*>ITulgFRb%Y`~#EOSc*6<-7%T8#p`2d~wza6l|85eh22*g}P_W za!%V}>Z5M-s0g4oD9NQYpek18I_9Y=hw}wTSr+}Z)12xBvBqDT{YtoL!G{nmIo@KW z1k|Ub@n47{uT*_$Iq;7pSHKWI!-Qj_{)NET=uEJCr<*D?nP(6Q!P zA;?x;pG}-z0W;J5XIDi#Z%dcmb-A!b;jQo4>qBe*l=ksbbIM$7^(_-0H)Hh^%4z_v zB(7u^cFjHK5jhZ(#S6>Q`lbv;b1+&VL3!ZY`u@xb0fIW{BUQ;0AX(+!WhRoWmj#YVK5@D)H&w4!e}19O=-1fPEw?A$QRNq_eaE^jX?- z-ucs0*)~aM)U?y8W>`5_6?H;UuSXXs9rRq*6&x`;ZmiPOqp{w!+30c6)|0i8Aa)=CE2fd=%QuJO?}{hfyB`k z_IbJJ+rTKFQ9^~BN+zepmjN-7Hz70d*t;05>GsI_ia3$m%0@?5e#)&x)w~PlA5NFo zCs3J@Ny*KHRlktryb+AC7@5zP8|Ix!3d0c~urrM95GmoN-o5--kUBlIw`jlZAXN_) z4^^OZ@(_W$xyO};S}vNZZ8l9dh*5Wn zR@T)FQ;Ol? zW)t|F{Jl3~i259`PV1MREDeLdKs!ELT<*|W@TkQbU+%yMCnUv7#c{NOAo}zdImM~` zwBJ34e$%8t!{|UUAVr{B@&3=V^X+)wh0CPTnE^)Z3|~GQgzXou*rsd2e}F?jAGd+W z-KA%*P5zF^NB2MhY4N~c5B~tsWlNl73{bnzxlug*AM6%dT<^}rX{r#Z@=OZUqfVK@ zKP^~~^s4HL(UWo|;98C?!oaTg1Tc||-wRMIag0)(-psS`?DZpk7p^NR*UIO}?-bX+ zcp~1vp}U5O zWfGdJUG6_3%(wN1`-Yxk8IWo_o9r#_*!N+HSYU!k&7*Z z2465hLjCG)w(Zulgs$`QRc*nLkq@p1-0b7@Pf%&}@i?0VBxtKBS5-^CQ;0JMA#n;a z|<4`V$9E^SJyjw@pdLp5xykcI~#` zDT$@P+^c(F8du@?CXG^Uk)PsCE?;iA7FPe-Uc!=$e5ax!HO{E|d(fc})+|yt6klQR z$TZy2yiPT123oXs5PAK$K%{Vtba4XJm7@c?JBP{9ozb1i)%g8v*<&r48V&CUl(^cX z$VMP2(Gm`Nh4F|cd1}b#3am0{T$!dyH!<<^@gtoBVxOt0qu)^9i!gp4Fy|x#Y$X;M zGDyTnPNJPXMw%HHz%h(usC)|zQ1p`8)9>I)WT~-l6?RVY`pA14e-0ks4GUGFPjJ34E0>#s7e=$?=iX~4aaO+E945$Sv(X2o-Lzj2j~eaX5;>}N+KOo zR8N#o#!Rm0Leg#wXZ?uPOf0NUo~xBlK1chhA>0qzvb^*5;3QwDUuW7KDF5WBvDGfh z;Rx_1m}R}0e^+}DNaNFa{<^LHH*uu57=4XWLMzH|tg4B_W9*vqA0Yh+2$k`hEzA?m zyiwF~Rjl|do;YT2>YrMd8fg$c+Ne4pJ#~{z|1QT+a=V935{zTHY8V|U@>Fvv?*60b zdt}xqwZ~a=V6y)jhO$l6JtcdI%Ier^you@Dr>uW=7JaU&Dz-;y`B&#sRR44#{7-(4 zJF`TC-xD%8O|Qq8d%(Qd=49I<-sM~`Mx!oJw*Q_C;}^;p)g8P~AVZk5$$w``aGQ3F zR`p1GyIxRF+{3NT)yTg~&>Z@C90}Xca1#MfBZyc)jfPYhV`PfV^cNRl`NlM9Qzc3K zuglwi%{)L_bJu&I^98ppsve+T8+K^(xI&vA~<>8v;$K z=X~WiJ*Cv%faCT8fKFNjLV)@+bB` z0J{SIdaMqA|8cJdUPgGsTBTCgw^eI=AIsweF%|n(dpe1UtGf5_e8S|{z|WM|9Vvv3 zXN|b5!-_&f3OYhmB{x@w9yNnDSv)0`N&#==l%l&l`e-qWQR#8lv47>IZs+gS9xMJ- zdbTOzi@)JEa607YLLE8Zk!Fk;jq&D(s@a_ts|AwYBHZWHY_l8fcjzQ{#4}r8e~ND% zjsA9}ctANR{~1zo*NpUvy-{`RtjNgY_C*?xnAoKH3M{Akx;efEUdb6Xh>nyROwt<- z;6d8M*;XY#URGTE4j`?lV+GGS&G{AqZ!dt;KbunPgihZoH~^*KKjFgp^{l=_B3^7O zXzDskYP?$;K*=AfAM(z*{Sl*7mDP2b&|@PsZ}Dhq+Q;jjYNIv#z{0*Hz8~GMCU&xf z-x15(M$zbCaHmO&npfg`7BF9q>K?o-QaRnk@_Z0;{_y=0byBQi(`!f|-4IS`jHi!( zNRGy^j4=Kn57}>g!MF8w>Y2h$H>TciP9DaFZ=WNjWuxf)L?+LyfKsf(b=e!UrD2m9 z0Y6G|Vx`mA>GI!gsniZU0Sef(iuh7W@jyIkk**;{5x22-qka+Rz`vDz?T|WH+2yOc z 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 literal 0 HcmV?d00001 From 8f3658da6c0040198c01dbf892a9ea77d0556407 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 17 Feb 2019 22:05:16 +1100 Subject: [PATCH 024/223] Jpeg Fuzz Fixes (#836) * Nomalize jpeg exceptions. Fix #821 * Fix #822 * Fix #823 * Check for correct QT index. Touch #824 * Check DHT props. Touch #824 * Limit sampling factors to 1 & 2. Touch #824 * Add already fixed image 4. Touch #824 * Check for excessive code lengths. Touch #824 * Add already fixed image 6. Touch #824 * Lint progressive scan details. Touch #824 * Add already fixed image 8. Fix #824 * Remove duplicate per-block checks * Add already fixed image 1. Touch #825 * Don't throw on bad JFIF density units. * Add already fixed image 3. Touch #825 * Add already fixed image 4. Fix #825 * Check SOFn marker length. Touch #826 * Add already fixed image 2. Touch #826 * Add already fixed image 3. Fix #826 * Add fixed already fixed image. Fix #827 * Revert unneeded bounds check introduced in #804 --- .../Jpeg/Components/Decoder/HuffmanTable.cs | 22 ++--- .../Jpeg/Components/Decoder/JFifMarker.cs | 19 ++-- .../Jpeg/Components/Decoder/JpegComponent.cs | 21 ++++ .../Jpeg/Components/Decoder/JpegFrame.cs | 2 +- .../Jpeg/Components/Decoder/ScanDecoder.cs | 62 ++++++++++-- .../Formats/Jpeg/JpegDecoderCore.cs | 92 ++++++++++++++---- .../Formats/Jpeg/JpegThrowHelper.cs | 35 ++++--- .../Formats/Jpg/JpegDecoderTests.Baseline.cs | 19 +--- .../Formats/Jpg/JpegDecoderTests.Images.cs | 28 ++++++ tests/ImageSharp.Tests/TestImages.cs | 29 +++++- tests/Images/External | 2 +- ...ticalEOF .jpg => Issue214-CriticalEOF.jpg} | Bin .../Issue797-NullReferenceException.jpg} | Bin .../Issue798-AccessViolationException.jpg | Bin .../fuzz/Issue821-DivideByZeroException.jpg | Bin 0 -> 397 bytes .../fuzz/Issue822-DivideByZeroException.jpg | Bin 0 -> 397 bytes .../fuzz/Issue823-NullReferenceException.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-A.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-B.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-C.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-D.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-E.jpg | Bin 0 -> 397 bytes .../Issue824-IndexOutOfRangeException-F.jpg | Bin 0 -> 411 bytes .../Issue824-IndexOutOfRangeException-G.jpg | Bin 0 -> 308 bytes .../Issue824-IndexOutOfRangeException-H.jpg | Bin 0 -> 308 bytes ...Issue825-ArgumentOutOfRangeException-A.jpg | Bin 0 -> 397 bytes ...Issue825-ArgumentOutOfRangeException-B.jpg | Bin 0 -> 397 bytes ...Issue825-ArgumentOutOfRangeException-C.jpg | Bin 0 -> 397 bytes ...Issue825-ArgumentOutOfRangeException-D.jpg | Bin 0 -> 380 bytes .../fuzz/Issue826-ArgumentException-A.jpg | Bin 0 -> 397 bytes .../fuzz/Issue826-ArgumentException-B.jpg | Bin 0 -> 397 bytes .../fuzz/Issue826-ArgumentException-C.jpg | Bin 0 -> 409 bytes .../Issue827-AccessViolationException.jpg | Bin 0 -> 397 bytes 33 files changed, 246 insertions(+), 85 deletions(-) rename tests/Images/Input/Jpg/issues/{Issue214-CriticalEOF .jpg => Issue214-CriticalEOF.jpg} (100%) rename tests/Images/Input/Jpg/issues/{Issue797-InvalidImage.jpg => fuzz/Issue797-NullReferenceException.jpg} (100%) rename tests/Images/Input/Jpg/issues/{ => fuzz}/Issue798-AccessViolationException.jpg (100%) create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue821-DivideByZeroException.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue822-DivideByZeroException.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue823-NullReferenceException.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-A.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-B.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-C.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-D.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-E.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-F.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-G.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-H.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-A.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-B.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-C.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-D.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-A.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-B.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue827-AccessViolationException.jpg diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs index 9e11981b1..90b362465 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs @@ -50,10 +50,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// The huffman values public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan codeLengths, ReadOnlySpan values) { - // We do some bounds checks in the code here to protect against AccessViolationExceptions - const int HuffCodeLength = 257; - const int MaxSizeLength = HuffCodeLength - 1; - using (IMemoryOwner huffcode = memoryAllocator.Allocate(HuffCodeLength)) + const int Length = 257; + using (IMemoryOwner huffcode = memoryAllocator.Allocate(Length)) { ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.GetSpan()); ref byte codeLengthsRef = ref MemoryMarshal.GetReference(codeLengths); @@ -65,7 +63,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (short i = 1; i < 17; i++) { byte length = Unsafe.Add(ref codeLengthsRef, i); - for (short j = 0; j < length && x < MaxSizeLength; j++) + for (short j = 0; j < length; j++) { Unsafe.Add(ref sizesRef, x++) = i; } @@ -86,7 +84,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder Unsafe.Add(ref valOffsetRef, k) = (int)(si - code); if (Unsafe.Add(ref sizesRef, si) == k) { - while (Unsafe.Add(ref sizesRef, si) == k && si < HuffCodeLength) + while (Unsafe.Add(ref sizesRef, si) == k) { Unsafe.Add(ref huffcodeRef, si++) = (short)code++; } @@ -103,19 +101,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder // Generate non-spec lookup tables to speed up decoding. const int FastBits = ScanDecoder.FastBits; ref byte lookaheadRef = ref this.Lookahead[0]; - const uint MaxFastLength = 1 << FastBits; - Unsafe.InitBlockUnaligned(ref lookaheadRef, 0xFF, MaxFastLength); // Flag for non-accelerated + Unsafe.InitBlockUnaligned(ref lookaheadRef, 0xFF, 1 << FastBits); // Flag for non-accelerated for (int i = 0; i < si; i++) { int size = Unsafe.Add(ref sizesRef, i); if (size <= FastBits) { - int huffCode = Unsafe.Add(ref huffcodeRef, i) << (FastBits - size); - int max = 1 << (FastBits - size); - for (int left = 0; left < max; left++) + int fastOffset = FastBits - size; + int fastCode = Unsafe.Add(ref huffcodeRef, i) << fastOffset; + int fastMax = 1 << fastOffset; + for (int left = 0; left < fastMax; left++) { - Unsafe.Add(ref lookaheadRef, huffCode + left) = (byte)i; + Unsafe.Add(ref lookaheadRef, fastCode + left) = (byte)i; } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs index c51a2f4da..76f0e2cb5 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs @@ -27,12 +27,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// The vertical pixel density private JFifMarker(byte majorVersion, byte minorVersion, byte densityUnits, short xDensity, short yDensity) { - Guard.MustBeGreaterThan(xDensity, 0, nameof(xDensity)); - Guard.MustBeGreaterThan(yDensity, 0, nameof(yDensity)); - Guard.MustBeBetweenOrEqualTo(densityUnits, 0, 2, nameof(densityUnits)); + if (xDensity <= 0) + { + JpegThrowHelper.ThrowImageFormatException($"X-Density {xDensity} must be greater than 0."); + } + + if (yDensity <= 0) + { + JpegThrowHelper.ThrowImageFormatException($"Y-Density {yDensity} must be greater than 0."); + } this.MajorVersion = majorVersion; this.MinorVersion = minorVersion; + + // LibJpeg and co will simply cast and not try to enforce a range. this.DensityUnits = (PixelResolutionUnit)densityUnits; this.XDensity = xDensity; this.YDensity = yDensity; @@ -104,10 +112,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } /// - public override bool Equals(object obj) - { - return obj is JFifMarker other && this.Equals(other); - } + public override bool Equals(object obj) => obj is JFifMarker other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs index cfed5d535..ac24f4ca5 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs @@ -21,9 +21,25 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.memoryAllocator = memoryAllocator; this.Frame = frame; this.Id = id; + + // Valid sampling factors are 1..2 + if (horizontalFactor == 0 + || verticalFactor == 0 + || horizontalFactor > 2 + || verticalFactor > 2) + { + JpegThrowHelper.ThrowBadSampling(); + } + this.HorizontalSamplingFactor = horizontalFactor; this.VerticalSamplingFactor = verticalFactor; this.SamplingFactors = new Size(this.HorizontalSamplingFactor, this.VerticalSamplingFactor); + + if (quantizationTableIndex > 3) + { + JpegThrowHelper.ThrowBadQuantizationTable(); + } + this.QuantizationTableIndex = quantizationTableIndex; this.Index = index; } @@ -110,6 +126,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder JpegComponent c0 = this.Frame.Components[0]; this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors); + if (this.SubSamplingDivisors.Width == 0 || this.SubSamplingDivisors.Height == 0) + { + JpegThrowHelper.ThrowBadSampling(); + } + int totalNumberOfBlocks = blocksPerColumnForMcu * (blocksPerLineForMcu + 1); int width = this.WidthInBlocks + 1; int height = totalNumberOfBlocks / width; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs index 36a3dc2d2..33a7c68ba 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { for (int i = 0; i < this.Components.Length; i++) { - this.Components[i].Dispose(); + this.Components[i]?.Dispose(); } this.Components = null; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs index a1c1b023e..070652a9f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs @@ -270,8 +270,60 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } } + private void CheckProgressiveData() + { + // Validate successive scan parameters. + // Logic has been adapted from libjpeg. + // See Table B.3 – Scan header parameter size and values. itu-t81.pdf + bool invalid = false; + if (this.spectralStart == 0) + { + if (this.spectralEnd != 0) + { + invalid = true; + } + } + else + { + // Need not check Ss/Se < 0 since they came from unsigned bytes. + if (this.spectralEnd < this.spectralStart || this.spectralEnd > 63) + { + invalid = true; + } + + // AC scans may have only one component. + if (this.componentsLength != 1) + { + invalid = true; + } + } + + if (this.successiveHigh != 0) + { + // Successive approximation refinement scan: must have Al = Ah-1. + if (this.successiveHigh - 1 != this.successiveLow) + { + invalid = true; + } + } + + // TODO: How does this affect 12bit jpegs. + // According to libjpeg the range covers 8bit only? + if (this.successiveLow > 13) + { + invalid = true; + } + + if (invalid) + { + JpegThrowHelper.ThrowBadProgressiveScan(this.spectralStart, this.spectralEnd, this.successiveHigh, this.successiveLow); + } + } + private void ParseProgressiveData() { + this.CheckProgressiveData(); + if (this.componentsLength == 1) { this.ParseProgressiveDataNonInterleaved(); @@ -483,11 +535,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder ref Block8x8 block, ref HuffmanTable dcTable) { - if (this.spectralEnd != 0) - { - JpegThrowHelper.ThrowImageFormatException("Can't merge DC and AC."); - } - this.CheckBits(); ref short blockDataRef = ref Unsafe.As(ref block); @@ -518,11 +565,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder ref HuffmanTable acTable, ref short fastACRef) { - if (this.spectralStart == 0) - { - JpegThrowHelper.ThrowImageFormatException("Can't merge DC and AC."); - } - ref short blockDataRef = ref Unsafe.As(ref block); if (this.successiveHigh == 0) diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 06c844d58..9bcfd9ff6 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -255,7 +255,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg var fileMarker = new JpegFileMarker(this.markerBuffer[1], 0); if (fileMarker.Marker != JpegConstants.Markers.SOI) { - throw new ImageFormatException("Missing SOI marker."); + JpegThrowHelper.ThrowImageFormatException("Missing SOI marker."); } this.InputStream.Read(this.markerBuffer, 0, 2); @@ -419,7 +419,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg : JpegColorSpace.Cmyk; } - throw new ImageFormatException($"Unsupported color mode. Max components 4; found {this.ComponentCount}"); + JpegThrowHelper.ThrowImageFormatException($"Unsupported color mode. Max components 4; found {this.ComponentCount}"); + return default; } /// @@ -646,6 +647,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg bool done = false; remaining--; int quantizationTableSpec = this.InputStream.ReadByte(); + int tableIndex = quantizationTableSpec & 15; + + // Max index. 4 Tables max. + if (tableIndex > 3) + { + JpegThrowHelper.ThrowBadQuantizationTable(); + } switch (quantizationTableSpec >> 4) { @@ -661,7 +669,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.InputStream.Read(this.temp, 0, 64); remaining -= 64; - ref Block8x8F table = ref this.QuantizationTables[quantizationTableSpec & 15]; + ref Block8x8F table = ref this.QuantizationTables[tableIndex]; for (int j = 0; j < 64; j++) { table[j] = this.temp[j]; @@ -681,7 +689,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.InputStream.Read(this.temp, 0, 128); remaining -= 128; - ref Block8x8F table = ref this.QuantizationTables[quantizationTableSpec & 15]; + ref Block8x8F table = ref this.QuantizationTables[tableIndex]; for (int j = 0; j < 64; j++) { table[j] = (this.temp[2 * j] << 8) | this.temp[(2 * j) + 1]; @@ -690,7 +698,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg break; default: - throw new ImageFormatException("Bad Tq index value"); + JpegThrowHelper.ThrowBadQuantizationTable(); + break; } if (done) @@ -701,7 +710,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg if (remaining != 0) { - throw new ImageFormatException("DQT has wrong length"); + JpegThrowHelper.ThrowBadMarker(nameof(JpegConstants.Markers.DQT), remaining); } this.MetaData.GetFormatMetaData(JpegFormat.Instance).Quality = QualityEvaluator.EstimateQuality(this.QuantizationTables); @@ -717,15 +726,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { if (this.Frame != null) { - throw new ImageFormatException("Multiple SOF markers. Only single frame jpegs supported."); + JpegThrowHelper.ThrowImageFormatException("Multiple SOF markers. Only single frame jpegs supported."); } - this.InputStream.Read(this.temp, 0, remaining); + // Read initial marker definitions. + const int length = 6; + this.InputStream.Read(this.temp, 0, length); // We only support 8-bit and 12-bit precision. if (!this.supportedPrecisions.Contains(this.temp[0])) { - throw new ImageFormatException("Only 8-Bit and 12-Bit precision supported."); + JpegThrowHelper.ThrowImageFormatException("Only 8-Bit and 12-Bit precision supported."); } this.Precision = this.temp[0]; @@ -740,22 +751,35 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ComponentCount = this.temp[5] }; - this.ImageSizeInPixels = new Size(this.Frame.SamplesPerLine, this.Frame.Scanlines); - - int maxH = 0; - int maxV = 0; - int index = 6; + if (this.Frame.SamplesPerLine == 0 || this.Frame.Scanlines == 0) + { + JpegThrowHelper.ThrowInvalidImageDimensions(this.Frame.SamplesPerLine, this.Frame.Scanlines); + } + this.ImageSizeInPixels = new Size(this.Frame.SamplesPerLine, this.Frame.Scanlines); this.ComponentCount = this.Frame.ComponentCount; if (!metadataOnly) { + remaining -= length; + + const int componentBytes = 3; + if (remaining > this.ComponentCount * componentBytes) + { + JpegThrowHelper.ThrowBadMarker("SOFn", remaining); + } + + this.InputStream.Read(this.temp, 0, remaining); + // No need to pool this. They max out at 4 this.Frame.ComponentIds = new byte[this.ComponentCount]; this.Frame.ComponentOrder = new byte[this.ComponentCount]; this.Frame.Components = new JpegComponent[this.ComponentCount]; this.ColorSpace = this.DeduceJpegColorSpace(); + int maxH = 0; + int maxV = 0; + int index = 0; for (int i = 0; i < this.ComponentCount; i++) { byte hv = this.temp[index + 1]; @@ -777,7 +801,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.Frame.Components[i] = component; this.Frame.ComponentIds[i] = component.Id; - index += 3; + index += componentBytes; } this.Frame.MaxHorizontalFactor = maxH; @@ -795,12 +819,29 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The remaining bytes in the segment block. private void ProcessDefineHuffmanTablesMarker(int remaining) { + int length = remaining; + using (IManagedByteBuffer huffmanData = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(256, AllocationOptions.Clean)) { ref byte huffmanDataRef = ref MemoryMarshal.GetReference(huffmanData.GetSpan()); for (int i = 2; i < remaining;) { byte huffmanTableSpec = (byte)this.InputStream.ReadByte(); + int tableType = huffmanTableSpec >> 4; + int tableIndex = huffmanTableSpec & 15; + + // Types 0..1 DC..AC + if (tableType > 1) + { + JpegThrowHelper.ThrowImageFormatException("Bad Huffman Table type."); + } + + // Max tables of each type + if (tableIndex > 3) + { + JpegThrowHelper.ThrowImageFormatException("Bad Huffman Table index."); + } + this.InputStream.Read(huffmanData.Array, 0, 16); using (IManagedByteBuffer codeLengths = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(17, AllocationOptions.Clean)) @@ -813,15 +854,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg codeLengthSum += Unsafe.Add(ref codeLengthsRef, j) = Unsafe.Add(ref huffmanDataRef, j - 1); } + length -= 17; + + if (codeLengthSum > 256 || codeLengthSum > length) + { + JpegThrowHelper.ThrowImageFormatException("Huffman table has excessive length."); + } + using (IManagedByteBuffer huffmanValues = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(256, AllocationOptions.Clean)) { this.InputStream.Read(huffmanValues.Array, 0, codeLengthSum); i += 17 + codeLengthSum; - int tableType = huffmanTableSpec >> 4; - int tableIndex = huffmanTableSpec & 15; - this.BuildHuffmanTable( tableType == 0 ? this.dcHuffmanTables : this.acHuffmanTables, tableIndex, @@ -848,7 +893,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { if (remaining != 2) { - throw new ImageFormatException($"DRI has wrong length: {remaining}"); + JpegThrowHelper.ThrowBadMarker(nameof(JpegConstants.Markers.DRI), remaining); } this.resetInterval = this.ReadUint16(); @@ -861,7 +906,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { if (this.Frame is null) { - throw new ImageFormatException("No readable SOFn (Start Of Frame) marker found."); + JpegThrowHelper.ThrowImageFormatException("No readable SOFn (Start Of Frame) marker found."); } int selectorsCount = this.InputStream.ReadByte(); @@ -882,7 +927,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg if (componentIndex < 0) { - throw new ImageFormatException("Unknown component selector"); + JpegThrowHelper.ThrowImageFormatException($"Unknown component selector {componentIndex}."); } ref JpegComponent component = ref this.Frame.Components[componentIndex]; @@ -944,6 +989,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private Image PostProcessIntoImage() where TPixel : struct, IPixel { + if (this.ImageWidth == 0 || this.ImageHeight == 0) + { + JpegThrowHelper.ThrowInvalidImageDimensions(this.ImageWidth, this.ImageHeight); + } + var image = Image.CreateUninitialized( this.configuration, this.ImageWidth, diff --git a/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs b/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs index c7f366660..b30da28c4 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs @@ -8,19 +8,28 @@ namespace SixLabors.ImageSharp.Formats.Jpeg internal static class JpegThrowHelper { /// - /// Cold path optimization for throwing -s + /// Cold path optimization for throwing 's. /// - /// The error message for the exception - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowImageFormatException(string errorMessage) - { - throw new ImageFormatException(errorMessage); - } - - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowBadHuffmanCode() - { - throw new ImageFormatException("Bad Huffman code."); - } + /// The error message for the exception. + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowImageFormatException(string errorMessage) => throw new ImageFormatException(errorMessage); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowBadMarker(string marker, int length) => throw new ImageFormatException($"Marker {marker} has bad length {length}."); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowBadQuantizationTable() => throw new ImageFormatException("Bad Quantization Table index."); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowBadHuffmanCode() => throw new ImageFormatException("Bad Huffman code."); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowBadSampling() => throw new ImageFormatException("Bad sampling factor."); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowBadProgressiveScan(int ss, int se, int ah, int al) => throw new ImageFormatException($"Invalid progressive parameters Ss={ss} Se={se} Ah={ah} Al={al}."); + + [MethodImpl(InliningOptions.ColdPath)] + public static void ThrowInvalidImageDimensions(int width, int height) => throw new ImageFormatException($"Invalid image dimensions: {width}x{height}."); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs index 1c9d207cd..31a5a0eeb 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -35,22 +34,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg } [Theory] - [WithFile(TestImages.Jpeg.Issues.CriticalEOF214, PixelTypes.Rgba32)] - public void DecodeBaselineJpeg_CriticalEOF_ShouldThrow(TestImageProvider provider) - where TPixel : struct, IPixel - { - // TODO: We need a public ImageDecoderException class in ImageSharp! - Assert.ThrowsAny(() => provider.GetImage(JpegDecoder)); - } - - [Theory] - [WithFile(TestImages.Jpeg.Issues.InvalidJpegThrowsWrongException797, PixelTypes.Rgba32)] - public void LoadingImage_InvalidTagLength_ShouldThrow(TestImageProvider provider) + [WithFileCollection(nameof(UnrecoverableTestJpegs), PixelTypes.Rgba32)] + public void UnrecoverableImagesShouldThrowCorrectError(TestImageProvider provider) where TPixel : struct, IPixel => Assert.Throws(() => provider.GetImage()); - - [Theory] - [WithFile(TestImages.Jpeg.Issues.AccessViolationException798, PixelTypes.Rgba32)] - public void LoadingImage_BadHuffman_ShouldNotThrow(TestImageProvider provider) - where TPixel : struct, IPixel => Assert.NotNull(provider.GetImage()); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index 9f34d7d09..ff49de248 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -31,6 +31,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Issues.ExifGetString750Load, TestImages.Jpeg.Issues.ExifGetString750Transform, + // LibJpeg can open this despite the invalid desity units. + TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825B, + // High depth images TestImages.Jpeg.Baseline.Testorig12bit, }; @@ -54,6 +57,31 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Issues.OrderedInterleavedProgressive723C }; + public static string[] UnrecoverableTestJpegs = { + + TestImages.Jpeg.Issues.CriticalEOF214, + TestImages.Jpeg.Issues.Fuzz.NullReferenceException797, + TestImages.Jpeg.Issues.Fuzz.AccessViolationException798, + TestImages.Jpeg.Issues.Fuzz.DivideByZeroException821, + TestImages.Jpeg.Issues.Fuzz.DivideByZeroException822, + TestImages.Jpeg.Issues.Fuzz.NullReferenceException823, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824A, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824B, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824C, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824D, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824E, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824F, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824G, + TestImages.Jpeg.Issues.Fuzz.IndexOutOfRangeException824H, + TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825A, + TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825C, + TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825D, + TestImages.Jpeg.Issues.Fuzz.ArgumentException826A, + TestImages.Jpeg.Issues.Fuzz.ArgumentException826B, + TestImages.Jpeg.Issues.Fuzz.ArgumentException826C, + TestImages.Jpeg.Issues.Fuzz.AccessViolationException827 + }; + private static readonly Dictionary CustomToleranceValues = new Dictionary { diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index e28caf627..c99fe8d65 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -172,8 +172,31 @@ namespace SixLabors.ImageSharp.Tests public const string OrderedInterleavedProgressive723C = "Jpg/issues/Issue723-Ordered-Interleaved-Progressive-C.jpg"; public const string ExifGetString750Transform = "Jpg/issues/issue750-exif-tranform.jpg"; public const string ExifGetString750Load = "Jpg/issues/issue750-exif-load.jpg"; - public const string InvalidJpegThrowsWrongException797 = "Jpg/issues/Issue797-InvalidImage.jpg"; - public const string AccessViolationException798 = "Jpg/issues/Issue798-AccessViolationException.jpg"; + + public static class Fuzz + { + public const string NullReferenceException797 = "Jpg/issues/fuzz/Issue797-NullReferenceException.jpg"; + public const string AccessViolationException798 = "Jpg/issues/fuzz/Issue798-AccessViolationException.jpg"; + public const string DivideByZeroException821 = "Jpg/issues/fuzz/Issue821-DivideByZeroException.jpg"; + public const string DivideByZeroException822 = "Jpg/issues/fuzz/Issue822-DivideByZeroException.jpg"; + public const string NullReferenceException823 = "Jpg/issues/fuzz/Issue823-NullReferenceException.jpg"; + public const string IndexOutOfRangeException824A = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-A.jpg"; + public const string IndexOutOfRangeException824B = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-B.jpg"; + public const string IndexOutOfRangeException824C = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-C.jpg"; + public const string IndexOutOfRangeException824D = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-D.jpg"; + public const string IndexOutOfRangeException824E = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-E.jpg"; + public const string IndexOutOfRangeException824F = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-F.jpg"; + public const string IndexOutOfRangeException824G = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-G.jpg"; + public const string IndexOutOfRangeException824H = "Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-H.jpg"; + public const string ArgumentOutOfRangeException825A = "Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-A.jpg"; + public const string ArgumentOutOfRangeException825B = "Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-B.jpg"; + public const string ArgumentOutOfRangeException825C = "Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-C.jpg"; + public const string ArgumentOutOfRangeException825D = "Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-D.jpg"; + public const string ArgumentException826A = "Jpg/issues/fuzz/Issue826-ArgumentException-A.jpg"; + public const string ArgumentException826B = "Jpg/issues/fuzz/Issue826-ArgumentException-B.jpg"; + public const string ArgumentException826C = "Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg"; + public const string AccessViolationException827 = "Jpg/issues/fuzz/Issue827-AccessViolationException.jpg"; + } } public static readonly string[] All = Baseline.All.Concat(Progressive.All).ToArray(); @@ -236,7 +259,7 @@ namespace SixLabors.ImageSharp.Tests public const string Rgba321010102 = "Bmp/rgba32-1010102.bmp"; public const string RgbaAlphaBitfields = "Bmp/rgba32abf.bmp"; - public static readonly string[] BitFields + public static readonly string[] BitFields = { Rgb32bfdef, Rgb32bf, diff --git a/tests/Images/External b/tests/Images/External index 32dc8aec1..c4098e463 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 32dc8aec1109b681f056264e6bde1f3a76f08aba +Subproject commit c4098e463ab0e7128ae196b7f963369271df8fd3 diff --git a/tests/Images/Input/Jpg/issues/Issue214-CriticalEOF .jpg b/tests/Images/Input/Jpg/issues/Issue214-CriticalEOF.jpg similarity index 100% rename from tests/Images/Input/Jpg/issues/Issue214-CriticalEOF .jpg rename to tests/Images/Input/Jpg/issues/Issue214-CriticalEOF.jpg diff --git a/tests/Images/Input/Jpg/issues/Issue797-InvalidImage.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue797-NullReferenceException.jpg similarity index 100% rename from tests/Images/Input/Jpg/issues/Issue797-InvalidImage.jpg rename to tests/Images/Input/Jpg/issues/fuzz/Issue797-NullReferenceException.jpg diff --git a/tests/Images/Input/Jpg/issues/Issue798-AccessViolationException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue798-AccessViolationException.jpg similarity index 100% rename from tests/Images/Input/Jpg/issues/Issue798-AccessViolationException.jpg rename to tests/Images/Input/Jpg/issues/fuzz/Issue798-AccessViolationException.jpg diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue821-DivideByZeroException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue821-DivideByZeroException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8ace30e1fbcab974ea2ec4888b441c4ee75b637e GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOLaWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@g9Ey3 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue822-DivideByZeroException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue822-DivideByZeroException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4378f429e6a96238859432baffd198ab0854d53e GIT binary patch literal 397 zcmex=Wcj9NnTq1L7-AG*#r~ReW8)bK;5r z|LgxF08lMsXjD{1X2t8Krq};~5)A)2LDKag0t6U@AvA~yXCWAjK*0kHf*cGA3<}JQ zN(@YbjLcWN?GIo1n54W_dVT2R+L!l=dHyr-2On+QzLjaZy&&WNBMjmU49tuiKvyFG zBNH=FLREl~fr){YnS~i91LO+|DH?8cESkiem~>IeC=jSjj1dT6Dj+l?NV~WoJ6z&_ z14x3AK~VAkEe2&~kU7kP4E7AyzlG-ByO)1Qd-L7Ah>whc^)1`7-fa4P`|R(|C{wpv qH%vEuI=zjlBv?kR{NCK>hSpod(|6t3IC~OaUnySO;liH(|0V#OGO4)$ literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue823-NullReferenceException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue823-NullReferenceException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e18bbe231031fe2c659fe9e1c84c0fba8a9855c4 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GjgRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@1R}cp literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-A.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-A.jpg new file mode 100644 index 0000000000000000000000000000000000000000..49e4d04e7864844e1d2709897d277a9531c889d3 GIT binary patch literal 397 zcmex=k#+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@oV&V& literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-B.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-B.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ac2e882a45e3af1487549fbf420e78ecfebb4450 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO635aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@l*_t+ literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-C.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-C.jpg new file mode 100644 index 0000000000000000000000000000000000000000..69b7c030a231d278c23915bb81a7cc79a3c83328 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYT*Sa6$jB_n`2PrlI0FMSBLfOx zWMT$Ns0uJLFfp()voOOXfqX$BMZ=AbMU$8llP)S51p<|c0ey!_#-&**JUB)o%O4S3V{wZez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRBB)nWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@0;0P7 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-E.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-E.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b6e7ed11e5a08907d0836f30fd80b2ff8d2bdc13 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oPmLvk%<8r zFfuU%B~%3%8JHMYnOT@&azMVIkfPy6$D&EhiAfigi~@nm#DG3!gsFhgj3Djeg6I;A z41$XPZ!z#NgUn$TWUyzr{w*~3-o5-g+MDm@MSNrotZ&(t^=8xW+h>1wMwzez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYWMW_vWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(qV`sE%b|0LlsqDH?8cESkiem~>IeC=jSg4Crr|X}8b*2I*u3 z873}>Bmp*$kwH-L|1Aa{pyf=0%z_N|4A;Mf=H9!Pe@A=s-Mom8jDhtn+p^wl`VBOu zGs@KM)(z85pU!V%DhZZRE5A4QxuNye@bq1GHqM@OwcGyim5)ivTcy{BPOg1ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO645aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N U76T8^IwnD8?ad4f5g!=?0mUSVMgRZ+ literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-H.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue824-IndexOutOfRangeException-H.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54bdc29409fdc850dea876308205440152acef7a GIT binary patch literal 308 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO645aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N V76T8^IwnEpUknVtB0e$(0szaIid+By literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-A.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-A.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a47a0057d8134342f32842d17ce99b8b08a9fba0 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@Rie85 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-B.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-B.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ffc801787a5a1b2108acf9513279dd7d994e2f3f GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJ7=Zw$0zxx_w2KR(OE5AB zD*nI4zyq|7Nsw8P!Jgszx6s^s_ww&(Z@!xs@sTmGzGYk1n@zuOpZ(n#W$Je8hUunH zr?)Yc1k0$E-<$i~(0Xfl`mQ@0XHUA?ZGZU6$0X&g((6Mf*S@@0%=4dtKlo_d_N`3Q O?G>->aAD8?e-i*vBD(wl literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-C.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-C.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dfd42e6f539654f35e8cdd503b0e0b6d86f76290 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeKBU{GLYRAOKfWMmd({C|W&oPmLv5h#iT z7@3%X5~>1>3``8H%q+|>DIi}^NYQYkW6>n$#H5Q#Mu9+OVnCmw>j!BU7etp}WDr#R ze~W#!}V{Wx%ckn-_hQDH!tENV_<#DwyZase&0U(yEDqv?bZ#`O`lG0 zV=4)jQ7gYU_qn0<*6{RQcQ($RbhX?5@Rg5A%3Gz^hfc12d9Rq~KLda8(YEbdnWoz- MUfbcqp8x+Q0CV%YTmS$7 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-D.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue825-ArgumentOutOfRangeException-D.jpg new file mode 100644 index 0000000000000000000000000000000000000000..58e96a2b1f66fbdb6d16af3fe6ae76c5ffa8809c GIT binary patch literal 380 zcmex=ez+{VquD8S9pEh;o1zTpH@MP6RT*Y!Im zp7@Ufek1XK`WQo_qAD^gUN<$pMv@?fd4NHXgF%5oftgW>fk}{&`6J{1BMjmU49tuS zD1ecP87QGDz{tSFz{<=b3zG!$1%(t1H#!zgVoprDsALofR3--W9J+pxc5y+tgelMf zpb|y~LB;<}g3N-8>=~|q3(dWEFaM7A=DT?j9~lGdTefAr+4TGN+25T}rf#=xm~Q%X zdK*(ou#8&yy}8c~t+$4!@4B;b_N1%b_J^-rPhwzUV31xPI=S}cy<(pKjQqhz+qQ3I Pnr^RnZHEhc{{Nc**7vOl literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-A.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-A.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aed67b2866003fa24b2bcfe4c1f03791282e75c5 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO6A5aeJ`U{GLYRAOKfWMmd({C|W&oPmLvkpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@2co+C literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-B.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-B.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e320cf62d27e39ad3c6062b1eb2ae60bc560900d GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd(1Ugrofq|Kk0R=EJ zF#{!31sEBa7+9HEm|>DYzMznz;YP=zNz92!7nO_xfy%^yK1J6L(k?EDF2TqksQCXD z0}s$TCP8LF2789<-$HZm-OInDz4>ll#7D-!`j%~3Z#MnDefD=}l&RaT8>X8+o!-V& z5-g)uesAt`L+h>K>AUW1oIUAkxBcNOACr`~O0N%{T>J7~G0%Sn{@|l++qW`Jw^zKj K!-YNn|4jg8`?_EN literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54ccb95c3db9a30a07cb2cdaead4e180732f35e5 GIT binary patch literal 409 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7@Uidll#7D-! z`j%~3Z#Mk~Iq961|97vL=RX5~@X@yITbZWYD_+~-!k+*CCIE7*xn}?X literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue827-AccessViolationException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue827-AccessViolationException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5d770c3b481dc82dac187aabc7c4033a5ff499ff GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({C|W&oS}i4kpTrT zGBE=sR0S9rm>5`@S(ssxK)#@mqTxozqDjn&Nf(uj0)fiJfIdan57I6!h%Uj%AgK8N z76T8^IwnD8K?Zw<>)%3i@7>G4qrLfVUc^Vn!1|VLS#LJ|zJ2z0XOyYitsADBKAqmi zR1z$sR(@~pb3^N`;pw~XY@9vmYPbF2D<6}Tw@R-Mom~6!UNO&q2L9lqZQHjpO}AIP Lw!?)z|Nl(@{FA!; literal 0 HcmV?d00001 From 617c77c084a7f0bdd0f9d022c9a305b703b29c93 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 23 Feb 2019 21:36:37 +1100 Subject: [PATCH 025/223] Lazily derive the huffman tables. Fix #839 (#841) * Lazily derive the huffman tables. Fix #839 * Lazy invoke fast table * Add performance tweaks to scan decoder. * Remove unneccessary classes. --- .../Jpeg/Components/Decoder/FastACTable.cs | 61 +++++++ .../Jpeg/Components/Decoder/FastACTables.cs | 90 ---------- .../Jpeg/Components/Decoder/HuffmanTable.cs | 31 +++- .../Jpeg/Components/Decoder/HuffmanTables.cs | 26 --- .../Jpeg/Components/Decoder/ScanDecoder.cs | 164 ++++++++++++------ .../Formats/Jpeg/JpegDecoderCore.cs | 22 +-- .../Formats/Jpg/JpegDecoderTests.Images.cs | 3 +- tests/ImageSharp.Tests/TestImages.cs | 1 + .../Issue839-ExecutionEngineException.jpg | Bin 0 -> 397 bytes 9 files changed, 209 insertions(+), 189 deletions(-) create mode 100644 src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs delete mode 100644 src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTables.cs delete mode 100644 src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTables.cs create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue839-ExecutionEngineException.jpg diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs new file mode 100644 index 000000000..57d2221ba --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs @@ -0,0 +1,61 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder +{ + internal unsafe struct FastACTable + { + /// + /// Gets the lookahead array + /// + public fixed short Lookahead[512]; + + /// + /// Derives a lookup table for fast AC entropy scan decoding. + /// This can happen multiple times during progressive decoding but always outside mcu loops. + /// + /// The AC Huffman table. + public void Derive(ref HuffmanTable huffmanTable) + { + const int FastBits = ScanDecoder.FastBits; + ref short fastACRef = ref this.Lookahead[0]; + ref byte huffmanLookaheadRef = ref huffmanTable.Lookahead[0]; + ref byte huffmanValuesRef = ref huffmanTable.Values[0]; + ref short huffmanSizesRef = ref huffmanTable.Sizes[0]; + + int i; + for (i = 0; i < (1 << FastBits); i++) + { + byte fast = Unsafe.Add(ref huffmanLookaheadRef, i); + Unsafe.Add(ref fastACRef, i) = 0; + + if (fast < byte.MaxValue) + { + int rs = Unsafe.Add(ref huffmanValuesRef, fast); + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = Unsafe.Add(ref huffmanSizesRef, fast); + + if (magbits != 0 && len + magbits <= FastBits) + { + // Magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FastBits) - 1)) >> (FastBits - magbits); + int m = 1 << (magbits - 1); + if (k < m) + { + k += (int)((~0U << magbits) + 1); + } + + // If the result is small enough, we can fit it in fastAC table + if (k >= -128 && k <= 127) + { + Unsafe.Add(ref fastACRef, i) = (short)((k << 8) + (run << 4) + (len + magbits)); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTables.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTables.cs deleted file mode 100644 index 06b46746a..000000000 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTables.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; - -using SixLabors.ImageSharp.Memory; -using SixLabors.Memory; - -namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder -{ - /// - /// The collection of lookup tables used for fast AC entropy scan decoding. - /// - internal sealed class FastACTables : IDisposable - { - private Buffer2D tables; - - /// - /// Initializes a new instance of the class. - /// - /// The memory allocator used to allocate memory for image processing operations. - public FastACTables(MemoryAllocator memoryAllocator) => this.tables = memoryAllocator.Allocate2D(512, 4, AllocationOptions.Clean); - - /// - /// Gets the representing the table at the index in the collection. - /// - /// The table index. - /// - [MethodImpl(InliningOptions.ShortMethod)] - public ReadOnlySpan GetTableSpan(int index) => this.tables.GetRowSpan(index); - - /// - /// Gets a reference to the first element of the AC table indexed by - /// - /// The frame component. - [MethodImpl(InliningOptions.ShortMethod)] - public ref short GetAcTableReference(JpegComponent component) => ref this.tables.GetRowSpan(component.ACHuffmanTableId)[0]; - - /// - /// Builds a lookup table for fast AC entropy scan decoding. - /// - /// The table index. - /// The collection of AC Huffman tables. - public unsafe void BuildACTableLut(int index, HuffmanTables acHuffmanTables) - { - const int FastBits = ScanDecoder.FastBits; - Span fastAC = this.tables.GetRowSpan(index); - ref HuffmanTable huffmanTable = ref acHuffmanTables[index]; - - int i; - for (i = 0; i < (1 << FastBits); i++) - { - byte fast = huffmanTable.Lookahead[i]; - fastAC[i] = 0; - if (fast < byte.MaxValue) - { - int rs = huffmanTable.Values[fast]; - int run = (rs >> 4) & 15; - int magbits = rs & 15; - int len = huffmanTable.Sizes[fast]; - - if (magbits != 0 && len + magbits <= FastBits) - { - // Magnitude code followed by receive_extend code - int k = ((i << len) & ((1 << FastBits) - 1)) >> (FastBits - magbits); - int m = 1 << (magbits - 1); - if (k < m) - { - k += (int)((~0U << magbits) + 1); - } - - // if the result is small enough, we can fit it in fastAC table - if (k >= -128 && k <= 127) - { - fastAC[i] = (short)((k << 8) + (run << 4) + (len + magbits)); - } - } - } - } - } - - /// - public void Dispose() - { - this.tables?.Dispose(); - this.tables = null; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs index 90b362465..a2c9bade1 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs @@ -17,6 +17,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder [StructLayout(LayoutKind.Sequential)] internal unsafe struct HuffmanTable { + private bool isDerived; + + private readonly MemoryAllocator memoryAllocator; + +#pragma warning disable IDE0044 // Add readonly modifier + private fixed byte codeLengths[17]; +#pragma warning restore IDE0044 // Add readonly modifier + /// /// Gets the max code array /// @@ -50,16 +58,31 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// The huffman values public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan codeLengths, ReadOnlySpan values) { + this.isDerived = false; + this.memoryAllocator = memoryAllocator; + Unsafe.CopyBlockUnaligned(ref this.codeLengths[0], ref MemoryMarshal.GetReference(codeLengths), (uint)codeLengths.Length); + Unsafe.CopyBlockUnaligned(ref this.Values[0], ref MemoryMarshal.GetReference(values), (uint)values.Length); + } + + /// + /// Expands the HuffmanTable into its derived form. + /// + public void Derive() + { + if (this.isDerived) + { + return; + } + const int Length = 257; - using (IMemoryOwner huffcode = memoryAllocator.Allocate(Length)) + using (IMemoryOwner huffcode = this.memoryAllocator.Allocate(Length)) { ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.GetSpan()); - ref byte codeLengthsRef = ref MemoryMarshal.GetReference(codeLengths); + ref byte codeLengthsRef = ref this.codeLengths[0]; // Figure C.1: make table of Huffman code length for each symbol ref short sizesRef = ref this.Sizes[0]; short x = 0; - for (short i = 1; i < 17; i++) { byte length = Unsafe.Add(ref codeLengthsRef, i); @@ -119,7 +142,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } } - Unsafe.CopyBlockUnaligned(ref this.Values[0], ref MemoryMarshal.GetReference(values), 256); + this.isDerived = true; } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTables.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTables.cs deleted file mode 100644 index dc066aa0a..000000000 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTables.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder -{ - /// - /// Defines a 2 pairs of huffman tables. - /// - internal sealed class HuffmanTables - { - private readonly HuffmanTable[] tables = new HuffmanTable[4]; - - /// - /// Gets or sets the table at the given index. - /// - /// The index - /// The - public ref HuffmanTable this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref this.tables[index]; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs index 070652a9f..ef4b359ff 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; @@ -25,9 +26,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder private static readonly int[] Bias = { 0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047, -4095, -8191, -16383, -32767 }; private readonly JpegFrame frame; - private readonly HuffmanTables dcHuffmanTables; - private readonly HuffmanTables acHuffmanTables; - private readonly FastACTables fastACTables; + private readonly HuffmanTable[] dcHuffmanTables; + private readonly HuffmanTable[] acHuffmanTables; + private readonly FastACTable[] fastACTables; private readonly DoubleBufferedStreamReader stream; private readonly JpegComponent[] components; @@ -95,9 +96,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder public ScanDecoder( DoubleBufferedStreamReader stream, JpegFrame frame, - HuffmanTables dcHuffmanTables, - HuffmanTables acHuffmanTables, - FastACTables fastACTables, + HuffmanTable[] dcHuffmanTables, + HuffmanTable[] acHuffmanTables, + FastACTable[] fastACTables, int componentsLength, int restartInterval, int spectralStart, @@ -159,17 +160,35 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } } - private void ParseBaselineDataInterleaved() + private unsafe void ParseBaselineDataInterleaved() { // Interleaved int mcu = 0; int mcusPerColumn = this.frame.McusPerColumn; int mcusPerLine = this.frame.McusPerLine; + + // Pre-derive the huffman table to avoid in-loop checks. + for (int i = 0; i < this.componentsLength; i++) + { + int order = this.frame.ComponentOrder[i]; + JpegComponent component = this.components[order]; + + ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; + ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; + dcHuffmanTable.Derive(); + acHuffmanTable.Derive(); + + ref FastACTable fastAcTable = ref this.fastACTables[component.ACHuffmanTableId]; + fastAcTable.Derive(ref acHuffmanTable); + } + for (int j = 0; j < mcusPerColumn; j++) { for (int i = 0; i < mcusPerLine; i++) { // Scan an interleaved mcu... process components in order + int mcuRow = mcu / mcusPerLine; + int mcuCol = mcu % mcusPerLine; for (int k = 0; k < this.componentsLength; k++) { int order = this.frame.ComponentOrder[k]; @@ -177,18 +196,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; - ref short fastACRef = ref this.fastACTables.GetAcTableReference(component); + ref FastACTable fastAcTable = ref this.fastACTables[component.ACHuffmanTableId]; + ref short fastACRef = ref fastAcTable.Lookahead[0]; + int h = component.HorizontalSamplingFactor; int v = component.VerticalSamplingFactor; - int mcuRow = mcu / mcusPerLine; - // Scan out an mcu's worth of this component; that's just determined // by the basic H and V specified for the component for (int y = 0; y < v; y++) { int blockRow = (mcuRow * v) + y; Span blockSpan = component.SpectralBlocks.GetRowSpan(blockRow); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); + for (int x = 0; x < h; x++) { if (this.eof) @@ -196,12 +217,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder return; } - int mcuCol = mcu % mcusPerLine; int blockCol = (mcuCol * h) + x; this.DecodeBlockBaseline( component, - ref blockSpan[blockCol], + ref Unsafe.Add(ref blockRef, blockCol), ref dcHuffmanTable, ref acHuffmanTable, ref fastACRef); @@ -225,7 +245,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// number of blocks to do just depends on how many actual "pixels" each component has, /// independent of interleaved MCU blocking and such. /// - private void ParseBaselineDataNonInterleaved() + private unsafe void ParseBaselineDataNonInterleaved() { JpegComponent component = this.components[this.frame.ComponentOrder[0]]; @@ -234,14 +254,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; - ref short fastACRef = ref this.fastACTables.GetAcTableReference(component); + dcHuffmanTable.Derive(); + acHuffmanTable.Derive(); + + ref FastACTable fastAcTable = ref this.fastACTables[component.ACHuffmanTableId]; + fastAcTable.Derive(ref acHuffmanTable); + ref short fastACRef = ref fastAcTable.Lookahead[0]; int mcu = 0; for (int j = 0; j < h; j++) { - // TODO: Isn't blockRow == j actually? - int blockRow = mcu / w; - Span blockSpan = component.SpectralBlocks.GetRowSpan(blockRow); + int blockRow = j; + Span blockSpan = component.SpectralBlocks.GetRowSpan(j); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int i = 0; i < w; i++) { @@ -250,12 +275,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder return; } - // TODO: Isn't blockCol == i actually? - int blockCol = mcu % w; - this.DecodeBlockBaseline( component, - ref blockSpan[blockCol], + ref Unsafe.Add(ref blockRef, i), ref dcHuffmanTable, ref acHuffmanTable, ref fastACRef); @@ -340,16 +362,29 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder int mcu = 0; int mcusPerColumn = this.frame.McusPerColumn; int mcusPerLine = this.frame.McusPerLine; + + // Pre-derive the huffman table to avoid in-loop checks. + for (int k = 0; k < this.componentsLength; k++) + { + int order = this.frame.ComponentOrder[k]; + JpegComponent component = this.components[order]; + ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; + dcHuffmanTable.Derive(); + } + for (int j = 0; j < mcusPerColumn; j++) { for (int i = 0; i < mcusPerLine; i++) { // Scan an interleaved mcu... process components in order + int mcuRow = mcu / mcusPerLine; + int mcuCol = mcu % mcusPerLine; for (int k = 0; k < this.componentsLength; k++) { int order = this.frame.ComponentOrder[k]; JpegComponent component = this.components[order]; ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; + int h = component.HorizontalSamplingFactor; int v = component.VerticalSamplingFactor; @@ -357,9 +392,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder // by the basic H and V specified for the component for (int y = 0; y < v; y++) { - int mcuRow = mcu / mcusPerLine; int blockRow = (mcuRow * v) + y; Span blockSpan = component.SpectralBlocks.GetRowSpan(blockRow); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int x = 0; x < h; x++) { @@ -368,12 +403,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder return; } - int mcuCol = mcu % mcusPerLine; int blockCol = (mcuCol * h) + x; this.DecodeBlockProgressiveDC( component, - ref blockSpan[blockCol], + ref Unsafe.Add(ref blockRef, blockCol), ref dcHuffmanTable); } } @@ -396,56 +430,78 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// number of blocks to do just depends on how many actual "pixels" this /// component has, independent of interleaved MCU blocking and such ///
- private void ParseProgressiveDataNonInterleaved() + private unsafe void ParseProgressiveDataNonInterleaved() { JpegComponent component = this.components[this.frame.ComponentOrder[0]]; int w = component.WidthInBlocks; int h = component.HeightInBlocks; - ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; - ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; - ref short fastACRef = ref this.fastACTables.GetAcTableReference(component); - - int mcu = 0; - for (int j = 0; j < h; j++) + if (this.spectralStart == 0) { - // TODO: isn't blockRow == j actually? - int blockRow = mcu / w; - Span blockSpan = component.SpectralBlocks.GetRowSpan(blockRow); + ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; + dcHuffmanTable.Derive(); - for (int i = 0; i < w; i++) + int mcu = 0; + for (int j = 0; j < h; j++) { - if (this.eof) - { - return; - } - - // TODO: isn't blockCol == i actually? - int blockCol = mcu % w; + Span blockSpan = component.SpectralBlocks.GetRowSpan(j); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); - ref Block8x8 block = ref blockSpan[blockCol]; - - if (this.spectralStart == 0) + for (int i = 0; i < w; i++) { + if (this.eof) + { + return; + } + this.DecodeBlockProgressiveDC( component, - ref block, + ref Unsafe.Add(ref blockRef, i), ref dcHuffmanTable); + + // Every data block is an MCU, so countdown the restart interval + mcu++; + if (!this.ContinueOnMcuComplete()) + { + return; + } } - else + } + } + else + { + ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; + acHuffmanTable.Derive(); + + ref FastACTable fastAcTable = ref this.fastACTables[component.ACHuffmanTableId]; + fastAcTable.Derive(ref acHuffmanTable); + ref short fastACRef = ref fastAcTable.Lookahead[0]; + + int mcu = 0; + for (int j = 0; j < h; j++) + { + Span blockSpan = component.SpectralBlocks.GetRowSpan(j); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); + + for (int i = 0; i < w; i++) { + if (this.eof) + { + return; + } + this.DecodeBlockProgressiveAC( - ref block, + ref Unsafe.Add(ref blockRef, i), ref acHuffmanTable, ref fastACRef); - } - // Every data block is an MCU, so countdown the restart interval - mcu++; - if (!this.ContinueOnMcuComplete()) - { - return; + // Every data block is an MCU, so countdown the restart interval + mcu++; + if (!this.ContinueOnMcuComplete()) + { + return; + } } } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 9bcfd9ff6..891dd5282 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -52,17 +52,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// The DC Huffman tables /// - private HuffmanTables dcHuffmanTables; + private HuffmanTable[] dcHuffmanTables; /// /// The AC Huffman tables /// - private HuffmanTables acHuffmanTables; + private HuffmanTable[] acHuffmanTables; /// /// The fast AC tables used for entropy decoding /// - private FastACTables fastACTables; + private FastACTable[] fastACTables; /// /// The reset interval determined by RST markers @@ -266,9 +266,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg // Only assign what we need if (!metadataOnly) { - this.dcHuffmanTables = new HuffmanTables(); - this.acHuffmanTables = new HuffmanTables(); - this.fastACTables = new FastACTables(this.configuration.MemoryAllocator); + const int maxTables = 4; + this.dcHuffmanTables = new HuffmanTable[maxTables]; + this.acHuffmanTables = new HuffmanTable[maxTables]; + this.fastACTables = new FastACTable[maxTables]; } // Break only when we discover a valid EOI marker. @@ -378,7 +379,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { this.InputStream?.Dispose(); this.Frame?.Dispose(); - this.fastACTables?.Dispose(); // Set large fields to null. this.InputStream = null; @@ -872,12 +872,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg tableIndex, codeLengths.GetSpan(), huffmanValues.GetSpan()); - - if (tableType != 0) - { - // Build a table that decodes both magnitude and value of small ACs in one go. - this.fastACTables.BuildACTableLut(tableIndex, this.acHuffmanTables); - } } } } @@ -967,7 +961,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The codelengths /// The values [MethodImpl(InliningOptions.ShortMethod)] - private void BuildHuffmanTable(HuffmanTables tables, int index, ReadOnlySpan codeLengths, ReadOnlySpan values) + private void BuildHuffmanTable(HuffmanTable[] tables, int index, ReadOnlySpan codeLengths, ReadOnlySpan values) => tables[index] = new HuffmanTable(this.configuration.MemoryAllocator, codeLengths, values); /// diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index ff49de248..8a9482607 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -79,7 +79,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Issues.Fuzz.ArgumentException826A, TestImages.Jpeg.Issues.Fuzz.ArgumentException826B, TestImages.Jpeg.Issues.Fuzz.ArgumentException826C, - TestImages.Jpeg.Issues.Fuzz.AccessViolationException827 + TestImages.Jpeg.Issues.Fuzz.AccessViolationException827, + TestImages.Jpeg.Issues.Fuzz.ExecutionEngineException839 }; private static readonly Dictionary CustomToleranceValues = diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index c99fe8d65..cf1e49b27 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -196,6 +196,7 @@ namespace SixLabors.ImageSharp.Tests public const string ArgumentException826B = "Jpg/issues/fuzz/Issue826-ArgumentException-B.jpg"; public const string ArgumentException826C = "Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg"; public const string AccessViolationException827 = "Jpg/issues/fuzz/Issue827-AccessViolationException.jpg"; + public const string ExecutionEngineException839 = "Jpg/issues/fuzz/Issue839-ExecutionEngineException.jpg"; } } diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue839-ExecutionEngineException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue839-ExecutionEngineException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0e284349e3115af7f46513de15814f356c2be7b3 GIT binary patch literal 397 zcmex=ez+{VquD8S9pEh;o1zT!kvMP6RT*Y!Im zp7>8302;y=8WmNMS@F85={0eBFjO625aeJ`U{GLYRAOKfWMmd({D0&Z1H&(7Mg|nX z$i)2r2!pBsBLfoyD>Dl-OcKZ!6jC(Y=vXv~IWg&?l2IT~nHbQg==wq0#RbtN7#Rc= z|KDQZ0b0i-$SlZU&v5-)Xzsmx`FFH8-_48o$QW4PvMuY)rr)>E{_c!2b-Q)LbknEP z+n7p%Wz@>=&3$fYy)`_2*PV^CCtdBfKYZn5lJZvR^`Vn%U*0R``Om-~e6(%*R;KCp Nir03yu;>532>>LFyjcJM literal 0 HcmV?d00001 From 6c637af2cfd5cb6372b7ddcd0ff7c0e2865951aa Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 16 Mar 2019 10:16:17 +1100 Subject: [PATCH 026/223] Implement IEquatable and check when summing. (#848) --- .../Formats/Jpeg/Components/Block8x8F.cs | 23 +++++++++++++++++- .../Components/Decoder/QualityEvaluator.cs | 8 ++++-- .../Formats/Jpg/JpegDecoderTests.MetaData.cs | 5 ++-- tests/ImageSharp.Tests/TestImages.cs | 1 + .../issues/Issue845-Incorrect-Quality99.jpg | Bin 0 -> 2270501 bytes 5 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 tests/Images/Input/Jpg/issues/Issue845-Incorrect-Quality99.jpg diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index c9c886f05..c0de45069 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Represents a Jpeg block with coefficients. /// - internal partial struct Block8x8F + internal partial struct Block8x8F : IEquatable { /// /// A number of scalar coefficients in a @@ -538,6 +538,27 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components Unsafe.Add(ref dRef, 7) = bottom; } + /// + public bool Equals(Block8x8F other) + { + return this.V0L == other.V0L + && this.V0R == other.V0R + && this.V1L == other.V1L + && this.V1R == other.V1R + && this.V2L == other.V2L + && this.V2R == other.V2R + && this.V3L == other.V3L + && this.V3R == other.V3R + && this.V4L == other.V4L + && this.V4R == other.V4R + && this.V5L == other.V5L + && this.V5R == other.V5R + && this.V6L == other.V6L + && this.V6R == other.V6R + && this.V7L == other.V7L + && this.V7R == other.V7R; + } + /// public override string ToString() { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/QualityEvaluator.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/QualityEvaluator.cs index 4e11568c8..a7d2a0fde 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/QualityEvaluator.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/QualityEvaluator.cs @@ -84,9 +84,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (int i = 0; i < quantizationTables.Length; i++) { ref Block8x8F qTable = ref quantizationTables[i]; - for (int j = 0; j < Block8x8F.Size; j++) + + if (!qTable.Equals(default)) { - sum += qTable[j]; + for (int j = 0; j < Block8x8F.Size; j++) + { + sum += qTable[j]; + } } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs index 4810985f1..1f1583a39 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs @@ -52,8 +52,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg public static readonly TheoryData QualityFiles = new TheoryData { - { TestImages.Jpeg.Baseline.Calliphora, 80}, - { TestImages.Jpeg.Progressive.Fb, 75 } + { TestImages.Jpeg.Baseline.Calliphora, 80 }, + { TestImages.Jpeg.Progressive.Fb, 75 }, + { TestImages.Jpeg.Issues.IncorrectQuality845, 99 } }; [Theory] diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index cf1e49b27..3f12fab12 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -172,6 +172,7 @@ namespace SixLabors.ImageSharp.Tests public const string OrderedInterleavedProgressive723C = "Jpg/issues/Issue723-Ordered-Interleaved-Progressive-C.jpg"; public const string ExifGetString750Transform = "Jpg/issues/issue750-exif-tranform.jpg"; public const string ExifGetString750Load = "Jpg/issues/issue750-exif-load.jpg"; + public const string IncorrectQuality845 = "Jpg/issues/Issue845-Incorrect-Quality99.jpg"; public static class Fuzz { diff --git a/tests/Images/Input/Jpg/issues/Issue845-Incorrect-Quality99.jpg b/tests/Images/Input/Jpg/issues/Issue845-Incorrect-Quality99.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c796224f9fb6724a354dafbdea6cf650e19ec42d GIT binary patch literal 2270501 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

Ny)`ZOsP>qN{ixCdlZ+tRI#aB6q9zF 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

Q9l=G`|n;(!Cls*WgO%BBM(o%S|o>uQxjvG;V$- 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ξ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≺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

rsuHFzke>J*eh5Qv#6A0Z7FKwT<&*&s-2T4IB1n zrKe$g>K&e%u^82O?ka-6b*^-S_rF)?WsKkk=3+l@dhuSzZ$itRbGD=|K~c#1y?C zI^u+TQzhtf?fhQSs~=CBQGZ#_*t?@KRRUG=0(xM%lYB63HZXxGbj6UW6j~#om;OxI z)c(udpz(w2{#jg#C>>IOh|=HcylIm7ZybdI-pc=QNJH8eGFITZGCHSE^4+_QPBM7o zzD#y+5-;Bvn995r=_gaZ9F~Nh9MtaJL<=Uhf!fBK)IP$QlP_z3+M6zy@C1CkZ}R;j zx58+5V=_?m&X05`YgMt+2I(O7b4z(}VX&ZLFiu!tKwzvf%G%K0G#`G=yU=mBK+#%D zZL4%sXSvJ@y>d~YT)gBuD;WgEB~`v`Yl}3b^W0#&9-wTNCB+w=^17%jW))DZNfOZ_ zezVd_UK!6(Ov-Yu$!k$>qXB2$VtV8ryTHj*WEz;Wg9#>3A7SW+n4n2d2~Ev@D{6_l zMx{skKyLX(nD<26)_&KVLe0j^Cp&dqdxkT8e6hK!SrWE$Vme~=9MX1ON@Isq_nVa& zjfc?A{ZLO{!S$oj#__l%_0=hf*XEN&zU`oCfgf9aN&JrF-V%5!-Y zKa_gD_r8r%%CQI%DIc=Vfmv@7b7<-NEb&J*z>BSW_i5FP{>6WQ=ccdldwgVUnl;NA zU;b(R&#dgzULLPGStp1ILd;^o;inD=O81CzN?%o(R8JqEl>ivE;!m_)d84&~))oD2 z_AH8&dQX#lx;gu>@JE4WlpkQAv(KuJZ(|r!c0IkHy(_e#oSi;QXW*Z?nT1fIYp&%R zwTWgg8JT`2ra{Y@w4nJE$zs;j190m*W{_xJhQp898|7XNn(X$x42^mgk=|yDa{BBs zVHYhs+8G0f%6QDAsm8;2iI`mmPof|5H=4S>9`?RMzV$}27hrlc^=n?wHGA_!`PnHu zoc|3~0v3wC#Qd(RKjj4+&oiH#yj;6B89tC9!4phl`-29tXVE|4t*aBDRe8>%7Z%^w zw6l!tXebXfJyNh2#nQkr*P&*HeatO8a{M@;$lIa2Q0{CL z2)=|^Mb-O?bJ)r;pOym#M#eHg`%!SojGEzsKzH%E7ToBug5(q1`1w<@k4;aj34^-; zs;zA+S@wlGT`w49y_s5yiv#MMj*kgPGyD&b2o~}&3`&oJlOt+(+QKh?TEp0sVk9lv_|2xWsOZ zOzAg&7J~vN$q4uA7=5ae;2?F13YFNK78QQg<}2u5)(;2=HK`{XdFK4(A^n}q+20NM z>mBIom+kxq_!CGYqYs0}_M=%h^Kt86`H;X>uLRV(S(kv^=7^7AnZAg?Et880W0KZQ zuFhiG;4(w=w$=)+7+_Q>3Dc4i%U$7U#i7Ah^DE4-&(@msnW^kj>Ah%g4w@5wz4d`z z_2_;6Cz!3I2E@+3MB9^jXf^&Ip^EN9o~BP&Nr+4vzrng zBp&g@diK+6sr{HGfALfSTqb)0v(<4=f3X{40hD)w{wL(u#h29q6qP!QIEG&C-JJ3& zo8axglpiRm9ldJH1D*UQk8(GkB+zg?_uCl~6EGb53d{0j`?@J$Q|y_MXZCzw-b1@< zsde6qus}oTaTrwj<0)g@cf127wX!jl>rSQfpd+|B6!GRtW4&tI>tSN>@8PP zTiY)-oojl^sQ@xZg}9OmAh4vo1Wjmd5^EvQUXm$%+{S0%sm(F=yJx4dZ`z&Xml$he!9%?ln5Vs1oq`kp>q8ZkEl zQFB_}5L4{`EP89PFx_`NO#~laT(&_*^yNS$R>Ez{l>+nsl$z2UtGB?#VC@eP@i%s& zt7oB#vBf+3W<8^d_W)gaL+MoTp$ByuQrDxn1Tw!u#xpH|%Juk_5g^Ew}gq}(uc^~!IarG;wL zQB+gb-yDVxFMY$VW!&^$&P?r zfpcY)OmQ_;7XUlvuDHB84z0(rbqq5s9{Lc4)gD$gw{0)nGx5o<@h7FwfB)yG$}x>j zS-!_dz5M_)dc)_wvGqr(7r){}_F`p2S}v+zJp$7}N2;aNzw%JcDgV9lno+9b?y5BL zUUM&|MSRjX*r=&7J~O>h+Lv{yxNE*{>K13e{O&; zr~Z^^b<{w`YV?^-rZP%FW%&6U<-oA&j+tr}0)C(J?=;FZJGZ6wJdxK~$&S^f9jY*a zIB;D3l*u)Ork4xOO-%Z=ns?7wvbs8}M7hmN(@WEPAJ}N3lgN_jk$UoiprkwMdtP;w zBb!OK(t^^0dFDw@G?F>iqnMKfpFp)J#g#=DK!$aw^B8lqpR4^oDo=stRqySU*ZgjO z;SC&t+zf*99JXOtoo#>1oGb4x^j3G>yS|?=Tu&P`L8s|GGhQU48PanHo==8I#g(u) z)?gpqH6;P{+s0_`zj6y`VxUu{noxjV*_<~>K@VdOp3)wklFtAZy(^UYmhR8IvnIKX zr@Q;U^K^U-x6eXu!!;>+^UAyT)u@w3ZpMdkgiB+D-y?;aibAeXqUJh zmX&)8Hg%oxNMSiOXG0OnzzWccz3zOetrdxUIw+})*Uq3@hG^C%BPW&a5OuUb`9>}; zZ7<&Zhp7VDEXA@cZu}uVSk`cTw(|oVn1%Ev`r-bfUt55Ba?@% z{cYw}O15gs-*~-aa-TdTNKgo$aS6NcSjG2q8<2bCSJk)555i4fa)MtkkVATV%)a(N zJ@f3mxYkLL*fNbe#|a5}lWYC(99H0YRX*H$LzM?PidY!f#dhX-_xtttS?c4^zhk!1`=DMyf7~9X;l?;U5@mQDNbQ{3 z_Qz~m_NQVu$L<}>vk+)XcxUJq6Ld#sTi@AZaY52A*mJ1KHt444A$)C5Yye>6iIQ+_2aT}l3B2jq)xz&5V9GZ-)DKFkz^Re#EyxRin zWl=qiA(ZAm9k}65EFQ^=1m_A(0K?3V`tbDlNPTjRKJL5)JsHz^K425c|KW*iS5H;& zR`>hJn}Nw9{^8b9nJ0x3j6i0UmM<{{an$LpzHCjn)f+FE^WgD@&p3s<#QEo^=z}c> z$dUYb1BOi2K>IvVHu4z&rIKJ|DmJ>IqBX0iZJzZ_ z*m1g1R0M}_a?=>&K$?HWc#*7;d#%cnf14Fkyilj2lj)~^0pru?4MMT(3cf27#})rH zn*4hw++?~azB|LuvB;W0^t&u3LkoA<#Slr=5-e5zMSz=|qbFO$Nit`>1rfVz zuvPC^4?FVRkC`aSwC$c`7^gs$C%giN%a4WdF%5Zl9P*|MvmkF-&tBU#jgE13E|T%q z_V4q^-<*YxvMJvK9CVIu#Po?JFlr%m=y!gYh|N|NlzK}%KU@%k*nL%VZ^uJX@j~RU z!W{4E;H7;VlArOg2$_DAz8b~8CWHxsN}N4um{<$k%E!$+BFWyj-Eb^ABjP;DchA@_ z^Ch?=bGmH)ziH%O%B-YUzUQ6_(Ehn%k{a>O8K>15uL!mflP~<%{P{wx<`2p}Q;i#_(4=wm+e$G$ao+7K z_eMJ!lrii}hq|m);C8~%@+gSzjLht$YYr3M3c)!0qTw^>nQNb-)8lp3q!-&SP@py+ z1}rE~Qf&0?7w-&-7&kJ^|fmeuxjbyr;Ds0hh8R_cX&$p;ZQVT%!JTJ6(Z+@A>HOw?_J z!-3oLYq1^9%}bzPu{+8cs}l-{qfuGl4HsxJesmg4EontLjraNSV-o;qaO#~8XR9A+mpZ@M&Bt0{2AH*GG22J?sKz%GBmm*ZIt#Um;pfwA zE=o!wt2W>`Ft$h6Ti1-27t|GDo$;Jvk|)PfEuMF5aD$V*Vd;)#HrwBkJcX!Ot%dN0 z_a$H8yKc>g!@E0q!SBxN8VBIaUj-`}JyTJ15f#&QDLXY|P6(GdXUcnP7g(me>T}SI z%wqN|QIQjUk~~k?y<^Qif5g|8P>+-~GeE0p174+&=)`Eb$0lvxc6n_x$0) zw*P19$p6IZ@~~p;L8tycx#}8gAT|DnbAx@Jp@(@8dUMHijT^daUGe{%qy5MEAI{P4 zKb#*}#q)c02sTV%zUST!>lv8CdIo;ThbLn#1N^s$=OFsm2 zJmR|@R6iaBzF+em&xfM*2+%`r@F;^2SlN-nwV|bH1HCg`%~rfm@(ypdWcc zn}CddfE&}P^gOqAZ22{m{uG9(_PCSR4kJg&n7&Bhj+0lT;&XW~ha1P$&NxWWgs5FdtgFY8H`k!C_tOQg?as_l z&oh!`?FmR(l;g=qt{R#8=^lh#L}=H-&w4tEZY5jG)o&*Q&DyYA-=sEOIzam~A4U>S8fxg;$(sZhKAr-{Z%{|_FGPjHE3-<31 z=6Z7Y3RXg6vFW@V$`a_&>reu?ODUHiZd;X58oBaK)o;C0e8DPS*CCyS-xPnP0DtD@ z4Z9b->U`ymorK-E&+&Gq6Z=z&e$TXTq=-kVqt;BmMZNbqcDrgoU7>~Y=|yUVEFLV`%6K!8 z{92kX7+GX$2V)M&;x+?hYKmy)VWr#p+mu63XQcn9&oon2;6B^Uz9RZ|AfP-mwxnLQr@3B1}y z><(I5(@qt~h|y<#-kaW3v(L$R@m7FY?0~q*nu9GqlBcqZ=NpHJe_H9=tUg`K(NBxh zR&oyygjlh?mgTjrEv=X+lUYtpIYbh!oW==r<~Yh)84UF*>Aq}AH5W)Ng$ zlM!i<4z}UbA}Bj-?B}uDQ<05DyG|6;KacyNm|A%QlU#>QzcOOs>W7lZh5n1(u+?Km zH9uOr(3C^cTA7;OQx1(b;X$Lmg{K>dNHCEkN6;ZP8?^20dSNwVoH3JfzQUx?z0iwQ zoPC##->{zvbPqatv501{x11W1u{h5a&ig3@vlSBKo_V&GD@fL@D4*Ym!8D@!%#ulnJebWjZ%Pk$r|!Ln37viwo9j?o$_h*NnDM>q8#gR7 zA4SWZCnAt5(b(W>IMm>y_UPfj^n{A*bEso0H!Yk}b%G*#At+=6T*?!@46Y83tOjIu ztR2X&u0h{B(f@(YId&G?ZSAh!+?(Am4lX^XNXcz^v(f3O-+ie6>UoCIQLCa;7p@6k zlY6a43qn{3w?W(FoV2OcuCk`C|#mgEuFqu>giq0@=**G7)ugTmDi6TKZx{Sgv+fzw`C-f+ce~#5nSwuo> zH$xxIPgiPFkDY-DE?dW=dDIuX4;-}yy&Ak_Bg!30y0*fPt!pd_s?cfMa30&%BK>gdA5uEqK}%5FputcRYqSs>}7&a=QEWYj$YC+hkX+Z%2#kB{V#r3F=Ok zz;FFp5UwSCC%PL1BK;}s%?_8+M}+Y+VV3Nb+z#M8GH)!1+=;sAuIJR=;~&liuwQ;f zkgn$Gl|NPoO1skq^<11;*Qj5S-SaHfpF0uWx7T^^6l~umyRKcVRQ$DKZ25F@d@JW3 zdbx(uKA0FaE^=SE1a1}|WkiIUQME6eC51K#Ji0U9?3r1lv@syQ@EN_Mf`wMl*3S;Y zuIgG3H~>o~TquaqT zb-mDz{GkiBxMdPrA@&<{esX*f0>7hyhE{y66Fyw~Jy7$P{mGrkoRbNbgQRZ}y3iOp zg{Z-|y1ERVH2Dub;BTklo|#G1{D%X>lzF_%LyS#w$F4l-B5eC(FqE=+h)}t$(7fkU z)@6Q#^;TN)s2b{uPf7wtu(w&ovosK6XytCI`y-{(E~+Q4wqiSme%W`6W|pQwG9H0n zXV!rt$$y$vyFu#!5wEb)_^MpwSY6{nRbcjwWVTTd{RSnzmeqUu=ot*%vBc6yp0=Uv zrq{ZN!hwJO!s-&9kzSkhwUIB|>=UbPhl(T*!ccmhNu0scMDN9L?4o#xL*sRE?D9)t z&~jXrB#GA(L(Hh-xq|V$Tc0*BcJoTu8TqsAASKCq2wukD!8=$GZ1rROkNWpo@h=-! zof_8jG0hMdWJTWqf>t8j;5L!3}*t_CEzNf8C9{)KxKnq zYO~#nraMbu?PmKY@YLuSG_+M$k-(hvk;Y)fS!NzJN}MJ11dC|Q*+8zo0LUzWdAf2G zZ-iy*=0Il%tEn)}Udw{BKoAT5mYE@{fSw^gGt#OR2Q5K>sA^g{sJSYxEqYt*b(V0$ zFVZoJ_+y^4RNYJr#n>Wyxn|wdguaR0DtC&n9$Oz{;qbnuQ$cvETjfSmR`R!X+nsFr z3nYffU{C&!l;SfogoG#E@F4c_$f7mfOW?ljX;3lJy+JDm-YQfEZ-Ieml0B>mbm z;yXo{Wa3Iz(+BVTmT7pBMu9SfsFmy_jjtbA4H|obx zt1gx8_K&{FdOJt5(=`Ga`C1tAVTF$(`Z8+8D%6K?jE1_ig96I9cp@HF8*QU#{zfGO z_c=$qBP7uh607+GhTYfE1G4qR3wD-D!*Lf>XctO;7dQB3C4R?_qU|LKq_~$6MW{~; z9JYms;8d~Qngih(d|*0YOS!uWbPh*x&a#J$2)Cv+W${3!NHbGRM&Es1Aa0I|DX;k@ z#EkxZ&KVk27e4C+gI>*q=!kC}KfFfXcF%TWMTe!jNhuPnhN|rfX|kCyRYhnY6tC~5 zrd%1X)QU+Fjnd7ZDffExz||ZxIPH{t z4AINQQH`Zhjhmlu8^naTQsp?+zK^tYOmyu!Ny=jbniZDWtkAyTY)tauUegh%*DaL( z{sl3bzP9sil*PN&{A_DOMAZX*Sd+6f&b&HND`2s7k@dJRLJ21#KEME{VrZq#scUIh%16F86`s&T|8^{IC#1NjNPtc0V_V+h+ zYr5_II~*b^ccb2|0J{P7iTA^&R2iOPS-KL3{TAuh_ue+rTXOGlf`6Jzn0ZHCN~ZJB zo2Eqw#!BvBxph|*`4E!(8PvBJm<3`hE?NBfY!A4*Mf+KSBiJWw3}^mI*u_f5plF?Haefi@c0@0^~qlaR{Zvv9mj_f8SoZ$Pe z)w%xxFAoxBky8rXYUpE-xP(Pj57!t>7A5JY+0ZsDyMo~gp`gDgRulHoS>sP$wdNTX zK`zt+=b(!XuRUz2fd-bgzQj7jpt4Q#v*-1_kaC!u@iZ8a0%}}Z6`~Ye_j}W+bG`ek z&PU(vs~)W9zy5R0{YTWzgv0M?;_k?QZ@Nlv4K4UoeSf}|_XM2aL^cky<9<@5*2N>AOGG8) z{B_R!l^|{ve^D}M2D~#m;ro)szig>jOCRH%s}3^!^ZE3t{J!3tYwb_mcIVv)_f!b_ z^>6fFrgb*b`RfYTo8K(g-s3rQUk`I18TRVD+{wFt(}5(AbUqm2HUPe^YpWk_l`H*U z|bne%##*Y&i$5k2|LgLpB|e%{};YwnhH9J}gfU2FP2< zhf?{`15xq7e(rF;XH0W4NQDHN*aSb&8vEZsB9OaGS?DoK!^l^+^8$h_^exhC;D3Gi>E^mueC{S_Ga7iF!1;c1Cu;~FCIr`CUW8OcDZI`{use?YP_mw5$= z^sHU0OtY1}zMr&jSUUf_Vp-o5+)Ci81CC;9-!5-@rKzQb*up%rZSIb9X;{rS;H-V# zOt6J%?&)YD)GXgjjkK=r-D&~}5NOS@SIaeh$RN&`+?PqiR5**{UfN;lx7154S_c=}rQWUC(-}8L+@hyaoc>D^4}+FdQ7IA2AfF28)}yeTOZn zb6|1OJ7RwBZ&o(1`K^|1ys_0x-R|{4uD^|TwVZr|Wz;fYd-qust23TGEou;5?-;(S-p$yAMe{4JJ~+Pw^6Fvjcz;g-S-Gh)(i3R6viihZK|z zW2BvuSdbnbRW_a0*Y0+kT1LP{px=TGRF?xCY?fCOYk}pGJD85D`s(M3!6gD-7_^l| zZVC9s00>dCp`6x&Got0ew%Dn~z`Q>(hWA52<*SDeAuZ+P+@OcKfuBxEBuf0lsHjN& zSX6?;BCB?tOC5^h0To@=8Ac4u$-F)cWq1PY%4pocLB})Rl7WNJ3Ui32Z<*kfp5L(L zkBr3ec(+AJ9$p0s`C>}@ZXIWF>Rc3j3y5e>XXM`np7xM)KSt= z=@?ePKyrH`$jUc`5~~_!`5~(!5|9bwF4fR0TP;6o%imbp_0w3&JnA=4Xr#B>IBWl*&q*N1_a9+wDERjHwgae!8#)$-a zj>a5yO>;#VsVNab01U=vlUdApxvLPxxvxdEM4&$D`Y|TKstlT0Qmzd8uGOSjBvx6G z(3jHw-0Fc7AL)X9bk3v*XjAr*!6E0XAN+vzff4))ND5eQw^8EU)}MZ3HI;)9LD73g zf1ni6!gY0|0dyc(kMEU>K5?2voqR=#JXfYXs`N^FhFFHu$ifLE1`S_~+M0*fMdG^} zZXeW>>^Y~91No;=QBkN!C&=21_w3M_UmIy3Q%DvTFPR%0TVU(WLanR(s zXDwfl`Y)o5_K8_Fwc?^Scku=G=u30GuWLdwU1<jIa`C@{m#3-X*eD*&4y?OX%ee<5P;Jl=K}v6{ z269}L61}c?8guM`Ir&EcnSr+XiBQ|~QZPYLZo3L(U!Ul+mB=P@zTN>NEc3y7K^ATo z4c(j#UnYvHM^19HOL0fy(<@e0b!6c&^WMKAlPxH;oN$!Cl>4So@lS@|fPgI%e)zo6 zg*LHtFecW?(V|*eAfbU3{(OIwMW91~R>KO|lo>p(59EHPARk zO;cBwosp)Jn4?{#Ng~((&fvXBpuWr&IaR|QNtB`k*TCt%<0)?27HSVS@r$%{| zUSgz2>O-n7|7Y8EJwO=VHj%?9?)h00E;5qRj&fJFE@+s~K|J5y{^2KL$b8_BE!QDlh) z&_K6=ul|9=>^U`$#BdJi(SE>3SCu06qm@SfIcdYdXPO1yokh`>1yPqvejqoaouV7a zsM03Aq^NbYoZ!spdj*nAcXc=EiE8er<6;|n9W`XHDDa2S$r*5vR=ThEASX7?%kAXA zZeUbrXmeRm^)V|g`y$aWFSk_&moP#1OWnGi;FeV;^ETv_m#_K61>A+=K@unynW z%Z?bZ;1~y1XtApQ!?%3O%Ph8IUuZ=?|9g=w3b94qlHfXJdwqsHCRIEK){q;x^5-`Y zDY!@6js7QW?!~ZsievndTA>2%gp;VTbZcY86^Qp|0f_aC(2Y*R!M=$756{BK@`oID z*k>BA-B0c&v3*VfNxlQlSRAH;gT|6B^`k+<tQK`{%S#E2ku=xR=zbHB^oj7;?8*z=_ z5G)S&>y7{BpC~o$TkC%7t*uKQO5SXBazC(mdt+`RHHh09-A`fyA3M)#Ra;JHrfgD3 z&MpP-G@pzs9#||8ks54T`uY!q^QL|G~$-mAYj# z|Ihcw@?iI$M;h_GG`Xp>M#(20-g!lLG57BL_P)78wuo_Y8z+m=pu6tafYVs!HGL*t z27JSa@abB>rbndn1Idg5!2CmfO>sY50weZqnP4D}_#%(=(ri z!POb#lR5XqYyaz&v=jF2;=z85hv|)Yn)jni;jFRFZB_;b(z?EB1oe-7={?Rb=}+%F ze+?jCA@93I+fPKLYBkcD3`^@Bg@NRD4e^5X`5!65q(k8l+9?U{j~$su2B-S><2U@L zKCR&K&d>h+oeov1>nW9Lok%_MvmbTHj6ce%cc;VB#?7@;>%U2u&=C{~A;HoXU!7@w zJn-T9CwtqODg?Ru**e`S1O7had(ytX=;7|0`(t*aabar>k(XHEezq?tiM+}%Dm&F< zB%7b*bqviULiXvHGE^VoSNZxOf*Pr6q}euwe7Ao)Hb+ou%T%9Zqg6NHeV&6Oz}Xu7 zkp7^MS6h--tF3m*vh&B2duu}QJXrxC#H<2(=tYOLZ}93i;3+13G6eu%@;hH&HB}D& zLR6~oAHYM>D{m0L*2Ipkhc9XaPa0}k_9F+U@309^#(w?la^(JoRp^E#>zEcgpR3 zp5-fag_$$#)({S%SovC>IxH9HH7ChK7YelLV+V$a8vu!I*M7NbI=CsHuny+QQ6lQ{ zeBCQyvRhr3&?4z`ArBP}QystU6R*r9>}QF~x5U?jd}H}8+b~Hi!N}y;*ibb_z*UA> zMgF7(*1Tgb2g@&eM{sp$d54(3cmFiFetk@S<9k6PnY!}=SOh-4(LNQV-tUWX$QfFQ z@`g^8d%St+M}W_EX*9QRUO|8J;wE>;Phs~{Uc_;mYKq0W^(9sRK`iCl3}(Lgdhb5b zToFfd;>5&+=ev*QcI0<~ z-m`auxHnV-NepAZ#C}ZBW->44nT_3s$DK`@0|YckS7J3*p<7TmW5g-ufiw)7Z8;mq zzf#U1`;K6y9sw<%bvtEl)hRaGk6rIg?WAjBk8Ez4*t^#*%gzZhTe6*(`@(XTKZr;Z z#-X|-)9?H>ZhJqqYIDs?`<`L1&?8nP&AQ#4+4SMqR5k4SQUie)Cbp zuMYVnX#Y9Ixy&a+DZko54~}juMm3gmq<{CWakKh(ojBhvozLjE$cePi9(Ew40^B2V zf6Pffq_$@vPme~V<}|W|G>JT_zW>xgR-VFy{Qpe)|Hkyc=PcKZ-}EU+xbe;kw$EwL zbVGW<>{S(;)2!4kXWe&u3JLEzZ0+BEdiWf~MSLUl3w%p>y5@`}esd<-CK+Ndx-U74 zSor*H;Vi2)4|i^Czb5?f+&^$9*V8Pkv*Z4L+dt%qo{Rl~?*YXh&EM%L!%Wv(N&laRKed@L9KE)z$QpO=jO3t3cUOu1Y1Yi;uw%oBT+s+uV0 zAMrj{RE>L4X#2+(vlAr{bEmPu-=X!ZszA2R!gC_R4Z=Y103>#$!be~E>+qQzI4_^IJQ zB)fuFHj%!}mc(S!KvcYehGscKHgh!7Z>!I!q(CgT;v)lN&~?uVJ~J%5w6~e`8s1T_ ze0NkBqS8bGl)Z2HR#;z0ybf=1y#>1J4TYy^B4WQ3?>)zT5&3xfuow%gZIqjdafTeV zsuFGirfh}QcQ5S`-tL~a-C?s&7kO+6bOqa2qPEN_Wp}#1pja^kI z;Wb(VzbjpuBc9(ZR^2TH)49yW9WE+ z-b+{8Aup&LyD4_$+N2W8J;p+^&D*mGUm1|&{m^%VmkUR1Ly<3JbEI(YUA;##&NNn` zEVqs`+vM3Ji+LjDlong`_Q?3p?^eqaGdKxdG#FZ#*?+?pPTEa7^mx6QvKYS^Fo3_l z$ANG7)PU*ooS8SB1QY3i{yKrgt7y}|P)Nb}^SAsy@TOT{$zS>r+RVrKt zYHPr~u;eNp64cJM>u0aAzZoFbU58uxjKAY@_bgpaA3x2Vyz4uP0!bYif=o~sqTGH^J~^yY?JB&9^q`zjovYy)b>^CP{i_CG+=w%dD7owxitYi z4=&7j=n{2|tRo4rlihefmRN!b!LGAuprhaP+6CF9J4UJN+YfokqkRN7!_BfE?0+JC zTj(vgao__&sOj#r9lMQb#iP!E5m^uYNK6K2Mz&Y+yd3;TF;8}WOkcQ9#m{UfG9E`` zG}-o}|E#Z&KAG-+wAm%2i`|Y{|M=r1-ud{5CB?C+UGPqj;&=t3{ljvM?j@!DJJ~q8 zA0YmQNLFa;;sLbNdIEVq0_UFAI(1gYS_R6 zH`ofxVo_{JLB|M1`b!g5T5>ZysvvL8V>9Yb^V++OuEzYGdE4R(TlG81A$g`&f*JI? z3w`LyI@h52E(Oo`UK^LXvK z{(A=3o5+i`5JR)(Li7&;n5g2q=YK{353aoqxS*kJQyk?;_hI2`c1QQByNDIHv?w)9 z^YkE#bPM!sSXnVP@LVapZNKp9xB4(5oA3gNZ?G!pu-*~zBthv>@!#E0!94A1LllD=qMIaCk6O>48? z!s2fDV23kUnp2#SP}(2OSwJ@CJmHl1HRu&PBEKQie(r7Kr#*VI2eT(-Vw6b_a{R5m~U*cKIxZMqvHUFxpgT+ zVq2ztq*rqepsd?5)%Wf{zC3vQxdbRB_NkM3QN z1|DT;RwK&73O{~p!{B}gkJ!!>W^E@5x50$@db>V>?YMQLzUJtd{ZE(SKl%)fXK%%9 zcP6-QxrNVflGi)?dM*c!Bb}PI6Hihfau-;rhbrHTBeqQQzSJ32PBB-z)bc|=_W9r> zz5{9rR8j7)%QWGgmW`*(A%*`Tbc{8 zVc3+6M&uW~iz{1o_!{lfY%N~9I&BFa! zgm%YLH4%narBzemUysB-H{AXD{KT?{1P}A_cP8cd_8Nq8@8!Pi&@+P=tBCCCT-!Oy zb|n)d)paU8MXAM2IK)ObzL+Df!I1Tt8BW=m_F9>f76waH<_XnT_&^Zp9J}!|{AYN` zFA+YzEIvNbq%446mPqy>CEbaLNQy}6pP(!IKo1Igeumm0(=HDZqtbN?YYK<xjlH;g6k0e#O1dj4e_xv0%)Ms?;)J`NBbE@E4WFI86aonOxHZGss~Jv8Az#N^ESa7eTUG zAmSXG$pq3V_a)gnqoK0;Z?eKpkjd?p%|T1XH$3U#xQy=oW#^^?R=ROiVS#uQ7O7Hb z0DOFOe1cjka{e#C!rq8cAgs@%Y^tyZb%jITq}n=F&kl%2Zv9P)=wn1=v3Y11S#&Q? zVIB5h?2O&JQR#pcl{$?`r-fD#eSpqQ<6j7^jOeyv% zpF<3+y1NNJ7H4mMGGgAoQDKjF@@6)J8m51`VJDGth;wQjq9ScL6rg?eDecXI_v?oI zdt4X=()31gq2{X^*>?`j^X!g(+hGn;!IX@KiZ(&ZUQdx@CyFo1^>m51nXW`&t0@c& zMSKmp9Z2KaR=Y!sOq>K!;PP*4Rjf(^U-Y^J_a>}aMSeQNva)tt6w0kX4INyTe5W_L zM0@Khn^);Mx9KO-M7X+r9AVt={{)L=h(Nv;wiB69is}4?x0Mym$v*qQ6jGmua7oIc1HrtM1Rc z2RkwSyqo!@GQr;E-GivLOQDvqund4f642x<73(&rOg<6HlAdxkBO6rrnx?mao540y z`7y;hu)Vwa;zvdoJFaTor2;m7+-7nU+-@ydpC)4Qa#Pv&~>C17I82bF~e zl>J;Up~a-md_af$8kVR0MIrIc^uaw>y0jfRxz#$=-SvL^{1=}gvZXqbTmOB|P_e;I ziL+%iNWWO#H3X)}ZZ@;+-mRasy1un56X09(060I~e@+`2t+*?;KA-pdnQr!Et}eYVX?s*sk}fH?P3b zP@;eifh+|dFyCw{*KUqDP5bT8XRET-RwvSLJK6e!P1*5o`dBejF&Gv`=KOcOUJf!g z%mcIyif~p^h>EK!78v9_@&Xt4#~3B?Z(2sWCk1%1xdJvN5%ZXe&SXG*s6Q_h4%!V2 z4hmU{g#N)Jz^nQJ1Swsmu0p0{th*dZCs*irjK-wlQQC8R6VO%fA097uv!9I!WsmfR z?U8ag|8#6N7Q$kxVz!jy@d@=0!24k?e648%Nh|sA%oCR|M3pVSj3gwNYS$rd(IIIS z=)HCPXFq9~C+qhS<6TnqtA;Yt`SovWrt5Uk)h}))uO8Og&CV8PHO8_n!Kqonq;Gn9Z$vHDX#+bc)hE-L)IqXZhUE(v zZKf|wED}tc+j$}q4PuXCrJPcW3go`fKu~t&6Q}9Z>ACXTCE)$cRDW9h2u;ZR*faG! zbH{+v_SoYZS0ii;uaKMf^3?3oft}*e| zZ^;11xLuF?+r_$pGdT69Lo2{u^&Us~yJDlVjoC9=@~#ZmMIl{TenM2>0swGiXhb;p zAV}0yOWwTOcdUp#Y-f;Rqdh!8Nh*c&Vhk<6h{{z9ERi{pVsTx=Zn$swa_?nqx>~9a zVczY{(1HqlH1vYsmQsIh0yD?D(fnNhoB6d$4f%4(hMgxu@gO3VA}gC3}b_>Zve+5A^1@5&yyQm55h)&+utl{18Z z)yYQIrC|6RrG6Rd9n1DkI7g^)ouT$8)jQbuv|>j9?Z;wTPEap;di}Ogf8x}<*WM&t z@6Bu|iiE)l)N2gQ}#!aGc(>%5T#f9N1KDy=kW zp*dW>6?kE;Sm|7qvU~iVL&?hE`nGdE$;^~w2f}1U1DZ&H5?R}ztMmu zS%$GHWcxs2@EljIDu&n8@AB#RTP(;U>6mLFA~tN$%)cnhvOlLAaJ~-BE3&WKDD6WU z*C7j7;_KM@Iq)M)aKk<%yVp5?mGd&)nPZWUL5z7Uy=F&5wP^_!8OX-Q#;No@7;_)f zqG5+b?8vu=BZ6;p)SMBJfvL|zt)rj`)=!5AbliKPTQ&;RqN9XY&cX`jtI96x7w9east_u|22P6UQ^ZH+E388*0zl zLS{`R$H&sxYZh+|U2n)tUz{9AZHs?Da%mbEz1tq9-g3+kh!QB}>?WDBveZhWv01Rw zuOeIHvULc+Wl(t-%Xod=EgIY8mAO;0b>h71XVzc5f zay0(>K<&C0j;Bgt+jjr`m}uQnFY(swN!;YM*kyqzV=Pz8PB2yE{Q4-WWl?nPdY#yf zbrHC*ZLIDiykfpaeDfyI$8A%BF2$Hqb@*W^!-Nd5mmT30t25-7^;kvT;nO19v|4T6 ze|wLe0&%~iDtTdMFLIAdWI6WXwI|idZRs`_@ivK2yvc({u5+#`bmJ7V9@abLk*#-* zI_Q2}zQr@y`)GqT$t5Zn6De98QZc`a`+ zY_8)qhttEsZ6gC9s0&Xnob6y2E2oel99vaGROpKkNuf=90ZxBqo+tNaW2~Px?Zob? z;;n8lPgXc#{I8#Oi+q;!{EQrOew&W_D-OWISKJmA$%>WL@asMSFk~XD4YZZ(E0vaQ z_I+Sz#h5{U%&8e?nb*Cr0m}LAxF(K^csvZ~FGpxL{G#PpYR>JT*@1Gqxg-|6ndB0J z|E=W%PmCiTkro~csF6JWSyfMLaD=2>N~lWKmGQZvhqMRIB@5lRB~WS~=bg|?edm?@ zA%MhDu}8ggE-~H`4^Rp%2+2HxTfpf}f7~DQ#VO=|G?P$Shmdqk()MQj4q!h$b}su{tNB#?0~Xv`-o8 zj5AVqu3A%mObey4!{;?`MZb!*$Y3923NeqYHhQ?tc~=^21;I+EYD*Ukk9ue-Aln1@ zP7UDZ#*}8h?C+=zyKU}kgLbxk9_oEj%>}gK z`I{081^|;30!#073xfdQtm2WmWqR*dmtjgL1tvaJ)sY8mLZ#=0q|64=0M0)I81u&+ zVrF>R)+^)Fd*13=nz4(a2#V3BdU^CTMwJi1DT$ZeZUC^?LB``whfvp-IP7Yt{Wn{; z*Dr&2-VNYHk@lY?KuDroU73W4%c}M5KB|;P=lEW({tl1Mb{+4bH|R0>B1bnU++T{_ zb>1q-0R2?RsH_^)iz?o-@+wDbTtAKyMfGNl-f3UWrAkEB9-j=KOYS_|h^m*v{lS*7 zX2t0Uy*wn&p>Ek!0F%h_N`vWzF21ze!YkE5EFCJx^Oqk57c1auunc)Jt8L=k@}iU)r90)Z#Q)4C$m#o3)WdHatYRSr1uo6Rv)T~}f{6vMbDSs0 zK6xg^IZFr(@2zcqs&TJ8QA;yPz~o#?XawgQe){CFN(-iIkY`&(^~^Hm($NY;S{KXdW3pyiX>Y7V~RF9Ko1C4ZF$ySA=m1S|CjX zG-cOhXMhNeIZdSy$jCSkDOCjkHI42SazwPd>odrQnY_m}9Y~sPS^@K;9P9R+>nkD) zOhdcRXc;D;$MP{jPL2Acp^YGb0)~3s9I=R2%J=6&`jDOl+8m4s21 zpZs#TC@r+xW$;LPZa8&IgartdWNEDs4(ZS)emUIk*&`LY$UAs)yWt6n^qIaJN^;>tLvGk8f}P}-xi1F zz!T|CE>`y`8O{R14yC;yw@K5U^GR*Zd-q#J+mQo!Z<$k&-8?cx4Y6%W>8LgHL21MR z*U3_{N6aMDN$@T2rQ_f`Q3et$+0`)Fw;tv1cCrx9)7}cMxRqc{gTP==*;s6*&s&}S zfm`Cds9y$VabF4SH8~cGD=So6RJRUlxE$onqx*ieV^Vdn$HALgD(o606WddJEu-Re zPp%a{D!6kt2oIPH%PtKG_Je?6!Az4H$*6;8YQu*8hH2ns_*}?e6uS0sADIjN%x2P@ z%MQ5<>6tWV$is!`RV%^h?ZAuo1Wx@?IC^z5ZH|wBe)Jj6N@=%$k{B5e$<9BQu6LjZ$7xX@qo@Pr z*Snn#5+r*nXUw}C;VgR?9$yjLI-=3~0!Kt~ww6-7GnjZ8IiUs?4c`Ye3p%!JtMtxC z|Ds@+W>Edu^3HJ_(o1vpHJ4b`b)SrV0i!GYa8-PR=K8v5*q_s|G1%{g)5`!#|1_sg zTyvkK#KlXMei!c|gi4zkY1UV7_!6f(O+?vFvtu}<#C6~Y2S)1Y>Ss<8WePfqT5KI@yHRKO z>5S~holxWJYyz}aUl?FOnUCq=sMy(^?|W2xYWnh$TqHJrdkhPJ80>bWQ?H|HcnKc) z4?Dg8eK7R@84Hw0eF=b;AyUg){C@8vp$X7A9tS*p5b^XJsoHw>AIWpQ63%T@Hdu=u z?C1SVp8ONL7HEjm3JyI#gqC#{c+83TZ5NJa_X$9#H~y%uxW}I0xgS={NxG&`YyF_B zu)4_mDFj&-ty?L9w`<-g0{1?ek~hS?eM)j)D{NJ5vH5qXfXF_{dL?5h|C#;DHzBLQ zM&~rGDGA0u^UY{O-+7&%jgJdLOB9%)qMFVyD3qjyd(NQ8{4?2mlpjB`0Gf;hv+gB( z0Ag8A*N2obW;v&%cwBqyIuNfEr@W257EnuiL2cMzrK#6TG%?G=n*&x6666&-wOR&) zg~C~O%dppwD!RJX2J}o|(uOi|d>s(zFmgJd&n1d()}q)kqJGNTJa~#2iQba^`Fr+- zy_2~}bR7a8`7`X|z336}ih~@9%+xrq;I~^QL9SydK+-yee^;5Yas6Xc2*NA_>HWuM zVq1Rby?B;K@?icW*NYYZ^s;FKt<{Lb-CFIT&9*^d-*O>(Wv_)Twh>iZ#tFI_gru3#M8QQ8Q4tXp zFdery@~JPzMJB{~rd1X2yh*5hKaVIPdKs+MC(l{Eyh zm7C4qbGeOp=q8chMYV+u;~Fd_K8sMF+57KEsW@ixtiN!Uw>JTj;fsM~+JWGztq7Ib*q%vkOBgzjm zi(4x-bFNP=-lr)RhKK!|P`3FeQN*;MR3zT_-p3;*Ty8OJiIqAjIYd!h6KLT!bD_OU zjdRYd)_Y0L0W{NY8i$dkde_3e==y?%>}bodn`boybFYZ}73Y-U%sIBTeH5lO zJ9zUvybA4`R()550OHdJB|SW(m>{f38dO3T?9`_)G%3^|-cL0W32(E7$Nd16qoi0z z7_XqBnM;c%+Xf=&jcM|L?x8mb@yKL|aHgwI*u0vX{%5ho%FqUzE3 zis-~3bgUD4dN`6g*7T5V-#s9gKqdg91#k+0q~}P%Kp>Fh-?-fW5?4lI3_Z; z#!muiplQs2v^arobHuOkHJTnm)KZ15hKf9hwU7pDs#@{&fCVirMu4g~e_0pGBo+jU zf@(#d8<9eZLh%fR2#-h>AK3^ZC=7UROp6+X8WF^bR7KGmg*1#B&wQX=#Kb@;iC|6n z-mJs6|1Z%>T}kxCW{X|JM@(oG6tx7(UIr)0d|?0i-;HbR6Y#}GoxYoD!(_va$4oEd z+SK9{nAMp%M7)-XzH{)5cl<52s&@plDa#?2XxaQNJdt{n@$$7SRX?JI86G*MdGwzS z414ULOgfdMYE-kq-3EY`GvO?7S5@1zk-_7yev{Waa~-XI$Y+l#qq@um?v%KtPmcx1 zRTaMOkCjMsqE2f8gb_PUP4&IZl9BeGlY9NAcE4#`gAOG&`A<0kcWz)%4yh^Px1_4u zy>+FNC8Z^nH%IViSnL*3Bpjf1SaGF8VlrUdSTiK(#d=ERHsuQX2=4^_=L0!^?a(+y zoYZ-1d0?_}%}s&CbznaYFgGxUqIVi(&5LAP4vUoG@T)73-lq1goa|?+8U`kMrUei^ z7^G7LhcBQu_V6+YpCpjI#pgo4%pJnpeL>m&eC+74LcO+wT1W3(0|vxZ@EWfA_DQJkR@yWr=J&(v>2 zL$t@PPo$(}7o$p5*`swhcl$!4F`^?9J0f0)l=OpCu>eNldUwR5o;-ABm<;sLD%i7< z@@kM5Dd^U%D#4&JiGbuCjF%PuhnCzXi&&??4LN)VeFZp>tlmu^9LW(PH|9Yv2v@B8 zt#K<*E_}8$d>xuf1lB>PFkE5|tN4XzO;aT)D(w8svP|*`=%xa!IZ3p#>BKy0c14m8 zHfobjusB#-N?4cNhxrAJLfuwd+~7XCpY9Zm%?6k6gjuKD75SZXw!m6xAM1H|M%6pY zInWK4Mc@rvJ|aHi0RG?Qk+FKASBl1L*Hd$#My#!wt;4sa#VRV!v)pjyXF3hB@X975 z+`QL7RdF`U?ZuSlA+8h!`7kZPemK~cv#p-Xf{R_CPwWe7=|`^rYe zI(Dzr`ECkMA%-wX6IaH`Dcg{j5Tr{RPVq}1Oaly+EL_JZhbKNQX*7LsU*749UsiV` zXJT3`{3E^z%`E3WNn!u5CKN1h)V9(NtWQ98&6A@Vq$>1Rq*XyW*M|aJNAt2yeNNS< zbeS{`)vrwrHjvg5m?H$-)|U@YbUD=3EXxxi zX(sye{A%GIRV6LOA3yp%_bpDH7A|3|JY0Sc^AT&%@-PJvC0a zwRZFqQ4Ye&&eB)vnXsVJBw*Ickawj)F0!fMtayd;;27L57E>ib*n+9qgydse>O2g}Gz9A!trDQv0%{dGsg`nbCOs$RquccAU@ zdy+G#m)+7uNtWnQ^PX3d&+?iBNK{rc5nj^9A%>nfvKqwLOj8?3!Jp$h+YBQEjQj&njKM#k<<t4>nb6wP&s z>OLJcE32)KE`TLHu4WU5YTm**+~$-4hD+9PL|)6E!+!?Nk%$}?!>a7+=5*B7eBD0k zep=3i_Rl6?!>`p&*nZwuA@Wx53Nex_8sxgnogScwe0(= zSX2p;fz3Ae49sb~v%NKMcD}CPGZq;g>&$1OQ-CwCygY}s8yD;#j6N`kU?Al~i==MV zQbj@=-$hn}&*0Vrz1s%z*^>U^XU5#fQEYF5Aj>P~0VDn&Ki)21Qdb-~fmSAq8BA}*Gu(G4;WWVIAs_K0#4kG91r3SqM+A3T3 zT`BNAKs^P(zW`f+-7cK%jb%#>YUhgYozm2}beqjzLjr-p2geNbC?aT{mnG)rFa*PcRFO zl2ViGDyJl_Q8S7fJ9Bn_IZOF^SAR&vOdQlykGaJ5iNRipWw&se(eX_}Xz8056feLU zIuy^Oo@>eyfTU*NFnTSf_{BuZPvdg@3o^u-PC}T_6OBov6#O3nxTN^~rRUob!G-Ev z?44De!RymlpT>=brHf{Ugby?p>BBF^y<7A+(jQ2fL>%nhTIp0&PZ)4(APKGW5513$ zuSMH}s+GEYK5lhL{@Rw1zK}Ag8UB*4}{$ISBX6ovR)sotRV9sJSI_DD`4x>nZ`{7J&qNVZzY*s2l|CM32c$ZXv6mLSVi zrg;NghMD<@kwW)B*n7{grrIW46n#NKMd?U~P^G>g9YjGwm7a)Fl_o9pUKJ5S@4Xs& zfFLb|&=l!aYJ`LukR~7?y}W1n?Q8e%JJ;Ul_u&`J%z6S`&suAqnS1Wr=PE$&0H6(^ zt27b|Eg()gUyUh-UOpaiI!L{A4?Q(?e!Qo))Unl@?pOnj@jb}l$oz+7>@J%7C=j4h zjOGhf3&Vuax!|pd=jJZS4GtH z_=PVEz#iItd^o}2-voWG&2X$dznJv^S!4gkiEqEmSR25ib269h_Zy$me@fWA@H@*? zk3Zc_WDE?D3ivTp>zqkw$`svPH1qn2e-pqmBKEm^^kJ4KYzaoqY8t4eWqR!|&(X>8 zUt_YBo$ap<_<8E@1QiYBgUyU?V*25sf43@kdWfPqve5(np-*Wp2N)F&B;F-a2UXSf zcS^w;U{J^Jx0-lL3`N~3Ce>%zp3yo)2PE=CAbKV0mNR<8CP#q_fx)YURr^|h<<9Rb zu?dfeKZAz?llQcr-tB8&IpJYkF@wpR^ESWb7j25wJoQj}N*Se@a&77PaZowh#PX_f zp~*t0VV;2jLjLZTMq;kI+kB_Z8N=FPsx^ODL0( z=H^^EosN1^&2>3{C%d9n^lrCKjzQ1i6qzxY-qO4Tu^w}1-x%TgSKCZ;{gP-0} z_N(ojrl~Detn8OQS#k5?PPrS8#l0^cq^Z60*M{7#Tp`w3X*LbN`4MH|!2B?@1K@UO z5Zk)%Z?ye5LT53kIT~yv zhBs)d>z#436>jdf>i2hA#D1hn`bN@A!jj0&`X>J&NrZDv*F*v^@E09vH9kyKeg(aE z#1h2nxHVq6p2i1zuS|cG-;)p-e*dP)s@1JiGrHH?RP%1Xtp#5nUi$N_udw3w*>=cN zTfbPmdVKr6J=fc|6P(W?m?HTO?miu*-uB?h)wkMm=&5QA?xdy(ZU<>RS93Z*q!!us zzI0E|P2e&*TAL3}Gfqs?$2mpIb0Id{Bvti31bA({v^w(Ne^U^Yx!23paZ2XgzqZ1l zxc^gjjo+e*@_V&eLfp#T4nGde)$=*$MxAGBKMkvYe9AsmK}s@-w@QvZNfLf_12=UgO`1AC9f=8e+O@@%HI zm&RY$1q5XW3k9N95h_#cvJivHe}hSRe8N7z9bG ztzv$d%o08Hlej|xki6jejLNIkqdfXwf#WyQ;UX9CHBD&VMed*qc^qm;;eg^YY6aW%DoxXh;?X)1ga?Uo+ zrC5Adh|gg4??*kkbkZ^Vw~l@sB&4=g2I0R1<@NfV@oA^;skTns8^#pLnWhUH=jbZi zVV7nic)ip1#pcBo!w4Q4GkyrH8%q4IHntz#)2zmJkwQQ4+%tHCM=icC8;$gg=0%&8 zrpR+I|CQbXGlv3?>w8~=Udr48NX*C?B$xtzbR9Mm9DDsg_y_#LjPN)1r`QeJGHGO! zsMF7DX_sxf|IFAqrk&>wYkr@_7|yhJw$Yv2d%>K41INoKD96`#bvtV1s5M_#>jgiX z&wTToOOrtVeORA}47oAZ2Ha?fdrmP8{tPy>)r8U>lSVarop~APeXmqGp4l@MTytgJ zV}J3v>cHbpQEyJq(}0$l>e`WK8?3JBPtXyz9#Kqrql3O|S#hRz^4H1gNVI$*YE!qF z0ScG??d?7#Ge6CqE3n&@l=o2m?rjg}i3k1Sfvhrb%uC&TL9@azkKm()8xpxKv9W?{ zVc&OL(UjSZ_Krbu222oMLn~d`oFp<<=L{&lIr2kk_D6fHV?mOWrKPK-XTH|2`};pb z7CxBBX~#Z%xwqTo3?ljm(qlgNFL${RWbikPm?uI`Z}OXdcgS+?dneu$rXa|cOv62) zFcZ2^nR}U^yAmrs+>KdCWThC$@bh<3@0Mvr=&{dNGp*eAl-3_~+j;Unezo5|VB0o^ zU1UIV5ZoUn(ivMFREu81Rutude5(GQl@1qb^L-#XtR$kXtW19~TT^1$%NdyC|6#{# zZnQg;+0SCCD_wZD+vkc_bgxb!-#sYdomx|c4W)TKZ|`29?!y>@by1Zj37U25UF#4Z zyNcIrN~W&O@sDG%<1M@M?Y+gC7|d?GY=Ypj9LKNSWaZ)A*4p&1%jDA5iX%!-`+Fl6 z@9*4vYq7)wPswrYTAls9l8MH6sIJJddlYZ~x3QHM>qh{tEmgZmY_o>;`d^RaUWQS))e>6X#GAXh*;xx4S! zQbM+pB_rUor$Ay%*5V9Tho~-nI-V<*qvv2*jrPS!skRfmQ#K@~*o0*szSA@nyPr*>}WZZ_@F>sSQho)jv6q@7=DY zA-XXnKWaZ`S}Vm0d0InN;=F(pQ$380TIZUt08khNp~k_gdb(-L>}=;N2RGwbO%r|r z?__uLjNCmlzHh@ZH=Eh5#YhILre8P?KCk2*`IR~S#--gvIFaSW*v%F0epu=?{vlK9 zN`s@JOXm*W3!1(2J9}kWK|$RY4a9lD9-@_^UXW*si=tfr{T?yr7gg3L)#rS77*mC_ z>|~;6nFOT2og?UeSaUyFX;Mxkg8-x?nFs}+FtN_>n_9(f)X)GIQ9v`a()ysDkdV{X zDfXh2UyLCx+UDj%Tpcz=OXUy_I*islPNZDB-g-@Le6j+{O9R2DgfRcJqA}cGkcF%LlhvnpZMYBdN~|=-e&jhx%XWahQLD%)HMu_ zo^f0H8up*y6#6{I9Te~r0^yz581u3mHn(2z?2R4FYBlJsuc8@~{)fbC zv2|t$kTWvPd|+gJt!0MKq|T}JMJ#%yLj83%fx?iK*6I1Lc(}0iqZhNE@#!BVDI7+( zjR&vS=Y)nS;oC*6l*H%#VmP+VXOMJz~h(Y z!N*&OUTqb=NU^dz84Bl}ov1aj9pi<5)9^kMg1EY9PsURpEB^A>%kK5$@Qn>3?u~ic zXHeg;tZR((%;#nijuB@S#nZs{h?;*v%~}4&t(W*RUoux7t^W^`BYww9o_1WsCh8xp zUvp(Qzkk9T4xN(s^y#(D@w85|h=k27a5=azR#v4Kp^IBsjEtn7&_E92%~mcvBQU!H zE3w7HFxg46l>Jy*YtfBI$Ja&b#%^K}wuV{$TLq z2Z9?W8lDM>j3KXoRE|o2-&1@Ov5OPRp0ffkf58wtcoi-Ef9$%N-Os$&kv6cio8$J% zO1PON|M}-A!$z-FB}>e{IzQo54VUo!WOi3NfWTe*j%QG2V35(wO*H8}o zJ4x~Br?Z$s9&MA$eMa7q5zmc_cdqp&ZlT?n*B z0~fsE{f7kW7#if7*s;4ev~c_lnEJ&Hgx+PHx;noAhR1^L)L;6PjR3P?$Q6J*&Np;# zGc*{O)GYXg*cZCG%+0vksQ6z$`@w~*r}6pje!}H1iP6K^0=b7*l_@~J2~6qrR(dTk zh%p95_HeMe9-o)=oCdeM$xvB{`L=Xz$SAZe?|Kq{2EYb3yqa~qPcv@Ebz1+}+Qr&! zp|YrHl9AIRiZ?wl^L|1fP{;lUE=^7~wC=-yg0(`tdsf}^B4T7iJTFS#UG`EUz)I9>v>c&+1q|5fgeKoW?>QK0;hF~HxU+xP|FDs3hmXGWM2 zV0edg6hf?H4^emLmg<%o9Dn@if6_o{1OfUcxEhni?Rgea7B!TMbL#CUzb^%G3ifw-> z$|5AvK4wbZ;al>*x0c!xmOEh?97f8)^ro}7w93PHr)VcW@&;KsJHT3%o0UIa^8K1v zg78}8d9Mpu-p^q+b)|CAhdtJaU=9-GY0vWptD2m2eILjBz4v(UaHjhA#F7E;?=1jE zh3jj&pE4UXYs5FhG5#?up;JYxO@6C9dNPGZc;&!q5LSe=ibJY%L8L4rRc6M#&m1+Q z7(D!IZP8;>;%ZaeiAd&}uOFS)v6oUjT`_Ws-|O)9o0&z9NqtaC(w>Zj z+z2%V5$=`6BCRA1C@b^?N}()`>d*3OLNkwGnKh&^<(qMNaX=fM|}-48#3X6 zcu3A8El8bGSQrVp1T`H2@mjf#&g4fwRwV=pJSWOzjVgNMmD<0YkVs4n@~ozs+YBJ! zF|pP2xK+@_Vx$TI16ylL11B&}c%EfM2rJvWF*!z04Q$PTaj5~xCi+syF=xeva-$?z z)dE{%(GckyDK|ezx}1Hzpldc7Mz3mtY{#a#DKt=lu6rfEP1RIz5e2yUE0A|%ri9+j z6~3dQEexRn=*<`e;v-1VyZoopWct{&wwoXlw2r_c*2~K^qVpUT?ltl@ zcqbEXA>mj7R5?}KCn^}mHcq9G)=hpoG}oDAP0>hc!Ezx~o(8&1uOB%jj&J3Qx^^d5 z1P^7QhtT76i%pHnR;CiTx1@+Pi<1Mp9RZ!SQVq(ux52$HAvX5;dv3y_X$E40S z6VqP=!bh>oNz{VW+w90ngfq1{ttG0QJKpp-CEj<=NJ5Inom7e!I!0Z4T~#LpTOm6r zT3%T#y&TaJ_?ExPTx!BYGw`l?OwLvu z3Tz;7Q?N!d*b`|%`;U#%$Y3pb`wB}adXm18I3zDD+Xv=a*QN2+ zjh}Ax9&>{Jx_GCmwQ5$G=J{Xq)W%)O)=hB)~ZJph#%Vpx4 z$=(I2tx~*cd=|!x3>L%wbnFrh2ca=$k*;POx$Zm9(y}zW_iw1ogtopYvA%zp^sPzq z*|h9`+PN~6wS6>?;rCXf2#iO;J#CgM_PeQC{IAQpZ%-3o#z=p zeF9D2Q#6IM6|j#V78XEZ&lDaif19M#YW00*D`RgB`ihDRo=XC^xBmkpix`S)I7x zZth+(uNAGuXBA#?h!D*S$xaNIp**I?F`KWH7bENhv8@LUmS&US>QSo_IjawRB zpP3ugl;pVz0JT=#LV&7OL+Jb|{}R3Nb~>+t%s^jNr#z}`tmOa3s+Iza5{W3n&c{70 zb70}6gmX7iOP)#N`VwD6cGN{yX1f@P3>I!7_*GR^=PW_WR_s>;>?nukXHBB-QGX_{ zX}yD@$l!tJ0s+mXs}cn4UF;v4X`QJa$~ut_Z0)y0UzgQ~fVl+>%x?3oUNlk+n#r)M zPtxg7+)2D`&ji}4xSJ2W_#CRAddyJwemEqfRe1^_o4uh?j!j(e(DI(pab!vFi&qpY z7s#ezE)@MH0R~S-g3pXl*-rX-b@;hti8RDbs4Lb%D#N!_7q)O*-Y#vu<)mTnQ;i~4PHuN!w8kQ;chDL+NE86zhZyi58F_|#JD6j7Z1wD#*0Q9nnhJwMc;zp@#8Ac6C=H% zl4s_^x})iJ*N*V?B$UNGmA??B*fQNlx@r`CGsgV${Edjn|m;F5#Pt;vKCek$+s?xUp6x_}0@;++$2{Y2;kc6x=sf5MBB0^zEx0-kzy z+oD7Li~cr)F|1DKAh?O@J0JROvfu;RnJwh+i6<56Rj#sIDDG{L>{2!;$`P(w4DU#j z`oA>a+{>5?UNbZjh{qD)(KnEAyML{M3_o|!`MJI+GfTr>SkmINu=lkz$MK`mtWlu6 zeB4oZWcdS^xuy%Zjndh2J#^~)NPJQ7N3P9VrcE%QPbKewMrLTsnT43DccVU2iB?za z%+(|9pO)r0{d96ykK&W@(y?TuzULTyE62QHN(ulAR|m(r2<-9n>_k;AFLP}hC>uGU zvrCIB5kPysx|^LRb8bv3$V~MSQa}*qGXa@Q^Rj3hU@KgHl69|Ll5)L8Q0!3( zgrJ2LGf9rI^^T%c)RWc#2E94cE6cuR|E>@~8^1`L=sK{8%ccP~A2yhxM(f`NBE5vY z*XzC~8k&gPf1A{&1c)r{quZ3SVl&_)qyG}l&}6b=T?dh@{0ESQ5z zT{=h*;6XK|I-JkmLL-LiQ!7N365!l9O7t*oooaZ%u8ud}0CoR#B=dK1sz^~=$2${4 z$oFqDM~M^WK295EghrPLf}8Z%B9CFH-MHi=4h#VrcFqNQW6uw~e${lfbY;mnCB(AJ z50z}Qzy`JXA`1 zR(J$&={@1!MBUS3|CT2@rd1n?yNJ^W?mD`hJ8GZamM*|mYg~5z`Ke){1r?!aOtuvhelZvG2u%ysym0r^5*!Y)C-4Sv5+>z3Ao>>Fd!SxkRz) z*wVC7u3jq}cgrS%wQ_-T4&@2sZSMggqgNwQJetkawp~GN349N?nWNBFe`ZjlW6UI4 z4RM*K{4aK=x1gI}eVViZuFwn&^-g+D8#+*}3m-f%CtkKR@=ih_9AAYc#lO|!iH@#- znl_ef#Z<{pEDqG&dZgdvSkg=f36?B}%}V#UH{H=yNv_m$47hGj4lhD-*_XGMw>KvI zY?^(F-;&L}oWCSmaMP@BD1JOq;99w>P>)VfG^Du6PP}Nj|0x1z#=}-?WF7d#>l*bl zNe|;qV&LB%Q#-mk8GgJyM}zoPUU0kk&}m9|ZRt3q%r0Bz!>>`ESF(Yo9EtYxeH62A ztd$!}Ki{yEeEGA}J0)i>RTVk(9<20z8%9RKs$w(-Hb%8Kc8Zi7@iZJHpsi*E%L|j8 z$^pc%NnhXGHH@63upgREb&)PD_omb7aNzB@6{z|UGgEs0&!u9R(E9}cehs;GZe?%^Ex92z#xIEI_q*P?U zpKQD=$KVZ=n93TRu8$L&dZR{sgQB8q%=UviGAysO%chVBRN9LFKO}Ma^84MtJ@Snf zMd??nGC9>7BftfFc9dC`DnObr7vsXx4z|J&ZjipQmDj0@_xYU5s|x0wo;gkUQb5rf zHJCGc@$T0_cfQvsbAw9n>~M2J?>z6y&*m1&<_!;#Benf!cWX++qUt84D>+D6Qk{YOkMhpa_!lmAusf({o(SC#F8`n*B(W=-WU9|?r34c zw0ry`qM|y-=U+kYIcX!X&E=^`+V1M3O3IJT$1$lD&oiGHOOPTDAsP5r<=Pg=Q`K%^IamZsm+fXiVMkoJ-#NpcJN6OkzeV@ z^FX>FlZo^LSd5ydaAfVT`c)UMlvUcvPi*tLNwa5FxAB#H!2@kvC1&CztumOqe8*=T6V; z)3<_b+&e|_B5z%I&8468DNS1?SIEeYeUp`$)5(!!)vwLQ=Bt6a;7nWE&8IFU+ z=W(p{r|M~K$!q>ZNxO%X=x|41I!EgqdbUFc9Es9BSl^^+_9$x_LwP1CjJKcwV7*f8 zN2ts0tstPG+IMQy8^mysY*r#8y`B7`{p_=c!cfn7U-GW+&Z8D9T;Na!*&!oq>Ot3f zjJ=}<-d+~FA30+*3-B1^ujQQHT(YEDW$Hc(lzA2-*VRGy>j;)Y_;#eF%@xuqmVEQVzDtZVqj96>f-Ezc{BWFxrfgM3j4)T=6dnL)omRos7=NyqaH;X zaCZeIAdEb32OSVrPaG7h8yqX#cX^ueB^Ji>L3|r6ugJL>l2kerv=-iBygSp;JM^Kd zEdJuwvRqU7!3#`xXd24w!{`{7P7Jfzi}6<`{%eveInNk@K}s(L;p=x29e$4;F}XMD zOr7<_G1J-qTI#jpk&TsN7Je}--DN+P=?viPe3+>m(wXe3o&b6>2Gq1#LwCrjU~aGR zB8khU)#&x4MbqtH-1Rhf$id;$MMC05Tpx=%z%y0tu=AL{v1* zwTHAPgE^rWo3{il>z^BsD9we?pR%R2W$z!8SY_R?6#jzG*RjK_%F^#2ox>_A`}*2KiRTv#vn;uS2UCR8*r-7Wj5(z*zYgU0e zc#YMfD>Fu{ht5y`z5HT|&MFYG6nS4TkEI8$7R~O}Rt` zk^Nvzx3J9hn}M?{yQK&M4{2WiVZWKm)Qy2LodWkJ_jbJ~JpX9=)+3yye~Nc+TrYWA zuNn8(CZ#}9Oh5M7)HH;o|q>mc}V-Ij@%apRH{9dsESS zzL>tag%C*QNS}{Ujgnf8Mi2qwljV>!`;DA`0^x10lx7LF95oi|3{iB8jF+9jB;0gQ zf6y~6r_O|rd2!grg0WbL7^|hR00*ag)HJiM4`Ed9jizud(Lhu-8-taE{EU|~!excy zW%nMx!yLSKS9qUjV?kWGT{hN z_%fj;LUzjk1+R#2c{mS0iAE6#>b55$82 z-abW}rDq({J*xvB`0#?z_kulcIp#;BARVmJ7(sRyt@gF&7LrE;8Dnv29HaGqf9w$V zX#~4fV=slnnfq*^8eOPcW%p?4=arQ2b-S`GTO!P|TfuETi#y_0yUaUXN!i`gkNT_3 z_#S%Lz2g3Sk}WTapkdf)wEp&}_7V;A=TYpL+1_0|Y!Pd+Ag)YbAa6zyZqxF-OIFQi z)W{-LSP3F)$u%XI=2-JKzglm<2k;U{z#Gb^+z*2!OP>0t7fWv4Yry|hnyEVwBf(4z z%L?9=+_DS5E4@hb@fHGsSZ}=X%>ID8gU0mEK-7Z_YpodG!VtyG-FJYTYu$Q^tHgl~ zLPY}sBx2eB+LMfiucZDVVJ=>%nSP6i*?3Ob&pw?`;?cIg&)U*s#+6f9)1SiilW!@* zJ;=eswuy?TFUN%_oI-^j37(4JD?Q*dpYZOoAdXTm5pzS0*Je8UVoQcblNIkSXExu7 z@+=!l>GnlwEDFdl;rL*~x>;UzZqn{O(+XA1x1Dc7`^EDfXL>wcFaKS^x7pmtpzz4l zp3LZ513`0ZT@`7mhqK7}l7Gi9foRhs+A8+>yC`>PG`^~9UpMNTN!A<|FCo%kf*w?1KU}tKs6ijUmyyl77t_w=F2?dh`p8BNz0cFf=%TvH zV&m^2n#?Eeyeg{SV%HkwV&^zF=dfh=<9plvm#@BM#j&B&#EoCSqy=6tkdI&B%R78G zE%%VhHEU0}z$TyWY8}=8x|!}l!K7$f3vN;CA4 zSq-`0+Lv}2YZt2^mLAy}mKmEWYYbTgb?};h01E}PWG(=lmYd1Ah_)6k9SiWPxO)hl zs}OCP0Pfj*z7x6kk9(E)eu;6og^0)&w)neJH8L-FL`i=yxTg& z1~u_RL#M0d5Ck=*k7I*EU)Vx{kyLwns4+m$Fy}pu?E=V`TUD@gb_*^cf_`%zZ3GmJ zD2`?5ijv5b@$&d(vaU@_E}AQi&?E^a12Bx1bE`n76(-6F(T>0X zKe@nxUEi!`wk`galbp{P!V$ZPgfazB%mON-0`nK{!Ex3xfBe(^Jg)`s1Ag+m` z5yZ&3`z|rW;0oB~LMppq&#hCus{VP+j_@aw-OZRH%V4@kk`qMyDYEy`=j6p!CYKk% zqv`C*pG5Fhpah^Z>}6xM5C}16IiD*&iQd>Axqv4106_u6;Mhd*}N$VSU!52@cdj0h0rc(Q|BU-^A4hKGUPw{2O+v*!RkXe4s8@q6`A z1VZ8?cazAtl$3iKfzt-VVSekw1U9r3SWKZnscDwvPB=dT4j|s!NfXqNfg5~bL zuaA#wIv-EV=U)AFVtlzS+j4b$QgAk5w7`GwsyGe+?gIG4UWdzdb^t-}#kbe;ynnCk zJge-u+3)b`*TutsNCGanFRjadaddXu0v_ zA0lwCKACJ!E6~T!-59m0d%4(yHW5CGv9bGT3iD}k=F5z9Z8BZ@MEUpECzO)k$l-+u z-hg2=-lg8O&_sla%cNSm+yI7dF-Hqg!KU$E3@kCXNXZRM9VKP;iIO4>6IOqQ8xbIo zanYCew`Oj!q49S`uyZak?3C>bHxvxGls`}xCNQwd)_y^AgJZv1QKGMNk_Z6#S(MRr z0RiAN1A>Eq99wj6#7EI*m8ON&eCa53gv3Lbc0upptsuflKCpPr#IyNJu7La|yaYp@th1P#xMM z!S}umea*7t;YqO4uexJgfn0s z)4X~>LQR=g#(R4op2VO$=WqIBs`^RBZsnJcV$o(ButxDq3;*MM z^&C3)PD!xJ6jhorcw(bm!Wq?iK6-l?A-lv36by4R%o%m_1n=Ys)hHcw9@xjrs=*N^ zrK>pbM48rmG1ic0Wh-~mKd^fdl=Y<`D(1k*Wp;_~NE0i%NLrLc=z2L)qk{qQ*My#4 zy-|I2uSofD%-dU^k%GyhAIjhUo|yPK`E$#C(D9+w;`L90(Zw+z9XTIK{yvw|Z=N;F z?^1iW2(!NR@d1S(L*bt_YBi*Z@X7T4&r(4K)L_P?Z_fg@wvH-p5ZsxQXJl{GM1uqn z>+%!{=D{ITocMTdLsNc|sXbLNo%u~=@vWMg*^;{Pl^eVbu7Abw7?7!IQhEKwjy=1? zCMVeXXUzCpI43ocPEp^6Dno$&TxoI9OLN;J3;rAk?2D8t&6E!?`r0Nxnd&4|)jrsD z;24MDD-Sb4P2p5=WhP}^y&Q25qR4m=YUVfTfP$dDu{pJIY32WE)mgp3!Ncr>pE(Jb znyomz@>gkrx>hFkMP7l3&0pJSK@t`XP2(l7j<;@}_A7T@tim_XXEKf{>MP!J_j$g>T;A-{ykb+e&#`>lHv~G|T1A z8M8B|f!ZXXyE4%hOfN`T*X47n$z>B$f&W`yEfor^P?3Qs(RyU<-)rv9;XvJcXN*o8 zqQc7qzNo1FzcXt*j&0xCl~2x6^~SNP0$c8>)W24FUJ%}u_SzDx)Ja3WRY;RQ3`v>t zn%O|5nFP>E(0}lQoRe#C*L>E}V6NatZq!xkso1G}s<~D0nu65(gaUxh@f?~<8(Ss0 z#0eMCB^fKd&>@u?t20tNG}1Fv-Ttkohbj$M1&De{!IH{!K=c@mO0NRo@P(|y-xiX<$pH~lI7lEL4%A>k#`ow&0W=6NkY07bWbM;vm!ht(Hk*Q?hq_qAW^~0mGCQEgBwfH=XVNdz zIS&k;ufRdf4WN(cjr5>fhHqTMi5r|mNj=a_pFAUTp|a5eaa_K=2Hxfw{t2nU zq$+w-HLBUy0SCw=tc_-FjY{&s>iA%V*9A5~rrsb`LQBIIPV3;jWPJI2pNYo3e32N( z4Z9V;blqTbnAYC~KP5Ge#PPksBuz78;hg4OuoWlNyC#Sc<=|Kdw$dyse_8#7<0j`j zU+Sh7b1zCPBGcu!CF*~^WCv&dmrHpmOB>@Ba(gbOsE8W2a#AR1zG9~$j#E3@j3x%+ zRLvhb#oDdOTz4I&Z5zQCkEbAA_@>jmRaAI6qU8A+dlWoP-^u)lnqPyBJ7`YH+;q~O zq99KV;n|qR^tw2?@m-855Vo;859CW1w;cjLa?vDo<;mmj$C+g{nzef^>>L$H(=8aY zu~pHOjz5*+hz0a5)!+U`WU*1=CZSy_Dl&9X`7;DS*roAbtTUv7%P#-bnhgd0H6Cr_ zC1XQX8P!ZqFo0}rMq?cyw~Y?8h*V|)2G_AUi3D%35%^p~8v(TKEK_OC81fTI!sf&9 z@#Lk|@mNkIKeYVVc$E}KR#r^H*;I%ohCQgXM!^N6rW_wlohnOxao8Xs7g-mGH!1Ejt5;paY@h3ap+x;Dwa2pjAv*_x%MYcB*-k&^-R3J9vn)t4ksgrJD>{~Ln z101H2OApT`nMsOwU zUttTPBzY6QOXsSd==hPHf-DRm%_nHOHy0=MWDYdTd~+KyU1d;U>&v9db3T>84B zY6LuwPBSFCS~5aJI$m^*`jh(YGNaiXT$yeOv^251bgYxGO!6^9x2#b{Ooz4t>QF51 z(BRf2`&PhqqGDTTa6)wx`aP48Ed9gs{H8Sd#_y9{Wu2`tYWeg=8U#cu2Evjy)we@u z$70}4E#);~5uROUAMjDk61q_{1`$dd`!Xa-xiJQr zFoWTn#yV0u6jHk1&luM%vM=eU#blZg@<1|*IC@_>a<}3mLQsfniZbA=Minxlbt*N( z;iJMw@aJ&*4%X*pq}0iv2ScC~z6^OnvAsN(Gvqn$E5Q@5>7T@!N%5IM!3GdOCUG1y z}>x z9jz4}nlYx7fGQK&TBokay5z?0KTvqg20b zR^(xl(NW(%XsQw}+M|94dkaiF{L$yW#t|Y3aZ9TGi?8p?ZDnO@h$@)F(9*KV5}|{B zGn`07JqG>pfBNI6FrZR}(vB&OZ=Fh2NY4~VKaIy+z{dhKF=w(b-K+5VG-2er$IM03!~RjoFHh-=T=uf~C?TV4Wp<@XT27KszqsABs(C&U5j zQL?R>ct56x_3M6J&JX&K#uwc6N{^aP88zM5?6{TPa|BuKBZ$RO1ot0Z-cy=1&8xro z3F6w9*hx_Z_cZ$~W~$rEgOOZ48q9Qw=hbhiX)Y0xdeu(qm1T8ruvNzk&GU*bId18@ zu0P)Bu8EQq033s`PdM*mfA5XEN3+*Rr;P1y@gtsB;O;r;xoPUQxi$X^uSmZ4Cd3S7 zytI*Q_MK!fxK}SJ&wn@$9_?7!U_d)2bnRi#z5P9+kMosi64&_5T;f%5uY~0zgvgBp z;o)9A`&*!Z^#_N%FP%}GE1wv726_pSI!NLNzdFT$AWp#+mxv`0U(_k>K2)T}#?^C; zz>u>S3m-HuZyhGCZ#6(NmX(aDb)yca3L5Q62pxU z!QPy>F!tw4iwz6()J#r|jMBs;oPC8@m%m@MmmaG4#d6h|HeyivI{!VNG1It0YM}l1s7tl72@4{9`q)=@hh~kpYjzl?~g3Qu7I)D zO}9((9m(Zyw<|{GmB&=4}^)Ai9?%x%9(EDFibY>$WcXGNTMX+M;yH^Jrs!D*+GKyY3^pTzl( zQy2rz`@2#?-{PK-&7w;Wrpy_HL(vBeK?BI*^>51 z|2;`+?iRp^$Ox7K>sh2di~Su*QS!2WGPPHq+WYglMYQ?K6g_Q?R;gOR)9~@CnN2P0 za&qiqa1B^=-!VE0S7Pu{BXzH?(!IID_okGPZH`T}ZIpO@0u0*QQI4c#7LN&L<)?P-nQ5$Q)FYjPc0Pr_9j@Dfw?I3u(&jET6?&)D|6eUAB|%VmTcEHVeo1K{9Wx zed0b(=FZ_kY+g?$%#qnsH%?qhdbU~KRmioVRpr;;m9{{oP_@a;T z@g=l#+V#%`d(0F*lkmx;KvjV12T*_8EPt-flh?kYD|;#n3a*oI*J1pml|z@N$>=-v zdrFCABHhf(ea7+DfxU*^esuiG6a~E(WW3_re7+&^V~dEg1u4%%e?SY(srmoaE`7Z7 zL7o%)dmm;Aqh$3^2?JK5r0^-<*s6YJUXV)Y1oE+KwT-htKDJqbD@5`&iu;5Zd6Jt1 zJh=&LREG7EdP6qL!^*R_j2Pdn%KZHSNYi}q5C(#qI>6loq-m%|sgNYO%6GT#4Zzwb zw8AE8NF2+tsJ9yO)#~oJt5w?(;@qmcfu8>{y~0SDA518IMTrvU zgS&MPDkdA}O5tg2y*46g843wP1Is&))(DVY`8;j&S^Fp>-L?nrJ#0IDFK=z`cm_uA zmkqT(sMu;Vas-7qM%ua`q%O-7yB>==!k3u%+Ip}E8l)3qQb8yow~QLc&UNYuQ77-0 z+K~c^C`RTCA7{*hR%PQcd-n#j5wdEUHSVbLaAfv+<4sl{gAs2I59KgbDOE25*WCPT zY6D8BjD02Kl*X<&@|$I9Sb}^Qe5)J|w*hKhCLj=0Nj0m2>o?;nXVFL@LVgnjVgi9c z3~+dwUJ{?9Mlji_hQL8N0L+5JBQ)Uf4+s#iVaZ_goeGdd8E0{1qP|5i85t{&DxJz0 zH7#(eh~$YJIHKH}yccSp%VzvLz~y@d@+zRxf;E{#=(|j>{-aBTo44iIMvGNx<>_X% zpNB?J&8r2rC&x!oU#3FU|LoD4HRSf?%*TC8!Ii?PB4dRc>zf@#V|wTcfGpzl(lai5~s#coEM2tvXsXm8oL z%d8{{!NYloNWnbsDY^y-(i{c-yhE)#^N_O6o2t9FfDiEPy1SThfD9=ea&moJ8wM%XWx zxsMux=SriDMp`(XhcYqy3e8fI57i}iWb-ru(LRU&WQVHfr^^2Hy*6|GEOB!&2YwWN z5H*?PyIxV^R@cVcf469)eX&R$A@4#1+PzyIfy~}86Ry$pcv^l?gAo`hkIxB*w|qr% zAxp8ww}r;d5;qmMc5XdHa+fZFM1O6<9V<|2w^>81>k2gQX?oEpArfRaq8Z(2Ay1*I zB7$iL4_mN7U2O{44s(GzG64?Q3d@HIEoDR66V0W0xP}Se(j4Uf9#kGGUDnspH&w%QL=1B|!}(Q~x{cDt6nxrB^;l&!{lt_f&W{ZBB7qa`gV6Ax=)+M-)5ZEm{ zG=xj_Y?X=og%A8jBuEg>1?pa(3^6fMh;+W~8a#R`Kj#?xdn4hmXHi(5tduNNLbLmYXU3r=6Y6%iy!AxEF{=;=f`jD`WyEG0%_KGI+;ewfxj(Zi(tp zh}OrImr7ERvjy#|&6Ej@wLQ|zDgJ$^Z^G&2JDOfEV)4f;x$rS&xqF#!xtJehBlwVw z{PIiJarb|itvzj0g*`D#lh+pKz9y?d8P&mww}%WHP}2t>H!K`_ub!VY56bZb$wXhI zEQ)FmuJ&X|h(74O=sp`B^}eq6`{@20$UJ=M(kwKXW+W}jN1RWx)`<1B#-U^muZZ6LCGzv_ zsjlr$9a3+tNF6+L*@M?h-EDF28-X3Wn>>0`yp*85eIcoEG zLZ)W=Xi3*)I z(b*j1%dI+(rZ#Rbxt6+rAvg5nr$5h1yu#dckW))rKJ;wH+mdj@(B_kpbz@4%HPP1Z zvq+!MeifH6>X|T;h*YG`3_d=ip&5m&d!2IM2}!DnVN;@%~eN%9oQ- z#uxpMH`i>Zj7ogJLA{gQt8Mt`{L@C;fVV>rT%uZ7wtLf|n(vNw`~N~4UG4ooA9MTC zX+Mo>`I>jX!r{iD?;>J5dq=gt+&m@iANV9*QLy1h08OUuln4|;U6frI&A9CUOFYN^ z?dbA4J!*k*rWSO*pQV{DmCs|}*XM(?4V!M=S2MuNi{gXB9m!mtQ+w{x?j<~?B;s)( zAqpU+O4eea5-W8O6hxUCqB6ec>f;6$cs`ATM71kao2-hD)5={+#yM?ai}eqW!M*d1 z?#`3>2xK{323r3+W%wsl+* zVIffD`-(7|mluMhd`}sF+P{KyknlcxP3nIf{EZI(}G#Jo&(fLIV{i zupwG~^Ou&NZ_&5zxIcFdJ@V0bn~1#C?KwTj*3$$SYOM95o&=-ccc?Kq;{p38d?5u3 zx{J>zydH0=8C(ICKDK?`c3EZgp~^e|W>?8KG3lQL)^7&R%w1aB=&A;Pue+()G&$M@ z8l!CZr{34lbqnG7_On)gD=wj?c+Pw)xnZx5Q^Ml%X%+d@+z@0)z)@Zc`?0jgU_!CV z(y-lg_~kbwp!JTVNHs%_rTUU-AO$p~l9GTc(xg>gyP-$#YK&XTF_sTlIfNcP+Bb7) zTp*wj7v9TpRv*XB_$BRUDv!PnE}oFMJ|i)r&(UXW#k+z;pl(txcdmc*ifjlGO!kky zkpsBC6` z4jiTJQ5;ecC@*SP6Dka}V3IELRe!CQKGVu7f<~1h&V>1Z9utUUx|IYi z=+4&ZOOm|~pyv0QKW_PesH!9iSuqKvZyfdHguoY7VRs+N@TR(SH!%bgDFUrN7r1Qs zLt$?Qe(c19eUT|f&;HCzG+juKF&J8#?`n7QW~B0MQ^6(IJ@Ff|3l+eo0q4|Mew-gx zVs}nqWs01fp6E9o2CO5LX-amJPwyz{ChLDo?TaPrnyXb~Cdt6|1L&>mp2!l#n;%W% zs^LaT>+KB-D}*91AYfx4#8u2{O=iMO#X9F9b@1KS;$!iYL#0zCA+k}5 z@~fCb9pUHmxFU|xcf0KS9Y5rLIeQYyEIs0n38l`&84$2@)}$&M7muvZFD2d6uCg!) zH%z-M+yGn*CenuL%YNC}3Wv<^mu(b>b{&-;76k;S$bMB;BiHRhr$AdPPXp@~Drk$Z zr3uPO#Th9i$6B|?8K32jX6+5{5EBXWRsO<2ClT?8I>z6IOT})l7iCr$hH2(uQQGgz zh)+9m<+*?@M_2vcd=pj^mPME+W~*Qf6YX=7pAPL!o9*C<+Jgp8GR#01A`xhGH~PfB zfUdi^w)d)1IFa?SEkI7Hl3ZQ&zo%aG08=ut)-4UKV}JtH;(t4ZT(-CI6|cG+YI6e? zo$aD`0T*ez`;$;Xrja*ybb5!D9xC)ZyWJi#(N%wNz2w_j%CHjBuA(4&{Xb^9|29)W zKe`3BCMQw;yP4jO)pE~qSjqL;RbvqE*NcMr3C|6m*oq+$3zxXy?2<@YK&LGo9B z!5YVW99%-C4k0Cx1N^*5fQEjpCMj`-yv`}74!`?KI9B#|-|f-g9O>-D3`d4Jjr)H6 zF(~NB3>%&QMZW$t%HMOEy3j%=add9|ntMp{qc5#)59_0Q+`MI-JuV-Ja&yACd(6H% zR!;fNRRg>REl+xQHQ>NDcnLrEN$N2DK6D`4$-Q3dMzBdABBU!JQkkZ2Zbq3J#3~_} zRW_qf(}IU(G1JF-C@I2ei&SkCKT>DW5$M!Ri70v7eezeBqy?;9HcXE&=Su?G=;nib zHsS?>_E7k6b>IY$Zvs96rv=$uyq{}x-@aMZ^@VH@1XhYLF+)Ix9IUYa-OPeaV`Z(# zb*@~@v#3wpy8GaJ-4w;fdG^vkQR+@%VV?zpaOJWAZoK?&dye?hFC&<~Q>T znnt_w(~##UgPxivyh4uk5-Y$3iIv29y|CyDjeK~_hwhi{7-@w=&VFEg5jg@(!4K`4 zfG+8vb!DRnm`2>tmGM9%OV%lvTbYi?g+-}n@p>5gPh+}pFD2K7pQIDh2c3K~NXqeR zQ9A2;s`DE#`ZFCRZ(MjNVL!n$YA`8ti1^rsgH#BM@LR1ZIpcGmUWUdla`6FCJc}sDObw1^Xr@ z(!f55ihtqa+5f`D9oW_VYTr60vo1WBF*U_}5tr>Di~R9@+lh&^GgdN~PsdnMT>ZQ# zz>yg)Pv~?xgmr#f%Lz@z6Lh&f zb?@g!sS1=N@*EgfW!pMK^19loCpu)cv@LRD0) zZPwOn##_T;OtecSj85vHy;sCEVvo+g%pBS@TmI4{g^%WD@VXC$vt>!u>> z%q;H_j8&=GTvdZ6SwmNP;Ak-8>TJkh|xBbu@dvgP<8|475)Wv zHI@f7u8bC{e&ILFk2LbNV}Y*rUw4Zz;TA@V0z`kSH(KM!xDTc5=gLPvK)XtXge5+m z35t&~_nWh>$oI|n&J7BlIdUxh1nZ2^^h`<`IJDmht^|jCs8qnP`y)=oA!O%A!}mGB z`58?E!nND4wHIgs|ACL|$ zFhPi!3M=jz)Q0KIdGu^9*6d?72BjZxAoCa`yqW{YCU`0)Hxaz?YTohNg%t8Il3eBd zUpAklK-A2$UtP+jnRhMEbMX*>1VX@Yhtja*0@;;$C12>W}_5K0Irj7E*4 zEv_Lo7Hbb0V|qx6Q(%=BBVZ9Sh&bV9iVE2Tbf~r@v@;WJZS^jsVSR`_{77M^8`b=p zK%yA#zjc?l?$zz$fS}OF3-~#+RS_h#mcw<7ai~4Mj^UF+qQn_t70F3A$GMD%GVuaF zM24&riZ5c$3K{y8({R`y(=r`jGdMEki)Wu2#wu?5<=>)&i2T<=iT_-B_fL}M|Nl0o z>dyom$a|m>8Iy}ieW}5bVj!M919BvUs=?ud~KNOuZP$Zm6`DsvOn2K)W`_mLcP^q#! z8<7xq_r3nSnjE2seF*sT9Fj3Uxr9bxZHC3F9 z3?8uZz_2qcOd^R84I#Te5fj5md&%DE?yQlQt@4H3C#RDohM05WA4+VRboi%y1~3jR zGt)!l3VH$-u5>Kln3k;hc}V46xk;y4z#%?eGJzvM2+4}TZZ2rkGaU-{=ktmms?(Mm zBPUTGLPg;7j71V|J}E1H}n0|CY;B4okc^ z!$94ImJ{i4XIPA8_RIE>{Ski8`07@fzTo-lFYl@Pu3Yb6q1+M$cs9@uw@q{AwQpcO zB+|Lw*;jj$=eG=yhjr#kjT!1kp+~i4Cpu9&o7fTj@V`CCyd0nYw8_@uQW4+xBDE5- zwUKxTqXEB(uxbp($&Hu`4LC>!Q%fkHOjkz$1_MZ5m}1WTGrpJxC^R4C*WvW6=T^4JHFEW?04osgY7TTveHR z-SX+^rp7`--mnv!4W#ro$+E4pwfVZkS%KFg*UTK5)4~i`$=Z-%RR2wbfJ)WL*Bc8D z%BnjQhhEaeybkNmByT^~ zd?m+hwxYa8FzvCidW;bX6`VLZ7Pl$bDjYbl>9MW*cJkAb9&eBu zR%8&%qR(l)TSRs#oo2jv_3+ua?2EDi8z=+4T-0{HD%APLYfm$HfiWxfK&CZ{D_a0P zF`3}9=|^lUAc8%KU^Eb934WCP=r$r=nKsW{-1Pa!udUvAK+z>%XEP?#QIa3WUldlC zl0l7Ct!(tI05%5iQK1Wkwf}XdejmaLQ9qE2qLnWV#kYH!ddspEN-1)QV73WT1gU{l zVxj@K+LrDnGX5$s6h5tz#x2%RM7~EZV3*R^!$4)r{*S?zUr(v4PQEl977V3P@IH0e z3f--Yw|d-{&DRe|R7BPfV}XZOX3{vGgP|Vi)qCbpZ#F@xB;o^P!S0OP>UpWU@WFxs z{srLSkbH=Vd&-c$l}Hx~@aA26)n|{bKDez-D^Tej&)X* zd&qh^edvk{U%W${QtK^V0cKE-UAzu_F>qzhqMnBzZkr zRfn~I`(&T)|5>1Jc1(4BM)=~40ex5)E{e2Qo=y#NSNg&+eNCM?-We{jZ$>Q}tSFV6 zbVIwpCKtpax;-kR3!Era<-!9}N(b>A#5|Fl?{s9ArEDMFclM`Zme%M-An&ZeHw*XrtNs0`Cs*>9L&-`ex2lfW{#wxaod zBwJr&25ShT9i9Jv!ruyHQEtF3oaH|>4l65rxpFh@scVPGRQuHd#9+OlX($IfQPvMhs>XjAEO zVUdSkV_&8#E%<#SCXrVwi$WLp193rDOxDYil*jH@z%m1$+w>Gmtf*3ms@pf`8`(%wc@M-nKQ?W;c6jJwdg~a^s*VwBD03c&iS;Xt zQ1vIqiZ5zMh1?&M(<3sxX$b%`N4oFN8;b!auF7)u__lQZ3=5wFdfJ+3Cpg3D6a!Yal~_QV>}AOvIWoN<1LAzan89981q^bv7{>Hf zB#$Ge&gxu-UC1`{j;0BvvPK!~D5Nkw@hPuzrCNnZd4M3(RCp`WAgY>7(8D<0{XFcY z!-HTKZ_b&X54>q#zlOL$SqN=JL)v{u!J+WZLF_5Pk7APc_0?r24{!f!;_B*K-;mej ztncV1=8m!t)8^NPj)bM=r5(J}78oqTSq@})lcEX+7Ab|Oe|bO)?Kjttl~}#r&_)~u zfERAT?v|}b%2NPP6YlFOs6Qj;GvS>8dp_rJV6Iec>*_WTPaXe05mV;feds?;AeGCW z{YW{@yLs`^U6yA2H%g*uVZ-s>Z08%;o0Adx`uXbzUyNzR?d}`2bXx!P%ZV}np6L6J zPr`pD4l35)I#E$VX?UMQk9;6chXMRzM4F$&cz8}0oaq{1gKBvtG(p7AH#vE@JeYY? zM@XTud|lX_BM;cxOjs{|b4c>K#Z~C>C?aBQbRtLwuw{>vDEKn#xKFpfB82%ol`AS- zO7ObG7PvNK9GtI1a(JqFXCYSpAY@ov0C8*8H)0{70!Kv}_&FBqyZsv8YkCAn21`_Y zof}&F6Ptp_*bk+7O?y7xuJlws=>(TIf=@^}i-$lE!0B+r7K32}qou+q;zj*L{iz3> z1xj8n3|I`!BSto!N3B1(G_5)lD?=yK&;WOur(c=VwaK21F|TV0B`JJp4tc%_%Y@-5 z*%r8rqfbs)T)NBmqi8JS9JvG-w;S^-GtUoI4HnP3dK4n8(L0?w2E#HuHxWKe&xi7t z&4oKmM8+wqJEcsRuGYUW?R>i#`pZUEL7?I;Zwt!71E<4)@T^vJVH_G8_38j^&HNVN zOAI;h7wA#DhPXzpaAg5&9w$Y+$+bZp(DC}l>d{T|sd0n`yPpjrWvB#3%;D1ofu+;Z z4)Wxe@w|GS;H3kZakw##CXVzts)YvFS6Wu=ji0deT8)-Ue9n6K&0%==f} z`Zta#;Z}^{o?ZSxFWE;iw_SFfD<{w*UT|5Uf#2ZknP=T{8^^<$HZaTVh!6Y2S^aIw zHHW=Ek9$acE~M2g?!OsTKU&pxpSl~?%_6`;Dh6AFKP6h{tJIAU0z+N}wIGqc11l7d z&wQ6VAgGm zUU!q^?k2HjWzr~?Hl!Qoe>bf|NMT@3mZWw9#~Js zl4fN!?D5y}R-4+*W6QTK+wP1uq9+Sm3TT||?0l&Wt&FAJhxADit&h3^tj6-?n-qGR zl9zc@-)H*yV$Mcf(nfz?D0_Zubdj>$<1BEiIcj1Bz$hm;KZSR9Sfht0$~TK;L6*XSQ0$o2=gG3}ugIQqDb)Gyim{Ct42=T;~?xp=4QK9M#*SKq7g zYPRIOLTznr+Y|>qQB!xm{u!2uGLmR|Nx!pn)^SU=I+t@tc4BK?J0*%T67XlLW}f3U ztHJ0vemLAF=M)YTa4uOb;mCRM-n2IYiM54a-eswW^dtq0Y3HGOmTn9UvAX)YeP)jd zU<8t>2QD;R`>L0jD|qyd@4Kc0?W>V!Kl#Ux%a3=5Q!|l&y#j@Jwm%(`c@$P;7uw0) zq^H@}Ph;HYhrH-STpVpK{Tkk^*WQFi`6yrc{7$>`p>Wj8RQ1Mmci5#QHEO0*uwqF) zgm-p*Vvqmp)5ZLU39W%ogSGSa>jdSA=gho2X_@mC5ziU#kxoLF*ws}T)V$>HFHKah zC4;e5=gz-M=Ky@k2L!kGoeTTT)o$eisBy=Ky=&Xp1hD4DctEW?|DweCwynOHjZxtK z3qJbIHSXnV|Bca8xB<{XzxCtY9Cod`E&fJo`P5JQnL@3Vs4u4}ChzpuSrNUxPv zcGu{Z*+%8WC}yf_z{N|3?fT_t?HexkMUD-Rz8}v#y=(RTTKrk{b4^6ECtf4|G6iO# zmoE0%PfALb+VU#hiN_xlaD%nC-#K`a;j^lA)1zyA8T5uK`smgpil=+9ZPL*s-S0-% zOdGeyyN+e;|IO9w3WD4_9`w9W0LG;<>>QAE{nnQ&)V1|#D}zr4>QJ>|iINgZdUN7e zw4q$LZ*sYbm^GdL&-PW7$&KS5ZV|_xCocs?SNOVYn;Q7kMbp-8{+ThQ)2BJR=c}~p z^t%Ac>}QO<$0G}v7_WW3qhFdgxlj#gY1-H=V{E@JWy%d?8#@6TujL&ZA}!Px7JP`` z=?l=>5n9l=Wese9f zCB)F&^)B^ogztj3({~&(ZEHWSS03LG*#(bQulfn>(yBr}yM5V7L4RDEDBrwxtiEc; z<2TnY%V)>gm|mbowq)&o;my>UmWRK&;O8Fhpj$50uTSr4>o2cqJ&v(HS{XW3xb$$( z=5g$AF6->TKG&#=oya@Ge%lkXg^8_t*Vo6-*M`Xi8xOx=Q5!PIyK<_T^hGdrTt52#qu_Vyo{wdBzj*uZ@GxVtwtY@7 zEx*YN^o>*%p4f9`mgN!1L?|;6tIVF-$&l$|nsjK*%Hf#Q=`f#$SE8Luhfsr!QMbb5Yv=KSR7gtU0BX=>V(MAbP1)2ilDDe+zbpcTXC=9eNC{> zx|{UU5lN+~J0*U(kuyug;T)GM!O)`wqHBj%4cFO6j5(u9AiBN_msEP;lMFEhA%mdCRT1mzg&>MCoEa z?wrKJ`e9LYTPFcM}&$&Pvpo1f@T7K4JA3KLn5U01td}QHSQe{QOf|> zkU?{}YUH0o@`Dkfc*z2+lz%55vfTs;g=h%t3?)HVVZH)qW{d@?qauy6diuU#T%&JB z258$Fe_%&^-;=>Y-lzV`JH2!TI7CF=R;7qELihE*V9~8Qf zSZJ-~^4MqgBR8hRjAs?G>jI7-ln>RPWc0W4%$PseH%Hp8L##pVNxnW0M>7VRUnV6N z7OSibIt^JFXStK$U?oV!&_91<7teE)+V4F4td;nyT;h8GS>x;J=E-kO&*We<*3#fa z>W$ujT&vkzoD2msAD4$mdW4e2vbAAI-w${CrnkEuQw3CBeA5@^gloM0`pD|xVcVaf zuib8p#@sW$EY`GqN~#`xW^YBJWhsdeQW?4OFm)x`?o;3T@rSQ&M6E})zXWOfh$>w0 z9=mrNciQ@|Cn?%5R8J0qK^b7OcfPOr=T{jZeTEse`yO1}A-V^rQ9)VW7L%S`E?V|x4qr<(VuJsLWZ$NTB+saGrd{ym<4r?jYVMXx`f zn9(_{MwfQAb(7ZzEnbIFfh_9*r%wtN6pxfk~f zPpLJW1@#WrG2|R&o2*lBYd{U$h2T~fa@y3|J`{Z8Yc}5yqyL~trJnWs6r(de@hj!^ z>ZO2FH|u`vwOZ=b-bAD8_hCY<||RD9~*k38_4mg z!7@V!n1J|9&fe0DUcYKg3wM8XHlw)wm)7@?s^XpJ&4s(0%Yr}OouiFs%oNN3I;Ho~ zc0q5fU7t{nODj5aY8$BD87p}T-zZ-Re4K&`kZOWjTge--t~0bubG34-yx(MHIzC~cM* zzKZ8BkqPBrp=AHOCWQ=8lC)}Na#&<5-q&zFlu^AjEC^KV^^|;Xdlh}HC!qS#K{~jh zP<$%b@j~3a-ZKqeE{S)<a7JZI#PiJ;Jz*&cRB@N`7{8l*Ap* zCY5z+{I#c-84err*%K2uWSiCKe;(H6%s~EhKL38mjm`)j8yl(d*xbEg?|z~yYrBq z%)Lfn2hRqG?+AxFFHY8GXAMi*y+2mCdfkt`Ufoy| z-4X?s8%G8#p1lmj8@BxXZ!UB5*2&JzwbhDOVaU4d{!1`O-BJl2wEOhZ&UX{+mdhqW z)j8&A)RAA&lLRQ8-nK-f1+WFHzg9Q^9}oS_Q!6_ykfgA%m{Ay(HFn(NokKBd7qfcp z%T@$Vg2VaE^&CInSZCZ;P~;l;@wS!aNA=O6gBu%Lg;#YLf!B>NOv zn$T$^$}j_^tBD`tmwbM8IryB%1teN9P#ghm&%(y=)9&40W}uWP-i77AEFQZBNZ>~FY|U)0saiwhrh`dA?qf)r*fAu=V~!)IN7T|M^4 zJ86|fz&n8?5q{`@I6kbaYaQ5qH9mnS^&G?6a)mPaDFF@OZ1YvNF#2}hLRa60wy?&; zM4=DxOuSpp8~x9Q?cAzAhV@+fs6IKs1w7f9fIm-m=e!YAJ+Z7sML~^B$uBdCnd@b; zMhY*sW{Xk4Ijc_}5y`aBthL`73CIa0~4?}Ja{$@61Q%-u&-Q7yPNzj=5s zhvXxJKZ#HG8Fkiy?3_KdHO=F<9Hvr^p(H;iU#F)4;FPX8yvrUI=PzQMdppCO|h`jEsw*RGtM4FUJm_lL% zTlW<@anIuTF47uEJzP!OCjP>#JZ9wj zc{R#=d1f1t2Gl}^I$LMlQe#tRViYI<+%{Xs^a1;o_fhckPE3Ksc5`uQ3&U=|p`p+v z^WR*rDYRwMVtnUSg#*b7`JZ(bd<{btVrHCCVMA-})6df5&C}nmNU!P0(uLc;S5oK; zWg+xzs%P3W&FvRda^m!Z{)G2CTrP{_+XY!kn9IV7Ru|JE`KFi5n4zz?3jG3MQAQH! zXmyYx4*Xv5>QPie1ZU*qEq1_sbvfa^M(1@%x{`~@l0s6AAc`f!0f0@N)m0Z$dKUHc ztSH}ca7uN+QRGL~O*(N+@L^avVczjC55r~ccfD*5Ri55L2MR7xhH8|;g0f4kVUs?E z*{q2mv#`j}i9X;yIHArPS=ZcIZf2ZUZ=?Y!(RDT*NQnaRBRV1@DP#Lhj>2}%+aE=f zzqx>T89Yy!e6d*m)%vS02d*f?*Dig4hvO_3GOp^LCkfM`+(Lg5F?se#zNkp^3&sM~ z9zS1$Ww`tc<1qDKFLE#$C#iSk=)=R}sHyn5yDmOe=E0wfxk)WqNbEo)0R0-^{pf)n zH9&!zR9{Bie&RYD$uMCrBOnVt6n0B=*YN7lO-*Yd>AX>>GmN(pzr#TfegM|HJWoj^QS!6jmmU7i z^{hME2~}!V9RtH6f%{9zRt?*EV77v1gJdH&{Rm{gaxW~2_jCa(MQ_Dm>GYv!KUgTx z?RHc8=B?;)v(8{MDnvu#$B)x8*S<7_i8}#4iRYID@RHU- zlnu0b`^|%qUjg}@h>6JwVk~q$(yY3i=@=BO^)%~EU?zLRGBf5)Agf3?s^G=qdURcB z<-0yhOlrk#fQcpS)#>amzR$k~>K_U$(l%^5e@U89CTD_pVkB@+ax##C9iG+$u zvfr=DY#RI67oZD422*D$cPkKhWrEVk3kj{Q*|x5`lmNc52kgDLVIVd_lwkSdPIF|> zk88KQ&4={7745vO@$+N?&wTYTqO)ybb|AR|Jz)8CAX|rlgzRH@kShSyG0y90P(yj0 zWdTA-93_+m2ZTC}6AP(syAamluCUu`e&eG=py(s?oy)&JNSX*d9;(lX(fG)@cdUgo zIUxYJ`B_T+_sZN*fgi&8NC!oOOmq+hR6(g_J$sMz!eqd zFKZ0E-OjHms1dC<=Ao5}W-K59UDQD1j2J|sI8^6M?o|AZ*&Z%xJE_OAXpBM9qgq!+@{}u>n?5i*8<%*4hs*Sx$S8 z5zrh}z(XVa{}Asi#eM3FI1QB)CWrwQGbCT0Kj)}-a-^sqQ}j`NFVdP!j>Quv*kJ|| z!%Ta7YkW55(suM0EF1E?y_IgKm&yq5rG)0Ozgr*TWiNvm-rSDNsW=HxAFBM z495HN8xy^Xe7A(}>11hu8z`zpVN#q`jY_(`J){f(iL?I$B-RL1i%FK%X4wFEvig7E z$u1m6fJPONX~rBA3rr1P2P27}!?OKE=*i^BKaUtNxh(K=41=tDpKbgf|~kKQLT#DApxJw!@Qb zwYvJAc-{Vnc4(>o1H#IIy9W;7Ifr)OR)9OgB+ex!t}|}9Nyq?! zRH|JbryD&UWTj0@msEhcRKb4Kur;V61Y+-AuLqt#cJ!i`fu?Hf-KqvY@HFYcD$~&f zBDRL|%R2j4KaX-FD3)+U8YHwx8J;Umj3)qONEEnotu`NiJn=w+r+0!G**9s>N?a1U z8J+k=#P7@nTvc~b#RKJpI0Iruiw>rp;O3DP{p(MYdp5wC|}8ij>At;C_uzG)RX zfQs9WxSmspp3}dV8~)FjdDcHqP5ytx#6v7z*vitu0_lhZ*y+}g9+3B~Y6n0WX+191iZR+0+{M<}%7 zG%HCyUFtAj9pu5j2_aJiaMEn7;s8K+G~IpO+$=U(nEzfFL?~MrC{YEPZCvhaP@hW) zr%jbWOs}8@0jeUDm=(~@BT@EM=YU%fzg_G}b4~8B__{w6FlSSkz+8pHw5gZdCE|lp zRh1ILY%G};RS5GH(@%TiETL9RI>0|S*HlEN6y9XG#2;2vMs_B81NSn*K+_vsSw6b@ zp^W`aV{rIO+_XN0XHTAoBvu^BC?d0meH{YUv*h7-5NYXfkoXnNlY;0+UetVxdssyW zkB`E-%86==9;S*~>6p8b*lQXc3+DuiL9x3(aW&d-dzVdN`8!FE_OME%&?@jL6u+3{ zMh6T>NQ_`APq{|3L)C-z%z}pcKc$TZXv?7@EAs2cF64_#6m{GS^t@p3COc$s;+goY z{SZHY=v^GRh&*&8O=HRU@EIi(Hq2i@zJmB`#cEKi9Fu{dQb9 z0;~?wPABonTozU|?rJ=)wg_7qfS-dW{ z+*!#@jWE_h8(0WHM+5Ng$VBCag%kOFx>u*TV}51P9rD zNaP&ACqgDyVXTCE9H8q+KrL5z0Eu+}Lrg*@Gyl19kQBzs!Q3_&gb)@EuXjYEgoTCb zk;n@ALlm&gy-2F|uq$Z6{@?t{>I$8BMK6CvMla4YP!Y^_d2YwkLShU@B@?k>EDQ)c z!xvkH`3|I~-6i7F!FE2 zr3?h|W9^ZH;unkK5;!>@K6F9IkAtSBRc zHSSy%27rfkI2Y-2yWbs0R z`OKC0b;Kj6!2BE_M*6-fuPRnv<}ROymu&|;x*(C9(4zi?HUbi+asg&gnr1Q6}I zOrIt^k&Ao$8A9Vr>Q4t(46cQsk4Te=RWD~2gEjNj7c&&JaR6R;)Bc&6C)HY@MQb=}-uEKAD!MT(`*(9c2Jmn*zJfte&Ye?(Zs)b%k=VG}j zGmz{&xy3hTP^~kD9F*no1^^2$p|!C}vd`k;h45TSKXjcJk+vt+rW~L*qU3uEo}Ok0 ze0WsHybxrC-CP9%eiiqu8>)&nn1i1?%&%GK4tzyIs*}4@<^uriTSI4zRpdp8pu}3! zlmt_aty6L}>!KW%B1uiN|Byf;Qb9fbo+tE>$@pRFHb~7b} z7{GJfTiPNlY>c0peLK1#zE}5;F~EZP$2bAEI;0m0wEkr5iR3>DQWO&cNDdv{V-pIk zhmUE?TrnQ4Q96pX3F5K5K8zH0UP?rxL@K@)jlEp&$EnT`TDe^U?6z|k)=3DN zcOya?ntz=ISvD*b74yE)miAV~earC06P(Ycv8#>kEHgA{6{@Dsr2}DvghGC0()*@2 z4+Fwif`O9hVG~pFG)6>#804pwj$O9M9f5N=<)tQ1#zJhIfLc!7nCks+(rPO0+1fRr zwnNmpPhyzC3okm6q2%3=8$fRWhR!)tN3&E~R@s7{}@W|KYuR ziDWi%u?;G|SY>zOh+_b|Q<87`z=8XBr^sYo8zwatXtQgBf?Q`Hr!g5pSr0uqrxY0o zcl?2nVKtGD((;*)GUG}OB{4W`8jy->Gh{d@+0&|R@%do#Mt~0>kIXe zyEm3RgR)<+$$7EY8iOTa1fvk^9CgLhASIPGB}df3C}fDo7^3O2JRmXK1}x>~t^o;O zO5r}6>{Hyl>hNT9StXfd1^ z0T`9Eqj5UQosdxJRDd%FB?{~Uyh^?5{4L*DELFxgryIwOw;)C5NI7_OSBZ{CaSkbo8- zQbLm7D`wa+-}20PB++N#OzMRla$bZSWl_r%gO!| zbi{jVDV4nJrP$@%sJfm$J3R4<@`+s>IF1j2f&XYTpK`o)DOtXlUxl?7!)J55@q1AQ z2(6h^L0%=D{mVRUATE;~s~@M-?D})SN?1=4I)scsJpG_x>1}GY{_?1)$fU-$w_-wG z5@7+{0xrZPi8%3$cL@^*2TuXCi7g$X5QxGYEwS4A{(eQ(Sub(UCn17JmitmTU41E96q}v8!BV-_nBiu4(H}E^A_=WN__)=rB=6qf!F_N`VMJzk6QE;o{kw<2 zig^q-H~Kb5>+F^V*6MZa+8M8gH;erV($rVZR)3|ZLgb-PdFXh4piWCuif8U3Lp2F> zsAVR(NgS#~FTGvrnLxjL-2hBlB}9~0`Ao3A*q$3rPUGe8n%8=tBqybu80}!~n_W!l ziPy?F%bTIn-uUIoiQJWQ#EGbSmyvtC@<|}u+-du0ryp=3?!Axd%fIoy;5|2UEA8z4 z+$LV7x=#|#WK_X?Q0;jU^MJ>*E7PyKt5aJdyX8?;-=rUktjT`;7<#Vpx}ln=cTu{g zNVCQFBh97f+R~dOPqwgXyd~!)=7DcoSENe!3htnJ^8_k*J}f!tp)hrjV@qA6oRRNx zixM>%vFBm@;Ohwd++l*>v#4(>$mq`XDw^~xbFLU#ZozGsZ!tffU$G?9mHt|#;G%n66a!PnKF1c<%zSKWnssD#Bd)%a9Tu{R3qhhDK7RgKC8jREE8(~9=fs|b zX?WBTnJTXrgpU~aC@?f(Eep_$7QmwdP5TBB`k^E8o5h~-X*#mPR5y74oLgHxY5wt) z>u>^*;|=ap0?UKVU^lr^6P>5U)`n_dcb6hg9FCGT5h*???2O^s8gd%#M*f}@W0LVc ze>CBlAO9h77|pJIoiT2(Eurb&I+V`ggDcx=^nKqi-y26pR$zkHHSUlZR1IVy-tlGb zGxbvlTv3EnyzR?j*Uc__(PD0wFpmarAWM&Htg}On4h6?@!&_9%h7TVzKDD0f7G6$s zG4u*uEFceyzI ze%n-$lMLbWdxQJuWWfyFnm$X2^X9K<&5&xv%H}_UmaT<1>e<-N5;*TYYir?yWY+y; z*5(GrL>c}=vP?6zMDP4PUxUxTz+oi1OuzkvXva_$BFWLr#=^N${drHZs!wDKt0&|P z@Jgr2AYiOjUNW}2wYs&&axmW&f%e)_s562Hnn}Y5)rGDZj0O>j;NxP=M8+Wd4pay) zI47-o!T$n+$@MsPvyfuvbj@p{-7&*cnU7=yZkNvsLMH5r_4dbi@jUyFM#bD$sM#x; z-F1{Pm-PaGSH3KRWEVkooZ1l6D~m9uxz7(>Xn~r9Tg(`MN#|D>H~H;pkgh8`;^YP_ zfmm?-7BFYom~Q4~p)LodwWc(QWGevO0{cS#0{(=B+zi12jRgItgPq;M_ z^st8fMXeIcuuDFnUc8A|9^!3SYV8ePEkT$t{kRQ_5B5(gqk}6Z1B3}&!?l2##+Mn= z@&+%QkZrwL$Cx}u4G6}BhcFjrodjr;@EYTxqlHiq)CP_0pm%4|kw3L#;qM~)8#izt zJ;j?qEnLx(5X%?_+K#Ng!TmEXCh=?SbI0Z;uz8VqJaf@~oaO2e3wm&`oiF6Zi0pR_ z5Q9w-a3znNc}I@kU+F8$?9Es@o(;X$-{6-m%6}}8f!X~BI;LUP!k|(0UM?yNyIA$9 z|F8Hr6k{5lX@06d(E_GENlR-1o5yg()_lX3ns1fEu>YH_HtIM~fNm!58a?1u0T?>w z`fsWKIO|0nT~|}F_2h&c6AQGrO(ab&V=$6;dR80PyL*ich9)B#8BT7^T4tp(%f2ND zW-c(zKxMb?S;ignT*m07Co*vGi#!T?_=brE%EhRaO5STjgH1v|H|)$1W*3mxGOpdL zYNwPyDGMc{X^_~MDQ%N`<#zuoZ;|X@d3f?(n8sEyrf{OBR7dm06-5KqF)x?)1-Od*2ph7gAcpcykh}!8(xf2P%gO^`9e(8|2BTVo6RB*EyQf!C7a(Z)dnSCS zulDF@gv7N;UhTfG&I>OMqG;*^h|Lf_z^GJAJ6Vym7BD&t-E?ijsrKX{nb*WWW>u(I z_#E4qZB|)_y=CqheB(+H@8>u;cmH3>zQOcC!q6$T*YCo=M@|I4F(i<8q;wcECsNT; z(jTgeul~raI4(6)4Iir?BU7DT&7To;nr->fB=qsAbh2lNdQ)JJ1W#aC16(rRvjfbm zA7xvTuRztX*C<#obPS_TT_(2i9!P$=Ehf_0U|_gNMqbUnoQIDqF+ zc5wD|W_@_;#4bC!II$T|MO_YszI$m9@6oJ4KeL8Xm|I}&*Ss&$@bv{RDh8Js>VE$^ql6S{fM7`)+F9 z-=6u>FnQ^?#8>PTHqmD*>1ZLD{r5OFe}6n-^DbiHjyg;O7E7JLkhf8Y z?yRXXkb8ahe%-Yx$$0e-dF|(Y!m~d^=fk(*O?mz-w}&|%?))ezk|^ezh_98tijGLy z>FmN^edsNoyWJeX3o=jZu)bA2Bk@jo1np0@!R2XZ=Zz-_xSvZh=+dn zNT6@Gs=M&`baaP5Y-eTfW${tEoEAHb45Hz}^ETosfaBdxK2%fAO1l4v|GMZ;d3vNT z8Ebr3`=V08T=81-yR7jK@)-n_fP^)otN;sUiAobYIg z#piYoyefWO?E<5rEZ#pLty(l;{;-gIrpnQgr+@F+@but}OKKd86>XM)ePR4Ff;6kR z4V|Iu_?X@xqsHm3}br?d=c$Tkh1)10u69qFYV%lV7zJz{#ZgN`xX2yJ`NX@9MlCufrVr#2KpV z`9J0NRm=5XN-xlEryq!qwO*&HESaEVpc@x7dfK)2=pN@suaoR=&8N3KvqamhSX2R? zjeD(C;hQ6)VRsrviF#fwUyr(F<*y9_Wd;pSaYfj2XW817<)eu`1Ux}a^QM!{)4n*) z1p(ohltA@6WCvFTbpE!7E6btP8U28ab@hhqQkf&?-8Eqv-%bOH34Wf!q=RztuS!#= zAe8JN^G}P4zy#Z~fM%@*t!5jC+O>2z+qIGgY8}HXlIGn%JtBW<>ad*IE}EamNXe()y$SnR=Onq~B4PNKYFN)c7-mC6b}aiPU*_?Bks zt`d3crht_aoi=U}eq>8w{DF4GU8?nKy@WC!psyF@^T3u`EBkN$5f63$`x#RI_cJKk zfSwU}*L3fI`Tv^PwEVHCa~RrR&Cykd@;yr-a`ZihnjxQ0vwP8f#Igk319L?SE7Bl2J8ytFk$JKDQ6cSj7akK++IgAu^E?JQ#X;op?<3YmX$|r1@K{O&*t-GXl9RukQA5 zQ!uU#rAD^i9ttl9q2-5eHsH+xX~mwkH*o!t%xj08ylb8JzFFJKeTJqP>h}N4RLY;_ zUv$upldySv(J$rOYL(m4ALnB~!=H}akiT$3BONN|YLg(Ve+(K_QV^YfvA(n~;`S|< zI_=ryvcwu>{1Qgoq{TlI-^o1v=oL!8F1=h|mPDychCymnTK64sYAZG=J^Oh0&Repf zQGAeYK`Qjyd!8l*rOce*4MT&5Pg$&j4I`N&d8V55J}_X2ip%bdzVkv9Nak5@87=lX8&HVUD`dY zp~9a|&kR@F6}vtwxj%{a&u3uO?F0E;b)$qoZGeT~f#Y;zSLHt>|B#3>U%jkWvimg| zQR}yJ@H?m$@N5YK&ni_jmCT()yZ%_NKcz=EHZ?Q6h>VvhU!QC46>geV?HuiCtuBi8 zySTI$7c94XzalKgaxZ6opM$2~=zlWUtn0-@A!Jw2Hoa~BwEV#{b|(Y8u#GG|R1i|t zDE&X8E6=L%4IR8wo4h;|AM||Ikt9_+nfDnQ_`<1C+gBgm>$22LT+>402g7SLm$b12c-lY_H1K0(FL;*El#rOQtz3gY{xvI4* zs>!jz`boi0xpC(Q&h^&bM7O+ErG?z3V2`w5upch2>4D|Xc zd522uOnadqVoW6X#(+Yn?AVWL$b0qWc$;eY68WchkKy%PqwT9oncrH?FUT&UA02(X zjVpNg0N)EA7c`&(`3Uam=h^4XNZDtp@=Nr~aCq9vzPJJ#0Cic`vr3gym}TfF8Vxt- z=WyjXa%;L&rScXj3YJBqa8Jh+JYcJ$jXDk1fR1Z-bw_&jbhEBpnlOZDVQ=v2M~t%= zbAsk8t5NaC)0$ltJwx7{&33(itOu0h3(t+>>N&Df&MFsLdxpX)qn>2t#pEo?uRapD zS++dPJHh%_I;Iz?4Gwxzl?G&y()ch4eh-!RE2KJjp3Ir(wAN|A@>!+*^Ll9M7f`YC z8mB%(%Lq>C++k-liJ#b_x^@pnR zH?g$uWAR>}>VJoF7YI?U%)axiBdhj$a2!J5|CHA!4O04gFe&ATvvXb~qsoq0Y z1M3|&E%9efPOQ6!#6Q@+k7J+qz_^Skr=;1i9HvDdxDJY^)I8)UZ9Q{oxx-L3 z;{n;25pz1P_8_EFhbh>`i@uzAi*ph?7Po%wW>PlbZmo1(Kc0uaU!Xs@X|;VWJc~UT zEl(u>1p=8?o;<=PY6BXFt-0!e=!0shfYF~EQhh$xC3@-eJHE|TYr6Fz;${3?`f)wJ z+s`|PU${3#w5cRBEJ3jl66LDW|tJO8* zdj#a?(ee_CF=}kA{b$UR9QyubIRx|cewNElcjhW>PoWrP_inI+6&=}BO7!sFM~XKj zJ|B?m0h*;pMp=up=SR2U?Ons?IKdDhw%5&H#fSMn<;L;MQGQu-XfB~y*JkG|4F;84 zqr{u}oWN)T>aIt+Dr#ARJLOIbORA^h$w)5zq#iZezVuP0ceajqn>YSP$e z_NEjAFYLY?dxU!a%A=NI1;UP^G!x{HiAw!?5j%?XwTOZ4YuYz^(M3oMsshhqSk=w_ zZIL=yJXNz-(QkyR8uTSvP z$63NUx1jV-IL*}Www@9R;*M*c!u%=p;%wK2zbU#Cr0m$3e@bQ-fujQ@ZbJgq!M7k} z;{G;jLvCRwfpR`_3vPO*m|zK`MEgLFGFbMSys8mvU7ym-yJW$(`*n{ze^{BY2-!%o z=+eVa&x;_)YUQt2z-5)@mEV31Bv=Zsv5BuwBtL?ie6sm+7S`O;FfU%GZbJ9q;`Lc^ zPb?=>x|vTez~d-i@S3g!wc0G6`8Cb$%Ae{%E=s4JJi=R<5at>Y)^lDm>@s}V+|(45 z$F{N4P%>?-vwlkNqme6lUj$kS*QKepyjnMD;8Ef3n2f}owncA(BvpHxL;FvQ1cThc zAll#BRNp-Rj1(^hC$bOLs?rDyEZyB<*rkG4F&P<@Q9p#HUKBhNjkhK?5P!d{{q%Z# zUl=iBmGYj(p&T*Y;B|srQD~FtYbmvP%ai3E=hhJOaAsf4_gRH~e&A1Hms|J`uHJ9C zJ=sn^FonG5J8*sK@?>V(x9cWo7X64<%Xzg@b^;Y=Hx7&kaCAj5}9pimk9 zU`(z%CimDNqHxsq7#mlHjRP=%o4=>F{~rrBsW3)B9SH-}R&sU~YK>TfBc57E=6IZX z+9EKd`Bk@PK}hG~ewN6?JZR>q2Wn?KV}957&GECqZRb`-ilhDZCllhNY-!ZsDf!(H zK>s|$(RaG*Sw9cIDYzgpqu+3j+YYFoyP}fz-P%jWMR~;4n77Y~81S9a3SMU_2!UFr zHZO>0BK;&-JQ8S}Xu`C=j};(txS161I5hYQKFAT$Pn2O7aN*!b^zf390^m|;g&U(i zA0o16@g>|KKk^k*OJ0a0YQjd4SApH(7`p;!79a9H@?{=&b_gE z{yN3;QK#r4YWB$C;AXsZzVCzBc*h6Y z9R%*+FL(w$XThZA_q9A@-Zh)s&yy0}d_i;?44}IGUIC z4eEbX$nY6tal8y_?LqxO?*vS%zsLIvekrMG`NNUODi_@KG2vjNf~)%Yr-ndoTnqE! zWCg9fP61^Mc|=Uj)0IxGmCpgIM2oCvU80=DBxCTdh*g#!@xJc`KQFGuu2v4a4~kD$ zF0}V+QjkqzM%u~1(W18LkuIu1!-@effv2cw@7Y&&H2a~n#K(Cay5q#)>5QqS#V3Tl z+Cf{_KCAFo`5-PP)3!k2=O2}>aW<@Hmu^ZlpK7yt$yY{QN8Xa-8n7n6m)_DBt0rAs zm4ZluKg z&crMqQkXmn?Cy%Op;trI5TATV8wvcT_U`3fHi6)>$#hp#Sv3_EK$Hf5P_kOMO6Ymv zB~$kf;AYs~bN@lCZzS$!`>cgk_~1sF*ZAusQqSMt8bM9)DLD1vQ^dt2T(30@LOst? zR1bbMA)QC+oPS@&#thvO3p-c*V*8WAQ&i_haq9Q?1E*oxRbx^FUIe$+#nYlU(dc-u z$KDwc(umhdfalx zI96W>k>$VP-lTk>!&-JZg@;`ug?yP|e^jr5!nC4YJ6NhSq(0hyw_V~SJoC7gnr)A+OT1#lM=BK zAuqi0ov39n?^*JaZYI5I`)YwtHu7T=_YBS528Vs?!f+=fE`bKS$xG>8qL%hRNv!|fz#8*voAp5cg6RwAaqC4DmMLZKHVdqU z#F5Hh?NI%O1fU(-D!5@&IVF}gB1O<{+d0)QY9rFk1(s@}wcHIx&x4_jA8gQX zN?Ik=jjCVpsbDdLon{PJFLHyus0>+x5x_>FIvbO#EzW@FpJl6&{7}`y;^fX>F?TPl zFCrK@z~3yYnpiPi3e@ZEkCWEn1g9Q<-SQWQaLX{=VthBRzT%psPuF$D*7eIgiNmY3 z7hi5S6#=(AsT5zD6qf<$PvrX46^21;I0@9&ZwVBL0q2%MKCd$x>*LP@C`nUs)uC~)L z8Y*0Oww`Lbw)?U$P&+#@MG~qpp<%#MqxbGdP0N1dqWZ$zKy%yBqH41f!?!ky1^Z6` zHf@z=VbMdAtn=Z3>o*z+4xi4!01480R(NNPXHZic&@u2T?^_Ih_Hrak=-uoMRr_>F z1}7y3P%-bt($!XCseG#bx7~+3r!xtoZK^8|xM%yX!4|4L7v_VUPN}}dCbg%_wRs7C zI-kr-ALD#By*;p~nE$gTO51j{liBLZfY8_FlGND*8dRu}S4We4-}^&D+K2#tg0v2u zno|*hq3v|0Kz6q6vHRMH_AS9ZAta^cMr(N5m*3bu_vOm=|8Q zViShFgl&~tSNv7Di+u{t$~$k1yp!|$#jsL%4SoMI?@PncpsVPNF9O$u-@)_M*t2X&?9?O!I?aK_k##P^^$xM8`z8S>kif>(L#gle?*~=2{ zZk!$FalxP}i_lnq;(iK(PHtdrZLV~WD{YF4^8Olk{Zk#S(GM@-uQ*DG!pb~tmaaM( z^e}%Wn2u!Uq>lx+EU8h=WY&ypc?H9zuFcD&_XGvOgK6@i%!ljhwTD7%@lTl_&Adot z|IR&?Is0{ud1HpTcqj{0`SQ;9$adQH4H~45kPcGc0(h;pg}-u88f|cbG^{@wjTObo z_-e7{j$D5=#k@}ymstP%6-PGF%^`_W@#|YOnjV-fy~-xu1@5bB$5G#9CcJ*+`IEMz zVq;i(J~p&TyQR1MA+Qf|BJb(vBF+RJW%etxZfO=|a69{#Ed z?4^!~C3c1^oi&kz?Yby-BQgnBR(Znn*1giW-$_H()mcjzZzkuhj(O(0ed7zU1Revz1+RH9o#G#8++ z*@WKir!$vlgYD)YCODz0P-WMjKMEy$k$m%KPPHp>1?N(&I`QH5&>>57KI><_w$VW! zeWy9Lz#DL#^~pHtV3sR^%bxKd*yF%GA1*1_6DG$22k};A97SUNHEepdP?VtvnwJgC z=LIvkcUNcL=6;F+b|aZ0?nIQLMEOrY;IaJ>TbrC-*qxllb}f01b}+k7>GX4Ha>GSb zD&L_O7qj!{sfK)V*1qTcoj;J+S2TQPKJ(+lxVZB2t+1clzpn&$=R9-EwWAj1`Wcrf zmhBnrO+u*peboQ(qTqsi)?2>n!|h>mtI_63Yq$%M6<1fB6lm;%D+720I6~udFyB`0 zWhl(T=yM~*%CNYeoVRaYVM!1G2I7a=kkd077Cd)p8{4KhBCxT@95f{bDj|31WNW!Y za~tMf@VVp+JIGu4zlEB?FXVYaEe2(Al|hB&Wp6rueOGg=%MVuRR=eqtB^5FJq1i9L z>yy-Mzf7d^m)#ZXjri4Bp|9fa(2q1Q2i#@3V(t~FXh3S&g=PGfqGjjsqS$V zqTnm8z>I}ImIah14{3CzdYw7_I$EqL8eyROTm$$BI)H_leedZ%BrGfEKbKuVzC(P8 zT}ta`gm1)>0`f#@xy}pnvRZwPZ=&RDI;^3HwdNrbF~+C5Tr3rtBeyD5zCQ4#xvVeBZl!VlZHC@%V6j;0 z@9a#OR#apBwDEb78S8VCr)hBFcj!4F>6=un&7q=VTl3*$V$tP>k7AG^0c7JL?7yaA zynWGwYN>DbUZSJ6imRHVkg?^)5Oo{ca1Z-u2z%)pB~ROmHi}v?+g?0q-pxt+n--dO zmM^_xypo6|vAo>ZqM?V{^8ut}))OmmS#o^eNpE9zEXj~SUzC# z1r}VE0q%h-Z^$2bx@H&;`_jdsYv#pGluIqk8;;;Adn~Im-pu{+;30*~HClSb3rX|y zcyxf?K-1O+Zld$}&$YjaEi}rDRw=TOH|cJwQR87WVWT(V^w&)9+~e;-tET zeb=C0ql=fs{SRUL>7l{rCOJgKH)lx4+237!O2e$#CM{I?FBR&n4%;j^5LG8-&>bE) zYw61M;f%e-Lz_&e$vCcAD4oVo;+c5+TFdPZZxlFXcznil7E9VX$skaCfC1oCvEw_$ z(KT<=@+N;sR%v)`LJws$H#dymtkJ7`ATw7vw#4TnW~b;JtVRxRb;jN4oWI>ZHuy92 zcR@%)8~xKcLvWF$vASI~{x56La_3*}`=4drQ@(udQ<5vkoYHf6~Mz^R&*fx$2FvVdH})wL3y_ z^@i~WW6;A}beD7CqnAm)hnkxbJDL z_&adEZ7pJnFnRw_-Oo&z`FJWM&@~!cdK@yndp_C&8hSVT$1K^#s@YPS#<`rQZsghr ztpMCE^WFYA0ZSj!Wi}}%Ql2zkpF&Qs7aa#)m@x0)r*j&9`AIiL_5jBDMrveB7dX zOxrTz7OmVqV=jLsre;&l=o^f}jDEHG1>5IUcS=30zEN78R5N1;WJB~z!{X(Wb^d`P zg@lhX1^qMqx9_}eiqB;~tdZp_D?-MNo0Ud5{6kV5*8A+wM*emB{5|>3s|N^CZx&g( zLyk}8=9BdF%GCat>DfBIJMf;MR=lznlz7b_ai3h8VZM=3d#mAC%%gKLLPqi8qeP}ynm6}31uFk#7CH>vS`MiizGtBUYFu(o zzG@x5%%Y#{SGBrCf;Y=m5@%e7O(_fN4CCe&Q?~1E>BFW#-H-3jql-|&AF!x<)Pj(9 zKHl26jl?wJ^(ir$u6Itz{GL?@VKm~+lenKIs+ z5@7@V%DDJprJnHTh+k4OHQ%dJ@4;el`m+}Ras{I8dxIbU4@rWF6~m!Q=2h6`z{Z4a z*PBw>?0%WZe28|Rsl_Ha=&i`gbmgC?zvzMVW2|f@U+vy(i6I}gmzTXpn?|IzH3?Ab=U0rU^TR)!|*i4Zze4gi#odg|fnP2t__k3n{_;yfn z0svW}7L3>AHWaq=b~-698ynfI!m-z79@D?hx47!sY)FHQti)Sz|_?*tug{;D$v_#!Jy|;Uy^BmFMV>#Jd}NjI8#m?C1{j*8nbBP{6%kLU}9|;&4lZJ*UvDMORK_(^brdYh}ehBzW1`4qcC9 zDaG0(Mo+P&kq=fcCjDh$lmC!xO^p55g#~UqAKhq15?oT;=4p?+LD5G;&>1>c7qaC;JFPwfY9yB2&1^O{TWg{wZ;>T!tqdBe78 z47^d4;dKF(F3fD5%>V@WtmKckO=E#*8W7cao&GlpgPB3O%%ByTxcS#ZdWO*@db&r~ z%TQQs1v;q$JsF=F%B$$)d(0=zXOw3zD+q%bFa;PemkUE;cs`WgCGdjO4L1}p+t}(? zsLE*|9LqxxH9Q@J8k@D!Zsl%u(6ZS4-Tj}1u`D9;KV9$!&l~QO@f4iSPr?FV@TI6KI`1D3qeC`mbp1D?K1*yXj94{hcv{tRjEUFd_*U5Y|VbeI6D0)rMu zWLzO`?_8Zv4_yDsOxD1VK?02sI@;l2WT^M(OsfZn^UyQFcQM&>Xm^5K7 zvrVKOOuVy-k?L`f|L%XyH!|%;e?>!vnVnuvh^zviY){f|5(oYJy~sUdkox(Qd>YmR z81<(0YE3H}u}}vjg^zQ6x`MgKUiJlM5DxZ&DAIj!kf|x^qnnrg9$ZH(5_tIwY7mW8 z{$;@`#j7nN^7)JssLBAKDow&k>CIqztN-%humR4RqO8roKAh*Sz;R4QKT!4~pJX~d z@~TUId6`Ss`Uejj#)!q>$Xof7IECB#??*i^gD(`f+1-bjOqrHMXpD8)<#7dhG_B{H z%uE=_omAXPY4Bb+a%>B1i*PHn3HYyKSnq{Ey7m1xWa7Veb?bgH?*?v`b#}csd%vn4 zMtJO94B^92*2qs6S7Te*-8LOqJnSBKZ;Axij%5 zs)(xX zkDMDaNI@#dJZ%8TQ1h-Y`p%+rc~ien957MO6Ng3e{Yf!%-H3YAc#>WFieseV^!ziu zSQ39#=9CGU-4|*&*G;qO&Vd*&nlR+fpeAxNM|n$at|%?uL3e>^R+&e*N+X_Pad@}6 z=VF12pxuez#@x*MD1vIGu2TPRFWisuY#4YwfiF3`MSF2|{js0TXm-{Ik?2-Z@XXL1 zc#Ya>vd-)#*qi%86J1oa*^mlT77Rgw4a0V$G!L+ZHz`Q;d)O zt?`V3OYb+UEA{69!4 zVgPXY-!NZju!;;b2=LB}ie^kU8ZZJ4!GGKRr1-W@N~~*1nFX-hfL_k#VTFO^j>xJz zV`SoWCUT(xL4FMbbW|J`TQi=aB+to47dI4&Tak}?x%e-?1dApVwxvH^F4Xgq7q284 zNYolP4jpa6@Uo*fT(KRxA(LyfK2FNQf_ntOfN>-EU*-%OT98GBq$S3>>U7TgWx7CM z0dq82=&oF)tBZ~m@ULP;aQmlNHuTkH+x08LEIDrT7iOukdM0IaXrI)VPC!# zoSpV31MpqwWKaljgi6MzF6}9cSl$SJzX33s8cbNw;_7igU9YSKT_mBHUoLw70*hdG znV=i-#t!OD_2(^Ie^${kMQ3?xC=~eb8zbLjJB@R-YHG;sr0tKwMZbFt{dr9U=P3c# z#oI2rFW!n?gQWfm8QqV?QE$P&b1go`NX5 z9h>(y*V?+@3;#n9N6`o_l3dZC#~a6+%bC#ShJ$33K{!o%H5WZOuA=)%&+ic6*(nrL znzAMcb5an9di;>bJ;G%)_GgmS#NvK;hh4=u97KibTf zi$!Jj8dT!_XAZxRxtdH(p#C8VGGRi{uM_DFU{HMrp{b2lkDng9^<1r@syRBF6t7G-(Lfu;{5sh>_QAO3mH9iBmp; zXU12@Hw>{rzqIg=V1i7hr)msWSTP}+rzeE%iK7{T;0(Gg<@v@1?=`g9yZJ zYgu{}DGIcPhfrfTrz4LfB&HW!hYkF%k!2axsKacO$GM&R<_T47Zq<=r(>6~w0Fa5L z0-s80WBHsm<-x4kEU1P{iiDRP@2_2(@VS|Ce6j_u_|o|@u~{YWj@0Ei!_9w41YoBBuRx3Zwh`TFK79Om zaV{>|$PNiJE7fE(L8ee>k^vobnyL!$zdGoXQt7PmPX?bPT0lqx8pXq9=VPi{|MMVk z&h=3aDnw$R4Q93z&z?0I6egDh~U1mqxsP87=g;NN;~q?>#w2f$W$1UNw?`=Kn7r5M$dGIzl6~TqXl3f zCaM33mWHv+%9*g_@TMVt#VZ=F<%r$1u?5aS^WJ>oqRSi0odSlpqd3D5vpxC# zuL?|nCbg{MWW$iJR5Q;r|G1n8PyFB|N)^OrV75J;57mp6pHtd2Y9??*5=|NQq;mmk zh$1S3?wd=CPJ!Thu{V6cJhE+s4j2V6Ucg{9r}rj@S|4}riJShOGy6(~V9+X$wxegD z{%si|ZuB5VkPs$s<>5E7qsg^fw!mQ`iHswU5WmY@UZ#<@+sPr`*s>nTn{+zim59me zg+z5Rzln!&#NZrHE5lr}i5FZA{wj$=qwKtr35ldY9>^o(4QF=Aug)d-bu0CAf_PxX z_9z>n8TU6`PvQZ5 z>$A&FC&t(HIlKH(U#@Mk-vxS8U7<1)24>S0wDVq9R-NjO)umvz+g$Wipm5G#*p!8` zuM+b5w;+rl*j^p}W~v2#4EvvNjUGj9-H>%=QU5z0^|v#gEEVRj4N$}MDi*$edVS&2 zW7TUpU)fPN-jufaHoFErWw=jaUQUo_U*wyfve`|FY0oma-WSe{4SFVBsy0_UeZY*v z?tA)+ueG|mh;1}J>LR#|rVXd&>_tk|W;Kty+VqIaB0j)28b>j{T3?Qxy|o83APP-W z3Q?CO;&FJj*7Zpxezy?mrs6d{GzVcTuRG!kbMHo>jh{PbYC{K`75-4rgm(AD;A@u~ zjf1~YHTu1GHZ#jIqq45FAoE3{1g09Nd+@f>?FZ^oPSmUEfrFz&>*xNSmgcrZ=Db`f z!zg$C3UD~+f3{@QU@0NxCAAcx*8j4tx$PZuUbg?W#_I&(yP{_tjy@bH z4V!*5^Iylp^rru0 z^0Fl1#e#eF0M|}HAFT+0>cT-!dr=KeQqP_T=v|&|}M9IdsOGWj$h8`=rh4 z@r?hz@)^giILawAO({DlHs)|f&1o`3hN~a{swXHQ)AcUD2wn^u-3`%kLpYuy_!=U5tS2bMF>{0U0dZoxFNUTD2}< zJ@5)CItzi`szCc+6~r*Ng$*9|&E(8dQlM=5ya%X{-BbsTZ?vR^BL9;=napio(QqU?3mA8DZx0Fnd!GPA6(UeSq=)tZMtAV3z8 z8hOvPM7K(i9RLA0b5iQzu?C=Jw6AyS||Lc^gt?LzczBcrLR}d)Ffd$C>G92%mmUyMBs8sUJwfdne2VAzQlJ#_vvl0yg2?;0*WxVSc>g zT7O5m_P<@QI)k5KMybMtC@&wWO!l{anFIiSSs!fER7%`0H-oFk(e-K(q+{AbT>}ck zbHZ%@%LMa5W~)3IhxQ$K74E{tc`?b7G7VfEwUxF}XllMNP1Yiv+Rwg7IZoHnKd_=9 zXFfh+fp_=XzG9uDvr6kt=6cO`)$xFr9s95Qu|mKLi3cT!S4~l}S8EV;=P5wl%7Bh7 z-*j4jAIVMDa%`TzGwZcif9qx{wk%0e5D!vAA$>}!-eNE_n|*zJw7bWK+cDL<7c9#H zzub90rr}++E;=>boeN9W{3T;xewG@a)X_h@VoDAfzn+B$ z|99i$Ni%AkQz80XxT)ByK>_LK$QLHE@Q)Ih_+#@t93go`b=81@S9zI=W|SI}ibenV zg(_e!S-=q^?7y?Srqa$(>evFps|T+w&L+(_8ijUot4B8!Cm=|#W(|!a4J^tD-PH*I zys)9Cp#{b#>zi&g_Wf=ZlTxs*xj= zfh*jwB6%2hM8<)J`V_{2UcJecEsHwyJ-FQn{5BS3L@79*{}pa`uJzS@M@5WBs6Fyy zV?-WfSR;O!%4JE`Yx+2s^fJ~I7$_atf~j(){I%PgCXAi$^#8XE z!=@u};A5R-zHR(!QkGC4f$9ol{c2m@{JG2AvLrX$k(d81>G>^UWY$?}eAwJkw>w?| zvuA}f?!EydQT~lv`=YEimi)pcYYO>v=$*_F|M8Tboi-yEclw0d8XCH(6BZ53?pN7r zvr#tvX;KbraZGckVj>b7z@cQjiDnCnK`NgVf3-VK@DuDrk=e_CITFa7h~BM$!c^82 zV2wnch z$Pz(ROV9d)(**2JxKBCDg~0UlIYCwE1R*3}q<~>1Fpixjbqoqte`PI0$abDdw6+dV z9##lD0Gs3qmJ@S)wJd{?XJTl^I}zU8liI(?^*^5?qeV(1$cu2%WLgxOD0dj9hBDna z)w;;nP}Y27i$iD$D!@gCDUy=gP{H%Hr^_yOqet*^AX3tA`X}4#NeS3h^5Jl}{)~P- zxYO~fLcMGayaXrxg0ivJ(DfDLlawTej-pmo{Vq@l%pb(N~S#BA9c@GO-O|+ zumGnRQFtE#V4)lfm&gc`xIaK;&6jDTDhuimBZNf6Of%qUGxJeu0o1_y>((J`TovR8 z?%kQvluL8AMf$tPG@P#GLSY)FjVBT__KLNnMh7YIkn$YtghHi%olfN1ucjdS<|25W zl=4u(8%_n!5V9-s&&;4I3P&h|c!mnXHTLx_M0r{`)Ug>3 z|0}cslGXsp{BrxLlxjM`G2pkW6o!A~l>Fw+!dN{3K$rlao~VFneX*n1wz}<}lD0R| zRY>lD_PJ-T{#{6h!mvom%5FvuALMLohx=Z42zjK%25fMPHyNCSvLfHe-Wu2o@mytU znoy@*d#Y`uq~)GPC;@9hAhzeZ#wwd?q(j>Q3|;}@kn-x0b^b1H-hK9GQ$@>RxrxG2 zuB_tRh`ES^!$o={L2VNIWGzKfu(z57bR$N0wH3U+BZu~&Po+(#9ap2R>s#j2Zi-HO z3Z-|f>q=Fy4^M#SVhVs{fQZp8cVYfFIydI#!6rG_)9W1YFy9GVo*r2i^?6*TJj`D~ zBIIY8s9#mf=+V-ghrjm8Opa$87ZTdDEu7^tP?~~79o)wEil-B@Hc|GouqNDa&fuI- zxz%-0iDQ0&urmi)NN<)&bfH`JvGRAKzQB57nN?Mj_G+3ml?je?u^ZcuUA#5EI+C|zS4Hsw^d}GdQBj*!iRf}Hw@bD!TGhw2QbX^5f zS_dKZ2n%~Y+V4=04Q}G@Siy8s$Z*}wgLSt1?Qu`%@72=d#j~8;cr;s{LlT@U6g+dx zap`g(4PQTyuIXg6b&LtklJa6s5;0I_EfcXW-?5dwfabT?g-#9TyhxD-W!B*opS1n@ zYN^@xz2oN*&p5g2 zmfmlN8~%MN-f+_z#YPqd(zM1_Qs%D}iYfc~?AX;xK@$Mp+;H z9= zr@Laqmom+R=Phr%(z)+^VE)EX5X^Nq$E5ryh* zZG0K?Lc>g6OvT`#LE%6|X0U$*XjKA_P-1B3CC zHlj#1M#wgymy%S(I+@}KKjC1UFzt}q6v=on_?_UtN2V*Li^-!?*TRtR2~l}v>_}I?%uzdm^mDH^!T4Z&6t1V z)g%YAjXQt+FBevIM^A4LZ2#$l?4a|RUdRMa=Pkfakqrc!fqt8!9Ami}yRkWrX+`kZ z)epzMF!IX!_|f{?f^{RtD-vtK)_BG-o$+1c*(+=;lrj?KhDq146DC{!Q(9K6%nJ8a z?ELxp738ZbVX9l=4}}c2kE_%sBbtQ5mX;Fhk37sW;R^=7w&zp+8uk)NMb= z?GM+Fq%>8H^sv}3+ThCXF^n<^wN+h@7f?715Bbj7HPJ6<$c;?LY57+ztdZN@Jk8>? z|9r#fn`*|l9JUTun24?Z2rJ5xCYTh8ypR+F>f&mHv_fs3!{UBKBDBR~iczlm<%ICC zV&ZXiFw+#ZE!>Sk6Sjjeq|_$WV919>$YM~mT0g`J!6>_GoOt|V;!bt&Gi{k!r7-xb zMA(6GMxoMQKCLt6NB?hK1RT;{NaCKy4=>1}TkQP=(!D6l6JZH%Q`()_*_+~+!TFLm z|9KFe;p^x@`>6OFhdj^#gL^DQUH=cE=a(7{iGGp3&e{T~0fuSpzZYd{Wc%EvX!G}? z&ldDD_T`?$5GoZt{~d!>(TN|%nQs~#p*(|WBEaoQFYo>kwvrDIjNMrwynPlH2$y@V zkl*4uGoEYsKP{Yp-E+nF6$DY#0<*xxX1PD&gb@~)2D8{U?v(6mT%=23RNi_gc>j0E#Q{;7ZG)S?H0J<}1r)$+!zUAGlv3+ulDfz<-O7T`6o70O zLr{A!N9EA6J}s#eS?IDWr=i>|b~;689iK`QGliM9j)bHez)8#X<+%VJwuN3AE8 z#R;A;356F05*Bt_w+IvmhO(4Bl9Nkq<>oBnz;Qi9dSiN^eqwUT_j!Y_WYy!p9R)?e z3E$^DcI(7EQ6A^9PiW#2tIyL$Mf3R5YroaJf8~S8GLz!`2qZExxqK%oUlKeqNypRH zMhKzYFBe~XkmmX&s1>vc#X1X(R7i-o*iYDmN;-=q*hc2D$pR?_!CJXJ zvvwP8JFM=U&zwtc^x+h?t zEN$}n1B?^!J34^h9=!i`!?1$Imw3HNuv7QDrN880a;F#I6_bSd!IOOja*iX_i zjq%G>u${B6(mT8yD%~E|PSYtds@kpD5?3kSnY6AN9@-tVJ!Kg%qwlRID%&0V7Mo6<-K=3bOB~*D+IZ2sz4XVcGc+J4TzpS>0RlmGxLOG20@8% z>&P7tjEgpvo_9T!FmwiWSR}$xN(bAIvaV0XfBY9u;|l|envvfom9uN|pUit9U({pt zR(kO0EGZkmcctBbcbrMB5Ly2SSO4+X_v{t$OSM-|g75|r9PT!!bn#R zC7{-y+%SXS2l%*NMHb$S&COisKzekq?F?Ss_`ujh{6$~^EiH%u3kwzP-}=+ew~`<= z8W9tWTr(*wixA8vyUhMyCVg22Eyr?q|q7S#V>(Y>I)i9JK; z1++?@sH`tvb(;n(%%s5QUr$IzUOc@+p8UbuV~;Dzy(a(N2?>~b!?UY$SS9=m5ztqd z{0D0-Gb_NIn4r|-hCYCfTjmc|WUJoYI5MSld;a@X`_|KWmuJ6QkQdGMeU29p*Wcd? z{$Qz;CO1t%)b)-^M#|^{^zg23KA4=;MssF`Pfuv`vVOEY|!11R1U-uPHb zPCGJaAN!aDQ2Sh7Ob^k$|u7OwOn5;NL|9%rfimJZyfa^_AHL=>Ea_t?>fy z#?ZO#yy))z_T2i_(T6`+lWG{}X@d$KpdYd=n)ub7^48PwP|igp`wdh3@6bib@oxsM zHyNH~{l-?FL0QLm)W%L|Vv8gbC*^Ogn>mI&?#&iySG^`SZQltJ`SyJ{8tcx+R-ROU zBIsb(CP~86P>E^YKe^$@fXMdiLo4aB`K$*jW_*==Mdy6cr9|ZRv(CzHYwrgVEvlCf zvG(F&By~X)C_^n7brr>zuQyFdHk!9P8y?e}YL>e1ZO*U8Do1kx5+zuR=xUep7R)1$ z(7;qLQ_F5=De3p|D(aLNJ8& z%yi4bMe-~-=(O8hI$Rjge@aOJI&g;7N>_nBY~kVNq6Oq`9S-Vc9$r+}WUSHz2U!hs zJp56ar_8zOis27Yiznf((po6Zim~k7m805<_*Q>tf%@Q=R~g6Ig0ZGvldY1-u8ro{ zS2f1Q&0Upd*L2k%=Ki=>oxo+gwV zqEmG$<0$?SMsdA9>~>`Tm!ZL9K1P|ihjy;*I(3Q^Q;O7D#yLtyCabYTn-XGIWgYYk znQE0r{G+_xjc;~lvzGc{V7hUamR^s?`Yf)d?lWFMo z4_22y=$(T>TpGrt zHg0q>ydqpYaai1Hgev@&z{33x))0+$2FAwz%J+d;aD8UO7S&mupo=ZnAFN^S21{1O zK#eIT{!$Nf9&_T#r|Z*p{a2D~2Ae0q%EN_E0d!uA z+jt|HG+x@yKsOJ8x>EqM_Sz;ZL!8o3|(uU9$i!5`+E6p%55%lzfUxIb@^=Rw)3gL<37IXlulV%g`V7|>cWB9HV;)1+$9|p2 zjYQ{H6zOE6ibc(4lqd{9pILTb7)(S6<( zfd?1Ov5!X}0s{nndA206Mcb}8Hs+|VofqnRhI#3aC=&TzG+6Q<^qMRColfr^$RYK) z#~i3;Xi^_d%C8RCsk6TmVtF0z`26<$#`nk9x>v79vqJ!iov{gPG!EjoNr(+0cD8|7 z;sdP32W$rAe3sHe8@*7{+3)p5iP7XduVQ07R+^Xl-rOAf>+D-)iwrNFEPNi_8+dSH zE6P(tyGpV^mEW1p_(lUSO+fyMs~AU}N~1q(+Ulh*)%m4Seoc%* zJb@@$j994XeH#g;BOb%G9=l7p?H%%MIzA8FKo5TjO%^fXjPDiIk#%xuaT_dqhz4GM z5$0%Y&9~y*(wC752iII8ViReo<9`d*HY|?Ze18V@m%1Q`Gq!x{ zyc%a<@QHXkYWa}3m{cJPfaWumIH_<4g>j2}Cq^h|J-sK|cs4@MHoxhT)nIW2TwKsN za!xSVGFrX=Zlct~E5;V|voKHL-67H>-)pB})wTd$|EWvQwX}llX>&IFp}Q9=B!Xr~h)Us(qcn)>ouKcLlZ|lT4$pC;Z(?OPx zB2^QtF$XRza*w)OWC*9sI)H% zMZ+`p9N|^74XTq)cSb5Wun@T_k{1kmxg%&<iy7R zeT&auytWBksphS<7WhqarEsYVU^H1*k*?Sf`VhlQ?PO_A#8)*iuDXZ)bSPu(JMCodLgayo8i}!gVrr4 zCtnHL0jdI_*iz5bk}nT_E%0-d7s-5PsS4?~$XAQ{Qt1HNAS&?igw}oWePOSlQ$|(S z6vhps4bs@)muwqNEH8%hK&ao}aq3a8s7;k^effihQ@d%n{Qc_afq8w2U+dN=w)J|t z;Wy7}VZlO1cXWzj>Z^8$J9>juCuEw5VIbHk%I6OjUY~cf?7qt&&1WWueo@^t`(`!Y zM%hr&W(jnNWX?jFG)IkFzv#owA*UN(x>{)+R4*)PE3QAZ>DX6SxX*vOVOl<>tJ!KH z)_(n_^a}Oufhf@v5AIAX6P%Zko=FYFqGZ5MF?(4^NYXr6f`nF35`4b5ujSAh_ z3q>9wbU1d2m*JAdBTDTCRo|afnZD#IAj<9;t(ihYJ+H!**aZK%=88}%*@EJWbU_CM)9QQl$ zN6AIg2x2Ck9GXli0O>wxqcWfi(Q@0xc&`=e&!5eGUEsXl#-m)U;#NwpI6fXKMUOfu7Bf{Rua~0>^MjbLSYG0W3nQn-k|+b4J#tDvfJK zc+sA98^(t?JBSbKQI|ets^8F=J$oBLA1-tmkBa5MemnhYy(l{(5}~U!&4n}UVCa*+ zuGf-R$JnrT>FE*nWToB67@98hDo5%ry{ zMX}D%z>PlQMqPuZ@2w6sqPl#3XeBl~8!X6`mcB+`@m&1SV2=D+;zQ!9NXP_}`;Ic# zk$c&7t6GfF(@z4Ah+mcUDfAA;+W7d`u0s5uUz-g_zwRG_PW}GXpcTqPyv+YA6haiQi4+|_;JfmHN^Rr_qJg^p%_ z@@tEhhKt=A;8|u!yd-O$SE!){ih`Gw5?oevYq=Jc8gc8h>M!1AK=wd7{G^W6wtppR z&$lBa0XLhg;URA-p<$YHCvbPB-N>fPrkjEZv#|8&IETUHSb}NYP-4$fq2A{Kb!>Zc zkD^olL%T6_n)3<0xm?0e8=RhjKJcTOX96l$v2V*{Nw3`ANoVq)HD2}CTG})}6Jf`0Y_qE| zJGe)4H@|R(Dp=w^)x$IDHAtGTgUka@hRO7C{$L5Tnxk$X#Wid!Ea$WV*3zQCty#XV zB;h`#1>mu~am7}}PutD+TnUS@Zli%m{A8@tTzOi}{_47_FYY>rX|#0Vad&E;6(Y>o zQDkzVk7qdjV}e=MkDkyPub#CB0v^_T6s*IIU|}sow-h65sV|7-$9E-Oj)R8W!t6`V zLsn$asmU$jXv0HyQ9W+?#Cp=F=H>2RAWd0;yzd6r2K#8ptonq7GNXmoty%mj*9$+1 zhkk!DBswyPdCV%ijz33 z6V*8}a{JmQ(J?$}BgNNSjy37S5L5)kY{dUU{74Vve$rPyF86FW(j_T(wXUMBKZ8@@ zI^Y00w8XXc_|&M4x&AbV7M&By_y^0UZf>!!Vs?B)h?!5~JUV&&cfXzyvXyUKnLJ0G zAJ>&u7OW@<@Fm;uf6!+^l;1>b8T3+bI45aKr%0M_0buZ0oC_7ae}elTKTShIk^ZNtk_T7TTPCLVFlhXFnT#~)f1a1-%w0=q9#$d=w^Th$+jBsb76ne0>&9a;W$s!G9`ArosrWpU) zE}1g%n!>4G-jz&*<6iVV?cdzPoVB3 zb&UqCi7pa%OTV`eD$alHr9$}9%RF0}x6aHm^5DqjnO7?)hl3kG%&v7&xh0^BW!X2!`OOgPhHph@E8PIwJCQwn)+(2fwE@1_#Fw}2A60ih_NPDT znd+(nF~v&olik0`5Jz`HUs7t@E=gr4!feWyg z7FlXc;|)u2oq@dEhCoCRK;ucqa{;^p?yS1>{`cf!f>!eGwDYJJa-ju?_{Bo$e$&3{k($8!< z5NFC)cJ;G3>KWJ{+|HOZy^Xebw~xdW?L5;Dz(cLdD=CL>+brA<**l!Eq5C>-_Q)HA z=th(-jcamdiuwn{3cX-FJ@wIi~NiE@=ZwcSO4keatK|d0VMdb`WSP(Z7Hia4x{DLhIfHUu_&>q^vc+`;%UdRuTRD& zsDa80FZOV~-}v}8-4eN6gkKm0C#y#-{utgU$%MWic9EM+m@NF5eMc9DB3IaWaTCt- zPC%#Jjw7=rccjiZtqYH4$C>^Ho0}7P6~s;5NlX+RVMJtGbU1WbNsZj{8KmZF`%J%@ zXvmMwmW)ssL`w4Zvo(qR(xG?z0BVC~b*{23rn@_!AinH#15@nGozcKRsJ<<;%0}Yc z-pH4>*ICe$pyY}ge$fkGul=A1XXWlf*2NT*#q~Q(vT5Eoys?0T#$8Q^unW_XzDqzo zg&;>le%v^Fy^go2E;zOfa8L9~h14{7v^#pRkAgcO)1zI&^g3@+6_(OSU`YNC96wZe zCq|0xsigd@0vjH<4fHwPOs2AmbZaDAq+A!b&Bj)m)QhZgW)@AD#|V_b!w6y;p8+7u zdKaa2Q$yqb?NV+!v$#_3;Q4w$X#;Be%>0Wp99EY8?6+7oK34>rQbsz!6(i_Ws&s^E zHj1t-IWEKiL3B$`;4l@;Bu+#aM-fsfBcl)outiw5Lb67_KRs>T$6RO;>SmNbm%zS8 z=NXt08Qh|%i6Rx$|Dnt7NKDjnHByE9==GySK@iKqk-F=UHt;nm7s(QtPmQxMKCm$Q zdR%)Z!84y&fX-d!`u4ZW$1aduPz}=oi-qT{`Gl(?@h$pM;n^$rGg38%Y@VB7%LRi= zf9gRDw_+A6k?(`?Q=ZI0=<|W&$B;__pJ%na8FmcY5+8E!HhV~@2nVi+Mqbp%CQt$U zA7hGct88C;8pPWK+!LK_yT%tmbx1k4rKp?y3@{poSx zp@%K&ZR6Zo^z}>f&3)pzoRd*yi=mUIpU&PWuPTfURuc?Algz*keB(FB909x4!BC|rWVj!t=|kr-Rp-eV$1ej7wP z8CYp3g*{dOEXr6&C2|os)8yAvBSKzQK@^ppK^O#Eb&LiEY0J~NVfPLQrG*2&x#OR5 zlR+F>s`Arh)_8#=ke|{xtilgTP;N$)u0MC*ZJj+`K*xydyRV0u9)UNxtv=MJztEtZ zX^C3XSb%`*T}o=H7xooCs3B93gEeZlL?IM!7)oB8%8rW5elkvv(K9v^->CaEJ;N9c zmACi&8H8EG-*CJnU^AUGHhz!m42&R|`o!d1rkQzL(}#4s7E(4V+oD0stWd_M-=V?j zXAsb1Kq}>g+=7kD4|P3e8dK$4OR3S?>8?EG=zq6@o8Nd>Mz7NV=hi z5;_i8aEo}@CbCiPJj^`UI^1M|Au61QTGVuW*v^QEP1&e_XMge*9oE-TOk{?}BwX$qAK!|)Q|S$5)Id}56u^vb;=2ZN+N&9jxh5>xJh z4t>m_66hG|5Fx%sbU{}Lqb7(j*PN@M2%cqI<@||XrJCqrb-@{kaD}6e@Oku;Ur1Ao zcQ8A+!mL&%k#Z*dqRCVxH{!@1p#^lkdYCMx`*og4F=DU##;A&I4D3;-52tGMeV~-Z z)$}jpn}Lh`Ec6hunBVV^lmFd$hb0Q@IZ_nRhd z?E>!fz`Oat70wE`?6Ba75>$_I@*CR;Cu##$Gh3pM@Rn(B02yb6Jf*ibX(Z(&qxqoF zBqqjv8xV3IrR^neM1w*OTEp^apIekkY#_p0_0+1%Sb>ALQu(CIE}AFzaV2wfh-{G-koxt5 zuGElKpH+}G?|LTIS%7VvIB;EwPLW=xhs0o}*!#CWj7tMR?l*RTeD%hkiN)v}$_}fuH1Es$v1ivfun*_P)LhJEPY3}On?(l%DruRC zUt>6OHXvefyK7tlr60{tBg~h!7}wu^vruPwL2R)3DhF^%hsjJINcK!~5P3Gd3v?(g z0fKrU`|no8i{TRMPYE~=Ohiv4V_$yvYx5~F{4HIt!X+QSByG}AkpYnR%tw4aCT8ZX zHrQgBnsBv}n`lYmJ{1(fdm^YvyUZR_>z z>#pJ;7rkF)KRJ9H_T+sp6-u`WlMSWJw-mRIe}@gJLz7}*gD5~sc_ym^nKUWu!i&5C zUTha#(g$gKCBgVDI=KdBZ$5;-5g$eI0cn4IC?LK@T79{5!SatXa1P6~6zd+a5_g!jeng%lj%!FQ5D za>LZMieCc_@ZG>;@vd5v+UluK*h@r=XmSF)w+YxfGq8_PO7j-mn^VbKI4WjGwqBQSRr&`(joDt?OUx$0TeLEXF>L&_JNKHDse)XX zroN-+Q?9#EaiR^P#iLphvTG_p8!Lf)t-J;=H(uh-UBK0NgIh}8|I;iv0if!UnJ|}o6YS4 zM!dHC)LoBsKO7GXt6S*nGX?y}vEXA!{N41KgUWlJ*AeonbYE`#MOURt%e4`tyW9~y z7s*i2tIB6}()FTF@74YJx`#E+DfqJyd2CH`CD2-6M_Sp7m_dwNCHIVrcM(>F>bkdI z?2yLCS9mIJdwT^rR~a1@nG))FX}&l9+t1pAq6e?ddhHL_nG*{1%d$mnEGH9HFVYUV ztBDQl2@l={mPI@}WC7_<)-T#EJgRVs<$w7Yh+f^g;yvA0#_2U_4|>I@z{b#V(vSRM z#5jaUuzsGgIS}?yVa`DM9X835^>c)%L&zzqoUlhrZB+gK!Cm!Y!Qys7#+{om)#A%7 z=KlTPk*yQxn`r;b1@gsu|D&226~VG~U*;euk8U1POR)!QqU#>miqLh;LBH%ey~>2^ zFxtUqXZ^>xc1;s>t;S zB~VE*XN56h>h})P@94~g=l1($YCwQn?2^A-Lz9(9!0cW@#&4zV*9ZrL{^GGAWR6DO z`IMxU)?LJe-6B^Ezdz+A?sljHFJoZ3s&{iw*r;3K1JevDMgRjr-hU2;X- zF-5qMfy?SdJQfnWh(D}F*}ZtmbQOfvxRBcu@6~xN91oR{7=#WLmy|fw4%KZ@8*oiX z$h=K^nAZPOw*$BL%QHUhJ0@S#OVmaEsoBS4e`Pg6U%S4_&E;%B-H$1~49 z(2y4$Ex%hF>=_Ux=40Ew1ozbI(HxVhw3?Yd<~@rRo1@nEpW`_cS`oruKWMgtJs~9V z9qMHZHfKJ;2JDu%*rq*7RDk(lm`$s^P=TEsn`)+WwQ@w{WyKcbi>(~4N)4QeW`#yXa9B(JXGhK1& z(O1EF*MoV`pVXv_+eJ^li9SvC{*Wb~RIijw3ZCsS@zDH5T0o{YI={LdTf`(<{E50Zdnm3~=H5Bhn9#%ZX<+VIDQ#TSY z=h1$0|Wu@VGT+s53pal;XoKgI^cBmn6M+ zRg&7eQR2~G4qDY%j2s!k(27`O_bH@f@VbI$`?rl56=c>tIPt}7lC{Pu(N|E}Wtn^G z{5@(zJ3WdBxy@lCN;!+K?^%My;$CQ3^nfsha`4QIQry0HG;{y*4yk+b4~`ia;2Hc- zYi4&ssr{g^SGa^z3l;ILn87hqTWDI9L#iJY3)} z&hshqf^b7JmT>*Ak1i<$G_F3nf~Uw2;`Vm+)b5Os39Ob&8qAmopD|G5s@-+beWdor zTx{=~J@8i|DT@*Yd#LrHbuEf+nU$K598O^5`>aBWx1KJa022PFWps53An8C{7Y zz{b1mdgO-k^1Sx3WU3|0+wzbpH2&+;@<~yf@If z7w(zQd*`X$5+|po70Klm1aF?T$t9~gPdKsDv&6zl6JVF`enco0|Ja_=+6D^aKsyzF z<7n*bX@ zrp?DdsceGgv>S)dc=B5`4)EeDJSs{lV1^aj-B_r2YwQ1=toL7&C%av>fdTf#6-wnM zWr^&s>DPtWfORtZNNiZKZH|qmaq=KN$3ufH{uO}OP79iX35ZUceXZ`QqSV?I!W8M- zYj|JYh`Px%n6=4;4iC;9UaULol+WjwHuN!U4|Zw)Hn`rw?EN_yCCItySg#yyi|li& zmCqqy$R)>FD5R_7fMZmK+*!6cj`hQqX2gvh_ykmI3q%FE3Rxt{emcb$H@>}=ynCf2 zALAW>?Txng!%+mfQ~x?$s6@N-b?3|Pa?kAXlfo4dAh3Op7y6kkmTFexAL(< z&l~lI8kJ#H$Oy2E#rsEuL+ju8n~m0vUVN{wZHgvt(#JLqwpPpo+)L@dYbTB_UD43M?qWoJw*H8l&r}O4F*hSLQPHioa@h;6nK-BTN&KWr8EI;-Cr)9e- zyD@X`yCGTQG;Y<<)^$Y$Zheog7cI_CL3TuI?SIbsHBf|abdA~P55k24xmv2H-XbPe z__cPGK^%NWo;h}PEc5u~7em@IGio0PG{3!|+KtPOb51`Xs0DB>Sf6VFwFT@)Gz(|6 z+8P}gMwWRd{2MRd{amcLE}Z)RIi!XxZ^2;exsESA?3SZ~^)4n>qNi%+u_U zfcbFli$1W%j9OHW?l*1jadi#l^Qs2ngPvvHex1WKcHoByFg?rmFJL zfqNZXuob15o00HCDF^(23uzuuMMfD!c`V0Pju6n z`Ss2&JXniMg(gi&v=DS_6}dnXvy*P3tB{X+n7A==M!&yL<9`8;ER@c0kmol~LJp8W z;;6koO$n$rlEV~lIJ61IHd-7%cR>!_@+|28B5q2Hs4*OyM(W9u|8q<^xz#*UyYc0V zBd<>%7>L(pt7L@jTLFAHV;BI|xBtw)`Olo2f0=A{aUG|sF=$mAgMpFcTc4|IYTWIA zR}oax|HfyV{kYn^H;}mQACdz3KO_YsQqH6vxTnNGA}zky9NDFw(R~b4@E>#tT$8GJ z<%aEz^|L+mf0!Zy|1cR)WJU3%9E$=c3e+Q@Rue<4N0|3QjKdIWK5#r;Jl@IJ$k zaIWI}2>wDqWR!B6I+8gRM7j(*o{(rS&E6`k2Nz=)IeDyV71~UTf z{7YpROMs{DneW!nxxZwX?&THwwrDOO;I^iP>cjRQC`5e&{~O^3L98%u996b+O;+^z z;#a}3No~kqeVe*|C<}x~PUoj@xR$JspQb0zyv%GC`CidJdJ8w?3N)JVCLG+lt_z&3}>sf8&9Z9Nf)`3k=h*urx~z%yrBwM~ZG z779*J79Q-zRk$ThY9*_?>XK@HQ&vWdx@(1EW5`YEgqM0MU`1_eFqBg4Ul%BTuU=Tn zlphRpM%?w{(WnDaOznY8vb?=L<5$&HK4iVhD`O@3XaTp6>Ljq?+)tXn1Q3Rtp{= zFD@)k?wlih<6aOsV$Yt54H2$0NXFgJx_T2Ymf^koKP~GWa!4o53{$YGQ>&e=&FYQy z4(kW2NDbhD1OUdj(%w5hcjWuku` zIo=pt_~i_#`zxs}KINLflelwtbew2uJ8+!42mpewIV4?uE9`#WoX@qisbW+Hh&HRa zTg21D-5e+1RIBU4rY6LK-NcsgUR!|U{`q;4P7&FHuxfLXia|Y8p3*!#|-2sQHeu_No8t-lhia+ z+|*4l%0};9LgfP)Iekr?OeQGFCn0#`^X&YLAF$SpU)rjdj_Dkk-n@gzQh^n*=a7O< zrVr!?WDZl(euApWgJ@z+(t>**%M$axDim-P+dH{kDY~C)osTydd>AwpXm_HlcGae( zO{s z$F`?7?Tg2x_S&qfCEql^>TlPxz53ky@o}yBU*HY({qTSGvl^@zRpx?D#ISIr@aFmd zDi5vXEi>V&H=r;gyugjK?Q5XlCwor2Z?*k5JHb~{{y_5Az zS|*$OO{K(eU|2<`1A(j7FF54GfPqNQ!S5_0ZAYJgb7|3wdixuqiZYc_Q7)?|Eo~Ed zwq-|-zl+!s&|122)sF7ZYgf z9}4cCSstO6(SNTcT`QeTrHH&Sz<&1(yfo*lv~C`rOT&}g@O- zuDbD>7~?$nC0}N#;OCelY#;CXoh%yEBmYj=P9xyguC`B_$~0}4yvN6;76apOR2Ipv zeIr*RQa{@Y7lOvFch-l;)E*^vD6yBYr$!jGDvYO0w*t7}R$qEQ068nUpp&|)8vhe> zkE|fk!2xjiopE;Z>-(FTw8QuRA9L>+)#TRw z?E->QL@5kOLTxFARqijJ8R_ql1;k+w9O1r4@VV?9O# z2^b^X$?|b6HA+8m@#m2vtqdY0*i9##InX~dAyJTjBhRU}_Vlwb5tp0! zxoBY)Y{5DlDtH5-U4Ox88$IGFObk;v)&1Od$0Lfzm#b9Yr3BmlvTg#wVGw4zM>Or; z0SQ!$_|P7Vkmf%Goa&aSohIx2JnaXG0wbDF7}cs^ zlaoxp`M?bL$}uC~%~!oFSM4XLGgZDWYrOTD9!~U8gXIBgsO0gJOg5iK6 zRFeN~wbT#L0#I7NF0;mfZNSr(Lv^C?K@bR#c+}Y4qT<@l5U3P@d=aJJY)zIPW@BS9 zBK-PqH;CDNE0W3;^Fjrn0M$1Yi6P9)S;1c%AviHY5ULiDa6MP^BON6da){b{rlfKT zHeo5|mb<-MiMFu2X4-utvZthjq=2+7qSeEqSP9AjRMaecI zRdvyG+8bK!>S&u&@AUI`B|f;TBC?lple|SO-J=QKYstNh)%u_Ji#!w;bwV8}hne06 z56+ei2NS=}Oo=%88fEysPo^F^hZhLRedLVWmm)USL$#+ZUlnKX3aQCZtVJ$}Oiklk z88%8|EbJR?f}IY+)=BZI{ET9-(U5hq%}@J7kSZIbS=G3;kl5X9H}*L7IPrbDD#ZP?-#&1f?=aSexy z+GRdQZLR;f7ezV#k!jwEu4|Hk;7bN{^VnDxh4zUtee2RP47OVhqRT0;IUx*#hp(B? zFe^$E*ep#+uNJyk^mr(_5PSEJpDF(BlLVy1Ejyj7I=lJeTGJ6B0>#UIf4s8U2yf=l z^GZ5-N!=u&j*&tW(X;cn0~W!mW{L*s%J|-oJ+n6-qL4Ax9IcxM444TR%Mz}wX9^JE zO&e`8R+d=?jxhAmk4BLsM`8|Dv)NdDssy)58Bv_z;!;51gJ{m-^x=e09~ad$ndnPK zz+yngC_oHkj8pdbE1-p*`8IE9n-Xx-QSA<9;FAzYXWvctWOf~BZ{7<>T{s00fe)J+ z!L4Bga(O4}z9?BZlqX+;m7+}uK+Cn+f|yHO>*_Oks-Lf7*n9-h`#Pm_ zJ0lPE0QEt>={Fbfr1Q;@zy?2hpEG8!ntjmd2oIQjAI z`hU5UpIbkK-`$eTNfyU6=>9KXb*U!}Z2(^dlG5tGTo$r#Hb|AfpCr&Q1zp_U zzQGw^Ou#?4vAmWi9kZI0);v7XKIA% z;|Ro%6k^EqF$5xFWUWJ(Deigs{+8pA_Apx3ka^6I3%HnrZRoC}%ewk3gP7|RqX^`m)HzY_1xDn3QhQSgC!CK3c#862d+yCeDoMmhnmk! z=h3dU)-w>nU@4@|FSl%An16+WqelOeOcWkDCs3bKu zZa$;cY79KNqZ|n%4TeH16W%ZofloBRmy`%~JaM8?H6}K|tI(#!!!UPk5X9Hhf`b%~qERRdGiR+^ z&%<9ybTY0Qh?uzdu~5;b5c*^0(Q>>u!3a@5J4f5WDGX?ZYI3n!s?r3}IhzbC zpa{a`op00+Vpwc#cLic_l6h2ZVRZrz8wWFQekg38#n^I1Di`0qt9hT*(j3FFm2s+o zN;-0Sd-7HiN2{=a^CbgSHY5w0#}xnHuA>zY$6sfn7@xllA@78g*cT1KJ3$DP4^YP| z@XZvK>-Xi}KB5>sJKv8+WCT?KI@v@yr)t~4`iFz_?u-TtK>yoR37L5W;rwsMC&({* zo{IeVjO9Fw*pwz#xCnT8Fb!S>nZ zbDC2(jp~e=;C85UbmiwzT(SWDy6n21%u;BcD_^2-hb(+zT@9{NOs@31%2IG+GY`?Q zNQal1Bo;^S=i!TB4Ku}>X?qg#;7Q*@JP9Z#holm5!~@8xN26Zc&97$e@HgAra0~q92l{ag%^9HkB0-QZ`Byn%+|p>V*07fSlUKhfOkt5Cc&A z(QtGy*et^rlTceHYBBvQk)M-7lF-t?(EQcIh^k_BSXWvigFTtD?4G(ay2?abZt#o zD;MuJOozPVf?Ac_>*}WAVO5ic>5l|~=#a{q8$_>E|HY-ySR7wESj4FWg>4ZR%`LVpw6*BX)P_ z!QeGmZ4~q_Y0Bv0u%(lwszhjHrWxkN7Z}WvHYMKGXuf7J_Qu_591kV?SWxqjqQ=v9OaoI+M@#e8ky`Ni3Ye}vkelXypc&J@A3~5X>CCBvH z`Nv6*gi5?{a~6MK=ITfnP)e*cs;uXF)w9QIUqWquX>QcyZSBku^8pfVRb=fdCzkM4 zsb8O##M4?@{>-T{PiO;AY}IMBth}{oA*lIqm_2hF%jQ&#ntA77sf7jx2N4KKg>`Nb zKRE>|4v$hgP?jGPq=0wXm{D=De&Sdg*Meg#pgw0#gY<*KT7ei14Rp^d=$ia=dxlr| z=H`!KgU?Jc@1uY*7!co}L0k4x=1h0w>PgUNlMbYxj7AeZ9_OsRZ`u!Am!9>umJvKZ z6wX8q+*jRkj;ho#6VXoD?EIC_2Mtr8h{Y9^Y$IiXt2p53RBC|KZsdxbiTc1EEI~U2jQpXeu zP>xtFrhHskuSdMaM{QPQpaBEA{}^;hWcH7^W0ME~v;B8DyA=As2ru#{zY zt2Zr1hWub_?a}SD?dXfzPK9b^d_Qc--QC|Hv)7|lY7IX8;-<|P$lBx+$`n38M*;nEdjy7VhziN$k{vkK=)ainsWrla9qBU1J`9P28=H^=} zj(KR{(Eg}#&k561_~X%*cI<&7!BM5)mb-+r`~(12VdUNOTaeH-dv1- zSGB_sejiKP#3r%-8n=e_?mEM}u7I8F%N!Q6fB&r7?pUhC)oXZedCvO{-sVZ6EB!U+ zy?=FYt8Y*8=B@8_)fcZo%PxGBS*L1=X_dVScKgaoJ5(|8tVQxm#ks7xyY??U`n;gi zCR2Ss>cRb~SW_-&;pw~c*YCZNxOU@`Xj$YXoo(U^e^?a5=kIf3UGCix-Ws_LvxdGg zeancZt)Nc)YHu|eTf-3mDc+|0SXO+>=F^9;p0#WZun$B7Z8er47Bu=8q-@d#!GnPy z8kkIWN}E$=&4vV_O<}Mxba0pfx)N6^T3Ch$Lx8DeQDdfu%%zo9lXuydLYs&-kT1@R z#YCWhM`)-$4I_$AkU$--^5T6kFz`+hCPodj$+73A|81d3)38t}#)Qk*pvWMKz)&-0 z!FD>EmCFg?Lk^-W8~U{3MP=Aai)v^dWB>JE33nvCQkC$Zoa!&zxqfmV=96r!U9kh&GWxm%n3a z@}SR9zQvT&s-oeUb(5KF%dD&^4GkR#<;`z^P`)DpOOo@c>-EqIN5Uy0HBqPXP-{B= z%P4edqQg%8ZAmdvq9`ATb|bgseE%1q1L{z{*RiR{07kllkqwN@*F%eZ>PJWf7nd75!UrsoTY*SHz%RT>=c}RE6 z2M}GH&~`De7ZZ$A*$Aw5&R{{{nwlWOT@=hP=Hnn0TuNQDXQI~LPD#HoAzx;)tPGFG z7*YzVNtKMO5fsIbq9PInRdR(hlho}KOjF^o?NTUpB+Zzqr7S|>;Iq!(}PZX{?s^!J@QOBC7^wP|!qGAaGliK-3XpFF=K_}X*@ z5YG^Oh}g~}&p4>AL<1jVlR8y7lo*n04S&I zMqyi&@!m?GtBk;dF`l4vzC%>TV2m!Xb0BmK2@Y&Td$Z(CJ7F{!(IDKJhaBY1M)@1g6-DPE>Ay| ziJH>bb4##MR-yO}PUW?LkBK*i5t=dyO}YP5Zr(6*9m!1Kf8%Y)6*TmxPDk6IE=G(k z!wdO{$vJ)OiJw#uWo%oc{}ZoU@UxC-qKBEAUS-yPUDm?zu%4d>GF0q;GSmWK3Wwz- z`@`jdMg;UbpRCYf2U|+2>IE&hEON{n22?gMkpnPj40Se}F`7~WO<4!LHuVeZkd250 zp2&#ayrfQ|bDj`!3md=>ULQ>%$^m(471NXq^W(qsQp=c1n4qOX;+V~zXX+&-jw?6+ zSB{D1!Zh)N@jgODZI~B}13o|^2}`b1WgSLV3yy(697Lme=-pihh4p+cunv8Q7{0(x z`%i+2`oEoj#YSNa*XT(ChP+u3bkThlrMKoEzt4JrFh^0a!Zox;P^>WPC`c~zrtH*p zs4M-mCaOOL5_Lg15XB@LMEPWFrEtm7sLoRUsgL9{gAaiCyX1Y-M?iQb6Nt(~{**@y zf%z*y_-*vST2g8N*B|=~y7}=LUS`@^5ExJa#P&9;9;uv2nf^$=5cx;=VKx?rHCQZS{f#xN;4*xcACt_x|WO9{MXR^av@Hd6wrlnSolh(WphBY{6uVK29XH{_Xl}OJZg)nAf{X5y^_&_tLh4NkZ{JVG{f^j_hT|piJ&7QJKR_%MiLbra2vFC7Yo#<4i8_gsc-J4ng&xE*=1kO z*NQaW&>1XgzmvEpFV&IR&ZFLVF>t9@_k{ZqW!i}b%7UF%E_gXQgeY3Od>>jYFjXk> zp;WFGi9qT}f7)3Y^!%CmelwQ!{jSUPRq=QCu0toMrMlnaLoE0FpBE3we08v&yvB`kxDVJukk88i`IvX2@wiOYXKQ~eXeCjL%L`k}hZ~@P1uU3_(&iiv-IuZiEst#K*`1Y}#?bi>HkS1> z9JK1Qb711${eB|!wfDYKsvvFs?~N~4UV*5vsXR8bY;<%!4nMvFU|kvOq1?jz#+9ss zW#u`}R~A<1l&}#h3y@mV{>ht<`yFl&MV~_^?44P?Q9@&7nURFGIv3vYK-0ac^L_)S zSNdMx!^?)->ZcJ&rn-4`9zBA!MA0ZPO;y8dJif9+e%SbP)3w;i)d1|0SWv4vm#tHX zPA+{4+V?y8vAT`cZrlp{j6>mR0lY>^o`Yz7z46J*M6@44#q|Hw_Vl$Z`b zCUY&K(4X05?IKii>!v%Meu?)tV!ON&JVPx5^kV0&31xvANry7@vtHA=XZn?(r*$-$ zr?=h93xnG3L|MmPo1UIJOHaQ)zkBXy_4oDzwhO1c2rIcOPi=o2A2WaYM4WIBYwUJo>g>p7_-Ko_)Y-ob?v3+ky6-V{7M1mm}a( zKk05N@J~A9KU;r18<5)kX_sR;ZX+q?FN(@cA-_)^Qj6t)o}I><_D$jhI>+;@Th8rx zXXNx|oZ0wU(ww_z^;WOVPCTA+a{C>p4%{ia zgl={>IK2Dp^m5bFBAxn`^0qP?Vw>}4zk`&&C}Iuhf$uQo-RbBrlRBrPfwNl{)~9&v zwb^s=F6Y|T|Du?BM{_m?{kGYDqfG9H)M@I}Ulat=onk+o-ja>aPgz`n-^0tXlamw= zwDqH^++F*X%iG(2XRE)1Oz&?$Jbk`bxn1sYR(s=kKaS_lWcbo?;nU;$F6Gf>vgjn| z2Kv7hz`Jr=AN@`XHvWr3?dQZv?QZM6%T0H78CQW3^sbDjqwcs`H^p|`Q%S%R?$sY0 zMNg!AT|0#KwhxxKk7W8dU*0MKa=g{(Ys0ZRXNxllX0s<2Pp?T*oJBplGt(^h`ub0S z-x&Gmv(~<+ul4ZdnlJ8D>)$$i;(3;2;j#}aA1bpyZf_bjKgi|px>)(nB}CKik#=_@ zFk!)FvhW4IqtU~5XsKyKc+Ww6f}@AVR81ttcw53H=G#Y3AXAkdU^lyJFx6;v>oXG# zudkAJOYoM1g%{%e$R)(%XB>HDVT6skh-<#WSGl?`^s+w_RK$Lo^jT)rejOZ^+mFRJS33)NCm6A6XM0?wXkIfpbW=dzgG3GLK$An&YHQGP< zVwMoD>o1Dug4KgjwbxQzS4;{UqKmf&>*)$DO%0yO9J@4}Tx{FDr<94)Aik4}6$v68 zJ6_ff?~!P8Y;q}k##U?96e#w~rRqe#X>r=WD_qDVvtjonk4J`sHzw^|VYcjOR|xzs z3IXFeDCjz-g)JBq+@qC?^3&vTAc;yU(*92eGnN~!{fAiWJ4`y8Wc6*Sdgwby|!(1`Uv{NrS zC*8O8_yDL9!hZ@b)vN$58T|Z?ZFP^^yzM^ky0JIvqd4dYrshEfSJi3w$Axv{&0Zgw zjKMj+1bmWIg-Ax0ngz*jSai61&UX8Ay-bWwycgpJM;M!|evD(++CQcjkI1btdvYS{ z0k2GL?GALWu@;~%gNg*V{Q!E^9|}Tiz-V_^|ps(JMpB=U#P~3mnP}?q+~izj2;~;G*6W3!FRvQQ5pWq zADCPj8HO-NToL!avpBAm{j9_Ld>t=@WEvVButSNhcOJpY^cK0yO|8_s(*q6DaVJM$ zI8Sfe?A3K-9ef?Hi)}h(758qM%BVbkL;lv=#cri}xU`~&!)Sf8Zg>h_+R^ALl4mTa zvS)wj*jb662|X3Sw&U#g>Zr$f+_``|JCsNI&Qdq2h1}_?+N$%izdjh+`f!SLhwnY8 z=LdrjY4OP8Lh2I56W(5-4Z7iXOmIMe_WIKqxy#R!e!fe!n76NK_+qN$CQ_@UE{bWX zZ!i%LWr*ITZG6q#>~hc1IV2AiC!cJZDDCf)OAvRdwu|(_5P!g zb(GHdt;wf}6=@e5Ihdy&ew0rcM1T0j73;~TiQ-CiyRNdDX>O~)^`2+`)kELYQY|xH zTvQ{-<=ouo`(5uY@A<`I6YRMixu4sAyiqokUmBJMj~VQHcw=FQ$;;=2BLW{?5f)jR zv3@V_@TjlYHrViCylsy#*#2-U=}IGxJ><7hjdt4yyDl{KktN1sf5MUhuHS^N{odMp z@|16y(|!!woYq^ft)C&^TU`yWhOafXv&tMJgA~Ts&pZ(EpCZppx-r9?ULRaNXB27B ze!CI(gmxj2VuHDv|3m0q6-ECGJT)+rESVYjI;y3Z8^K8%!KDV3iR zB|;$MDOO76jM_{u8rhJZ)Qs67y`G(dpYf{CgiX<=xKXo3(sJN zVQ&F}JhSnqFTT8Q@SJCVo6D{=d8?6&_63xc6bifVA-Fsae0z!SN)fHRcZF3SXyMg~ z(ZkLkZhkq}KH2es>{HWX4*!r%=}|&aTpdP^Nfga=5Xa;9QD&!#5-f!($2aVF@*et9 zK*=_Wtki~v)ZQSrVV2MJEw!JLz?$}*mxii!_#{I3whckBNijTFG9$ob>@fX@oz_;9 zdU>=U9z01UJVwm}#W_YsuivMtnspdRd#$pNm7oomYl~wB zB?tnYK6S3sZJb{*CpT!zA+Lln&&y~$Lvy~Al-J6oWF}GsqltDi5lcK%0ZO#wOLy?T z=4e&NIM{>@kw`nSLQb&uv~pO{-9h*Te*MZ_-ov4|J*XSDw4>YW^*ZJxY+|6+)ao{e zZa#Ab4pw$B9&Xy)x|ifn^)0AT!KhkaZQ#-DYMZlbR_53H0ls!6dbOt9A|;=M&?7+A zY7@m(^kF^AeuArZg6?G8I-$Rz-}_aTNJZ*NW}>xwD*Tp+P(Rwb$fxXl5*R+c0ychM z0$I5|bt!R!=qaqCe^u%;QD469IB-{($7%6Q;{D^1s~CZ$8K-uj8N*RSWc~6@_KQin=x_F55RZR8+dZKe-YO#jvndFR?>ABJQ(e#~Bo%lVW6y zp`7nSTuReMyCv4`xmm$tgMAGL3F|r=wRA}4DWplsV9%eH$ft*3DAi`kFL6zq#8aPm zJ?sSd9&f}jo+f8*)X_|4NB{wkKvYNa(Fzi#;Fd_|%$`YXSvmk~%P(R+l1dh{lA`SH zX{fPHR^{BSvm>SZraMp|V&mS77J1;|%onJ&&}<;1>~z~VjfzZtk2ghC(_>e!Y;Ur) zbbHG9F>N1_y)(TNDNVXHGh8(ed)a99kiZ{y!Y{`1tc{MqcT#=Km??D5%7eygk4ZsM zzk3FE{o#tX1u@Ub&yYx10vj8fEYZ0)Ip_kW{zAf!fi1M=T$)mtQH><8IS;Cz5kHv(g22X9vK<1zaT;Z-vHD71bZ z-d7^tTE0DgcMCtg(beJo3Kv8#1aNCrB4+5t$ofl+-q!j}Ou%G88 zz%JRNK`FC2^<~9jMSt2FjuhU8`5_G(vF&_8K=n3%aItdLnhQ_X;H z1nWj-%DE;>Xa~vuPL5fW+c{GASd~ro&MDq3nlSy^Gvmsh;Zhb$EDz34%i*2BW|P*& z@Iu{TD)P&fgH%vg`OVKa>ag86n=vl3iF1=%SVi~k_zWzFWymE+_q@zw*E=@vcOyTl ze%Ljat>o_B9w_v7WsL2ni?%0Tp$`cJ<-sv5KNzvkoU3&{ltY_o!c!I}x7gQATx5jX zEU6@j6IV;2KRY1;-)lf2tiPk~(`uQLpJ3snEv`U5+BdfKKbmCeZxr0jK;C4td`%@n ztkl{2B-$W3wLEdbQ_1hlvzv$gtXk|%zt*hK7 z!w+;ef47HRfGnhoa1RDel3JPu52`VwE3td=aZMvz2q(d3a&yuA@gA+F+f*o}zF|2q zsr>tfqIS#)jn%YbmI1h)Vagh!AowaSS*!Oq9M7*9YmmGfqNb7@( zE9K|q0;-o%HhE^V>gjvl^fFr5nIHC>>@x}ZL#gEWs>>)KD$J~hik4b-}e*C-!t^}Q0wFN_=)I}?|vbVU(oz8x!uP; z2kYJ0+a-MyII>%V_K?ra^(w69;=jhbEQ5G4)>@U6UQ%d-^9L?a`%L_>&2fo z2ob86uHRz)fD!{Sa?4mPMmwG@?~jHnn7BT)Rev``nZ2OB>Ej^ri7pDNR^r;LE}&RZ9%z`h zw(Ka>giK-qZT8_DT_r{jML`UCb$udaI;W;Y{irXf4=ilBF6;MOz*Hu!O3EDR2Ac0V-bvZt&SI!c7+_(I;s7VFkUC+5d+DedTm1 zJ404)wUx8+>?pfpNH*y?T$2L*RAUmdf2X)v%KGeB;Am;R{bUH$B~9DCLa_qv(w@2lihnBRi0 zOpj-}uTt7h=$fjHy7or$U0@i@Tvd_TPD0*Hd5!AgK>erZ>~>-vSwAh}AlD<=w? z!-OHYoH{M>?Vc=?s1Lo>UN+Bee8%Haa1b01(&&xu*VUS?s-p^v@I_}?myAu%9Y1}p zra>|`?MJ$TZTAtO__>q&gk{Rq&hH9h=|BX9T6mY{tF{?Kx?kxp;!2qW6=tGFeohCL z^Y!>3^jE(p^cgceF zoC8B)5wNxdyWB^WZ#Qj1XAyJhHWyREtB@B$VvH?ebPVw6oKo?FAhxgp^HinS-4tuS z-5sekPmaqoQm>U`SAW*%Bi>lhbTFy^ij}rMgI*ta>*d_n=Sj_I zx&kJMHay(B1O)t}-;^j9SH*sD1yXeLmsfKBs^J>+4|Y|(502m1A}#V}pB&7dL;vz+ zLtlK+f_dgvL4Fr}=f`Dv%Z_G2`})Zg?U)g%mUBzav3JX=)o+8vC!PRP4iE27+(qtW zs++H0t;|RqwY$l|Yc#Bj9;T-2M8h@@;oisNq~zV_oo5{1k7t(km1|;_WRkdT=NoSc z#$0l>_SH0ZEQCezU){Dnyz6d^5p^Wng+g|f7R94;E?wF!iwSglxn%*Jk>gJPip(T= zJc(mB(RA13!sNv9>`b^0y9mHOU$>(`v6`}tz-9aES>0VPcVHE{*u!qQRX`;yJo{@v z%htl*u+@O#?DiJPyl14)7mCA!Ga8&)jqH2s5b^JgsWnC~G+?2wlI72&-m4QMfqO60 z0%`A*^6&HKU_NtmKPDm3jnzVHrKK4}^x#0YP+6ed+hHER`W6yBeg_j30D%Y-lfUhW zXgkj{ewWb%#{EfzmNsXCt$?OjVv)(}%-5UF&&29!c%RnK3SrndykIVQMA72HT)5{y zwqlDX<1tZo$109mw9~Ob*XxRMaG!9~x|eQg%WIi1BoD zJdL!Y3T!?{gizuWGo=3XbJuAwv>e<}Pbei^B23!?Eqx{5oc7UIB=<%;=r!<#3MEdl z1fp|pYsoO`LGveLYB5e+{6==MLNS3De3%ROIjo$3d(_@G!=>?qZ*r9qgbBli2Rg*r zf9$U|*;dgrC7)-c23P?cm086P10(n`GqK+3hfUk$4M#A53INTNeu)8zQbWlW?Uur7 z@%H&#P>iuWG8=UPG5VJ5-jjuV-D)0dvyLSFPGs z*wyIr<))0(C5LhA7mn8(IWB1L_P-+w>yV{?zp}C#sIYL@7m+B}uiK?vjL}^2YzciI zyy)vvVf^zRm?ZpGQSv4y$d{Yui%o-tNXw6&n@~=yLcs%uSui3JCz|ma+%#$;@=|i~ zc~JL9CZx7E#WnQ)&nRv0^^uWr{8{Bu-1>{%c47ZJLA9j%SgnSq7c7D#)i3+Jyv3Hf zcNN>oPfPq=td{y5iC~RyP7zuQEiGX=kogU?cP`BN?d?gux%D$H%gy?2?nMis$m^vu z*4_0|S<6qx8sAc(NM9{p%{=i6Espiu1^}FbYCM?=P5)~s0BweSWqyDY2h+MSHIgH+lTAdHP}L+%J%Kn z&**_j;}q$;}y>KhTll@`f`OeuHX8~ z&1{koJDo>?H3glbeQ_?MEaL=h#_Nd4RHNIB8)YT$VT;bhoNS+R;h@&XO9DT-XGC6B zaFDng^F3cy_%AnRa{JzR+bvD~vEqfhk$}66b@d}K8I|l~DiZ2K+_X*>sh&9RFt=p2 zuLOGBx2POUwc4MWrnK$3tt`yoi{ZMdk8W@D7m(v+aDAAg>{dlc5EGw>7}hl!FJoR7 zG*M0Vx#g2`&Qeyur-RXZ1YwBQJ%kkbW(zBY*cYf_CYc3+|ASgHY#XJ-T-qYHYaf#e zKP&}nI3=l_TWV>DVx_1vdNT_Ln$}TkV%D#}C5;qzF9f^)G5u+t*pmRz6xX3=;$uj( z3P>k^PST5iMxgs)2YZ%N;!Tsc$*6g62H;lK8Jw)Gi3r~zHR~zh)}rz2C3v88VmADI zI$_Cn=GuoB=9U+wU&p}FAn%E|A78AZiBj;&Ua140IjHhl3osIW=v{nGG8+m$Vs&*n z|L<*L*YJ_8YWxW#bjbz+DGiGxF3|4_qO79PiuNBY($z->`Kg`}@f4R)2;)+mgj)@! zp+8B~%)f)rPmg_gW1y z+bEKa1IcPu(&HZ0oh4aVXxDTGw`AD^3n%~Dn9t~Gd9xRbE|cpKRBPL-OhoRwbR7oZ zT5VmVme1cLsijy=k6@NaQxa9o(tOXc-Pm|mR+vFo!S$$&lb26w2D)!s-^z6CZ)w`g zxxl;Jh+W7OlYbSg`}JO$jLA~htC%+f7)bZ+G~YE^z7f554!3Ohz+%&O&6BYwYl_J! z7Csk_bSR2Sw$_dJMjv)Zyq4(`#}n)*rYD3rj^_QI4GmwWB*Tb&sIXB!Z z)ZarXueEu~@z?|=rC18S)Oy_tT}k{(${ZW(w&$|!bgJjXks~aN&DqG-L~G^~ktc@k z7dUNZd|p1LTO7w;8e>aHO7U`|-(8jeA#~>D&exUf)3$0+6uWZu+z-i18sD;fdE(sc zSGn))rcoIZ8NaSbazB>5VMG0s*g&K*TVqW9PiMnTZaHKBJaFX@g+y$w`ZhIa(=7a? zvU8C^E>kHf=6m*Y%C22*ld(wKk=GV3v6EFVO~}a|Z(!FGx!4C>FEU75;6DYKWg)2I z`!8^LJSoo*`C4_{b@=q^uC-5&_uJn_?;4&^ELkaaH;gbe+bD5_+uXaxJK4xQ5<#{Y zEKk5ZRwjOWS#&t>pHj6`_)cfRBE$d1#Mi6d8bwY4dXW;!Qb!Z4y&R4avY0*fa z`dTucEX%xf)2=(VGWbOkBWAnqWSW`&(spKBU%+O$>)nNe4>muaF0%SO*}pS4_7?m1 z0S{MEQALvLiP&aE-EqJZLkkBfk|wF;?=#oFkj)jb!G}329+P=HQ_Wi?6-_|twywiX z9Ax+O*69Mq_e3vvKQ5kcXZzcUSaH*)MWr;4c2GIeoPr8u$cWTdk&1IY<=B|eDfW-~ zl6uZR>0$UwFQ_aSMrLtK5zAciw4JJX4O^uxd|y4!{o;0NzK$WYC+pfCc1ND#%Z&;O zrh~sIJU_WuUsfKvk!f{dh4%u~exBL+p~w97g_=d1-;E!3WTj12)d98V zPl?;~>kj^hWdEM9J%l{Sjl+M)m50R5+e4c2jd{Z_Bxva)2=jyg4omK^U3a@mJ~h=J zpFdS94{DuHvexMwJ38>%k}6A8a_Kj3EgrHNs=~CnzgCJ^9L5z$CDliA7rfL6gkJE1UO7MQ)$L zZ^Xmq8O?Vta?e}3!#yN&6&inV&Od(6v&=wJ^Q`Xb9(I${tCagttWiI0^QkE?yT(=c zvdksz_%-qOf?u}PEp3#yl`B1-I=P87lzjO8C{=1^^uFKApPIMq{IieP>c2SN*HG(e zsR^~@yYJB-w8U?2AI`NDQP}PDYtK%mI;JLQlv*~ec7}e1r@J@b1@qhyPG|6i2{VjJ zzF>4JoD;Q0a#L%$4v6NlD z*zk9AyV)u49aF2-n{oE@)STE3)l15QhCrj(h?T=K{!cIam`jDFlqv1V@{N8xAa@js z8?h_JO)?+wqpix&;`w5N>XJk~SM=|)I@4c15ue5-g(NL^3sXlM-bo7m-c0I5pIJJu z9B+peE!T%Gw-vo@N!0x{p+bWEMIqUoBv{<9VeObnWnDm^2UaAUvx?V4<%sdpk`3U< zs9GdjH-~k}$ogyjU0tQ#uQ8vx3>d0xJfhFj3EZfgOm}G)o^s(Hk?pyCF5$NH2{$!s z@Je^#a}Cj=*Dm)MtcwD}>Lz!mMUryX{V&(QsH?oj_2&DTPxUs9RW{0w_{ZecH)CtWI$5RGW~K?Mfqk;Yf3t&6n6 zP0`02Odk^$1id`iUg?L#kQA^RxlEzV2ftfg>678AlX8q_`H|z%2|Ri~1y?Q@BVR3OO6JrZ zpMBmgK+uEn&Z1#_FY?X;mJ^rZWB0sBC3ucb8lo^U7o%%nR{eC0oC=o2u7KaHVhz|9 zN2Nj-EbB331Cmg2#<WOY^)#Z4?r|%Yo(pp+lbXWkYD;_bLvP zJAE!MU=Gw&k*D7;BV?_0UN=H@%s5|3I{xDQtQ>RjM~{VvNC(iF(}dn?qalE8(Cj%( z*mA3gm1p?AZK(hJz;w-Oc}mRD*|4!-`H9w{+=M1K%}?J_5w&9?OTC!WLmS7|!X)Lw zRcu9*(vr(}QE{g~a0B+A;f9!hh8sNo1#a;DSGeKR?4#%3DBAO$SJ0L?0lFb$AX$?! zKsTi1j!(|z7OJz*OAX-cVpBCB4jnTG8nPf+r{j-RzB3&EP4J}uhv31Yf#yEF%$4Cr zX)Zc53KgJNP~blufv^8&)=)cph3|dx0os9V^e475tUaxk%!UyBvV{d+N1qRkm`-q} z0;H#NN$?Rs@afOtguf31Xarh)cp7D$Ow5c`KA^$qrujAb`mJ2XJXS6`7jxWgg4aqdNB>d|Jn$A=Vd*5c@9BceKG~x**(lFtpHyeUbF?uWx zxMsR*lT-%tIY;$KDg{VNZXIl*D6m#PNn#=#$jPy^Ku*r4YcP#>`P}x8_=ClDx!XxO z@yr%1>||yhE(!pE0BF`qo#LQxcN*)P6x>GiM}jkJPd@>IW38)4&?8O6vD38Mh;MG= zF){V1%q0LX{k0dj34YgFB|I7hg#yl+ z@%w>JHl*rl!$8=+JMPF4fd}i8HHrC-(Pbgd*($^nPVZES#6qq}1DP*;>~9eunj!=Y zP7?r-&WAGVBA8^p8Fl{xeyT}2JYOxLG%~N!$Qs}FAzN_!KSp+Z06_+0PnHF-vTf+@ z8?p7-lANk%d@kL+BrlOcnsyW=3o3*};tphwA!f6lfPTsKriG+OGc%EsfLfijeyJ#7 z)cL>P&>!*7mHfi1xDzF_>gQg7z*UTM-`oJ>a+!+U8!U>eZhp;p;_^T}RGAcwP(=qM zIRmfF@Xi(4s5qGsvN;tiXuHBss)h>-iVwOiwc9#bNOyhHO@a)5HU_ z7v3!vwg!psq@glX^c08pBtYhXr1CV_s%*d90Fenu2+EOx`Vc$1(~xbZurECja7Ux# z#FFBV@m+0yxc`diKivP0k-c6U;C6%{ZQ~J#9-Dc_!;hc|c(VH|8b2}VVr#&=N81XC z*&mi9WdX#$1jHM7#T22+;RzuAl4CptgoCvxYwSN3i%$NL@;4>JrkH#81Bc>4bvyu0 z-4_5LI6j|K7+y853JIoVKqW*SDLBQ%{*XC7WR&mD2v9`Q>?{_w#yQ&^`r8fMknmJNxWoepTAHBw=_2|s0_8%Bcy4gqQVb8?&c3PV}#&n&2= zhBOSqwV9dAORw0Wq0Q*;t*+(qo+F!8QwVVxM%_|beDuk;wKdD zHTR~x&9sb(9Ygw~gPB;Z@^YF+744>^IWr6tThcLfb(53ZXpUslFO={Ny3O+cS2KwZ zb|hC3{+%y3M(jQxPBY@}@}s>eSS3)vm5)xzhb9A0J>QR~s`HL?ih9L(ecD9l7(9TY z!i|?KMH+<_9nSLHYN@k}jgcbM+OitMfNT$*uv?Kdlf+Z=)KG4kN`FMGG$~XtqrefE zl{t)x^lQ$n0n03Be{2?t7=U(CH%TvK1S?@jMW?>$sOkX{uj3Dr;&Kp-Fp zNDEDhQ~?1YH0cOR2`z*s2%#xR??`W<7X>LwkuIM2>}P-8_hSF|Is06l+d1Z37ckb! z9Od^N72CH>&s>g>{Umd;v}Q!pf3X4H9nh&1^Dz^27PfLu8tW<(iDw+q19GR?Ft=gC zDgHw7#qz)CUKM>kD|-=^i@B8(fC+sk|2u!c`X&g67*qJ9a&@xw-golThrOM~Jske} zcp_~3;?vH`O6mT~QXKU2DY*UV5ybH0*U+xxrH+fduS>t*Pa0S8$2yCyi|9zU3(7@~NuE3GaF(jsygR7#p=LDb82ANm?*Tdstj&lbJ zLBw-}$UW~+JnjE(y>8J-Kl%Q^tuyKfCU`KMWO~0vfBZcW?nndQf34N{pDpW0gfz8F zi%BRGVQb_`VkcctDLCN>BLsD(AJu;}P--(rhKIua8lp=praosDElDu&4+*^qe#}cy zaJnFY&Z#jauuS%CdYF7C$8kSAoZ=1f@M1&8B3Su>YWU|Vy*(_(KwAyV4VQdT$V>RK22S2jhe!G^-9Lyfl-w<` zG^E^wx^aXIM+yMq@x*bu8~ZVWP6Sc@VwLj~i>~^SkEIg3f$oGGe`Wtb<4|f>^{e{T z&{Y-?5tkR}uTn_puLQbc90w5lpRKoL95yeG*Fm1>UF0w1K{7VB^Y|HrPBk{jF9V8=b^Y+C$kDC7~ z{}GZ!SF7APp0?ooF8?I`-}#>#+?$5OX1!96TbCc(n#EbU`|l+$@mO8!YHpRIv6B$RY%Bg#0teu+M{#s{>22)Z+YWn{E5=1z1>z2ZY-#D6?Y{g`UG`*H@G2v zuaDhvKQR{b*PX$iML+3~2cc(GGI|{XlVpdm9CUD_U^sJbI5g-r{VymgE4QIj;LIYK zA2SxO$G`Bn-o#xujNd&TT{CN%G#XlAC2b7M^9DltO@St+P;q3e^7ezAGOo8*W*7%# z+`aYK^4F!Y#ieK~5Ut6OSi3?`{9o>* zknymbZ_Gc5)}+ML1iZqzfajF!5TNXD=-C!PTVeLaCTnfeqM-&YW*x%>0( z*2(qssQ4;*r@dLY&Kj9=T!BOsDmFBX__{4W2ie)rA)F*Tr8U4M2|qL(&x}EetOrE| z{e2vI-(0jAmih1LZMXm5qQe!mQD=vxM7;*IVnhgYB;pTwbG9qWre~|vLpUUV^ON&} z0^E&AWnnDq>T=`eh7~oIk>~Pums<2{h=aL;Th1+ayCdC@)%oT&4R-}G)}ANhF-C|3 zt?AMw8~{^+OlcBV#wfFC5M%0hI8LnPVhyY{Sij@#Fs6@_;nOi02Z`(T_^{pEaM#x2 zb~m;LCEdxK7&rba-(`VVW*|1D1AFI^67J0*o8mbiiI*Uee|5eRs0LwjY@kjcYMewi zCOo+OsE~7v1_XqvgK#AglX$NNKGdnU4|`Jk9Ud1Ju;1ivIjG6<^%OK^@l~U3CQW^O zY0FMcm7aL#R1C5*Y4d)|^?MwoL2ect>Z%U{RVBn+Pp50Ch!5V;^(6R4}nQ<09t6%CSxFuHi>_< zek|d!skS;B9n%<5@`-b20!LQ)5uMvuS0Go=a0oj)%JEes(v!1k53Qp9;k2M+CWU z=mid$dMeUr6Zq;H4Lp%|EjdA_mR49hJZz9Z4nOe{24+xY$~d8M=pj+pf7&c)Slhri zv)Svs!Z6-x0dFd{6o$$%nUu%T^ATxr`=$FRq4?G33Dl?SjK(O{8P%8!@-n0VK;GD{ z(YhpUIU;8jUL9qO9y`7>AeNwfa-vi~CyI_WaK^a*Ye6EZ139VLfTo%_kue@rIS8^? z?mx5I`}*43pRdBc%Z=-U+TuLQd48KWc23myaHh?2 z3+s?JK%n@(AiP>s+vQ!qo>dU0q7?-CRWAANsR<+NNa1Y&#dVPj5=VDI3xk=9JN@42 z7(J1XDvlL9N-Ra7b0kpjWG&OkXZ-lo6L1sYd20scb41b3ElA&SSM}CRRV@NKHceAT zVjXdzD0Hk?^>U6lcr*<^3(v7mf;|RV{8^>o05XZIc>Z6rn>#$TWSE&KpQOD=%h`aI6O@>Qgr|#sj~XBGFK8NbH?j&XvdDBF4RB z#}8^CI&oTkAk8a7z2w{HRJEMTkFA}@Rru%K$B03c1(~trjsKnHO|H;9x2(B9FDa|6 zVHQoMOSiiYZJIN8>;impqOBu^{3Ou6E|Hfvz}FFT2Ka$JWeRX<2n}nwA^{4IZy^R{ z!y}f)GqH>D?KlTrDxLmyxx2?ko3EWICNe=l8lYw6=_BzQ=hObV=Civsxcb*Tzo4Bq zGhIF02ADLdGL|xuQ{>uuqJGyF>}9ANmD%dvzK{ z1Uf8)j%3AXb!l_7)ES^&re`H%EE@urv1#J*?n(roEAa&A9r-bl#ns_AM=b<5uTx%R z85Qa^s-Dh`M>hh=USCnmqiz?V`A90z2PmTwtNdVh=T0n=NGCKV7s5COrF{vV4uFW5 zRDJn`k+p-569}kwfzcGsqOt1e@2zO+7C7=@;_G$7yOa*jE=-vj#Ip22NvHsH$tW+^ zg%rlZk1?Q(k)ZE!&j6DfP3xMPK<}3ApbWwFFRSBIu)@S$EadhWz0xR@YjJtGXx8M( zlyK>S`Yfn_KP_@CKC0GA&{P8=X9AhZ(BHXqB|M`fQ~i0L3HhAM3nmyfUalyFJ6KdM zntIo^v~;UKa?+hKGwSm=G~Eo;&A1>oPOi$0$WV{~GUq-nt`{PSp9eWuFXV#EfdXSe zqL9UAT1$9j>R2}WT}P&rXRdH27;T#Rb~%p9U}fPd_0WM6-VJ@Mr>Gp6t8T6?0HKLC zok$VrkYDkU(U_AJG1zyonx@rBE7)l^rgNcx$N)d%mluDj+q_g6AA}^QmxzpO1%iro zCBco033C`~p>O_m;@@KhbXq8c_UV}0)Zf6p-$-;hv%^ysFNwULLe!UumMa=OA%s0qH|hKL+^4E zm87X_@XANIW?p`57UFFMnzJlL>Dt2H;bVgyK393)-!_y`luxf*1*mXDyT)XYFjfTD zh=3fdp4p>czo!=MtRY4O1udaAgR2`n8_5T459SJ>i?+lvVfPhI-u1V*`RQ;06;bphksFqka{rp zF8OjMHg$9n+Ge@@PoZu;W}NjV1Cpk-!pUON~J zP9e^l9jTY_q&GX0me`JKged^_XCdX~b-W)IE-=v}>w3#yK}&SE)I z2_(#kvW%g0a!Pc2@}Kx?f_oFjRJDs7USr|FdK;9pNRf4kK1TK`f-hX*mB*3A>Uwp7 z=mYk@{qg3vP4*L2S9Km!uVFuCDk@f>D3W{2(c7XKgOJuIhE4RWgwOqd2qxVU{Z3GH zh{pBJmpsc=9vm*S%3>=MxHY<#uC)Z6e$PAA57k$L7!DX)XAtqp9!f_uesPvhh(t(~ zww%tYGftVGnjxEo$TVEm9Vu?7lKrP?NZkP0{=wKf?caw6h&Z&=K`f@QV8?$;db*RS&^4iW@UJyV?7o`xLvd$cF#+lfu0Duch6#Wab zW6P@-eib8Sp_NGJEh>!-O4FXXg;1_jv zh^Zhh!G$H{e%M)P`M|{EI&cCey3-g+JsjU6)FOelz#O)Ktj$Yq05Mj_E0Z&-Z6 zzA(lV-)WOFVcp09dFcffau7rT=kYn)Ew=$X=n{y8$$rX6VP3y7PyqZRiDsY6m=Yua zYeAdO2&gM2D^F@jMHse_^&{vDDDtY1aB+3hk;4v{s9cmlL068~ywUKSLO2$x0;vI_a2_)d5P@)xw z0M~p9asA#bH}BJq7(8x4SX4?l6B98sOaN@U1}fKiwwE;E(o~y6IsoP1i@`w$BlTL? zDMYSC8czSoJ3})h<|Yq_V(^x^S_huIM6`sXu3dAgBg<_a|M3<0P+2+X*X*6+qqcXz z282(;tO%$dMnmd}f!7&E?oZmf^b+xOH zf-lWZfh??Buce%s`#|wgts675kyviZ?qjm4SqG$l{PXG)Fbhm<=w3`jVB60x!W$M- zF3+UhW+-3xyzhxzZIA#>_ZuWI16mB^u<0Ay?-~{#unWakXXt$4^1JrAaE`gfHMr*Z zmX;W)CX-%;dOt`1de5)xiV_{7i<<;f%EEn>9b9pa9}@BM$oEDw%>|PJbW6Nf)>+3< zA81^_-ca`?WhG`LFS<>|W4ptu<~F&N*)$PWYu6${VKmvxlSX1(>fw=-)9*HlbpM~8 zyi&mBKv^o1IlOB>$^Y-VRw0I8>xQCW*V)-{#ANtT{6Z>9! zAuG5uj=C{Kd*G0-TT^BGlrz{_Fc-N&1F!`DuP=jAiocPJ&Ag zSJ`#L;>=I++(+ykGMG_qc$QP3uSOPwRRYbR6CR&Zv26jUG3#h1;JNvLD#4L_zY-~l z&kf-q^QNP1Dr=s$XA=zmSR!6j0ZZ!F`YU2nhG%>vk!ysC#Un{c)Aowlr zf}iG#9lzf0TGH~`aFZI5HwUEk(N#piht`j;R@1wL3n_LADXKNz8<=e58H8s^JQ$H0 zu9NTa9{;eoq5Fo`XpBjMd4I#Zk$c@R`ZQOZoCVAzce<+zvhQd6G4C-Z0p4HKW!Cgi zo^UJM$)4u1^Mh>Li%qMxoPPhM_oLwv4&7Cl*f{|NBv6Q^0$#`v_(8{&cYaM%c`&E) zF+Mhiq%d4$GoY*EW(})RPrT|=$chLM#j*LrpWi`!4O&9|W+Hd(`SDrTnqq-3vO81- zA;8_nGRtID2nmdNt9D5aPNiQ@T5y}*r743+8G(y~w$vQQJ*>DU&BnT0)q)68gmUAI zO;I&^|9GT4z8GstLuk4YfMb(=mgw?urf?F8bT$7jQUvnUwC)xhjQm7Hk{ z8+fpGvI&3be(>2BwZp{FtVa+-kla#_4v+@X6cOI)k)=T>H69Qz^cVB zbN3U_yF+0>In8swU&Xq(d-Sng3cLXHgT?`$Twb&q$zFJ^d^tNOy3< zP3Sq4oWU3tmXm4kSiJ1co;25@B{DDI)MGRq#-st9GPf-)-mt!7pyR-b7`x{|RR89Yer2YJms9Q^1DD67a?%b?(!G z=x~-W8jtNgmIzgjLdgNX^P$duXK>_?l|Brk_+@fWGYd|6+SnL9ENKIHKGK|-^@8Xy z?6(#1QY%$GpU1SSc>gEAUsZ9}Pwg@eSE866xj>rAh)kgFO#1$E9!srdxc_I{9Rd}e zNGZUcOjGTU68&kHiAiH^v#$SlbUWC&@9P<}!}4<8Mqs_i1Nu4|PM@AvInV9&@D->( zI(>WgD&Ow)f);gZ8cF9)6;dmgZZh)cc5I7TSsU~*%L>)?+@M8Q3j9gb5m!;VV#n_& zy2u{o5ce+D1hR2VO;5d|8$1|{TI=?f1zOJj!OJ`3s7VYnSjp+5dn_cCjr~x`HpN7u zH7#Mq#+4Yp|5~ilDmIg$1+FRbH3uO6$p5K(TKExFN5myh>p_Ceoh@X6z*8>ru?|_t zB9-WA{3MjP#`Ns>q8AkmO>3!dQ^M`8{o;XrMR8}wcP~P#NvyIs;tHA+ zbYwj4JlZ0Ng$Iq7cEcd80lAC63GPXp?AM9WRa8M#=caBLz z4(3cZ9~x70Ho7#hKrPE8oD#miArgMfo>51QW(5(!UgSKLo|+$Qi(iKKfnI_c)}Ku7 zF3w_udyNkHyCmq>c3$6@N+c)9W%+2GP6@C8z7Cxy-;U#h61}^AAmO#}MvfK`k6#61 zfmFS{2CSwWe(9AE+ju0^X2tK+xvZUgK+KXQH)#IjW2DR=O7z>}grMLjq%o7lPwX_E zU*+cWPd&H0?r}ue-L0L+^%zo)8aF|#t#hv1gJAQ1P-4S_*2f{QH3I_=fr_w);5D))wc{%9Tt1P0GBR=@0L_ z8y_~G{t7!gDV??agBO@`{j@pvvijMjElFif`X9WyThQMOcTY&%0%}}eTqu78-Apli zo@{kuP^afNf?imN@1>rdflneZ5_dEH}a9jVu)?#JwO`W^; z=DA>RjjT#;#Fhc6gx<~C%k^saNWty4Iw#D74`yyZqPb>2>UF$z_anw&MV0B0HUQ+xYycAo;-#ObhK#EK{56B5s z9y!YLzTq=%$K_pWuib-!@?jKOi!Z@LV$*8>>wnfw4+SirdQwrE?Nnd82zhN`+_KM+vX zHBS~PioBib6cXkNh(C?PWAZgDWC}wZ)o^7n$TxpS<*Xm4JP`f8>wxR#g3&iV%aF>p zCpt>yL&xrOEg8$fLd9IkP1$024Q~V3QAy)V(+tqri4R{ypGbC-ZwY8Z=@wL4kghG4 z(AAM9?QmWn#xZL_x;ar8?x^p{j-|p)ZFgzO#a497=oaH)J|6L6uDOp7=^gaRb&qAy z)tsKIZRUAv<$h&#Cr-Ow5U&Abww=d~2WU0o$y!O}<%7#+$p-9hv>l1>bvuEt|6($f^TkG`kmbZhIUwkG_e!^%Avnu8@3R-zMMA_3Zb1!8+~-%gEF$zfs5l znJ>>P!!C;#<)M^6#e-IoCpQ}6bRzXa&+2aXl0~9b!hT>bvygYUXFgS|)VWdaHw@E` z8-9HAg3j&d^?fCNjt31j2X0fL%R=wlXpbPWray#q``E7^&^%n|f8l1kI2&|Em(zLP zk*f((J+gWKDU9b;siE87L#|b$EFwKGVXJ`rVX9WM@>+l2cU(Q^pHxTOyf54T;2otr zez35S@dvL;dzUQl3r}A#%?&b;=5i^hHe$c$+Sz;MyRGC+x{?iL$AkG>q$jF7HyNTU znV8Ee1p1;vcV))vM(G|79LQ`%b7s0_IbF6Qb3Wqz;xw-Qh3_r(%3D`Bn%q+=mMaLh zz52Sda;3lh)b{C3>DBZO1h9U5<6_PTceTgJ;i@{5|Cl-i~86Mxt`s42)j=SAAcMIqX;dk==#iZ_*9h zgUQ}sk5#w-;B_nH|G_J4QaCg26dnI~aC7^*^$*@7`<2<{yEcx)FXpg9fAEwsfA9?8 z)2Ih^`PXH6cV1{IiCx9}fZPK1y{|)>2rmWS;uK7K%kMv|CLg|Ezk7Lh`=(YJ(ZJ1l zGobk8Vt?oo>|HZX->6ZQ_5Eho7{}Cm@dwZR`tHrkL15u;)>Xrkth=)gr!0T) zjIZ-=;=E}t%~M?)_LXkRo|XL$?z7!ys{%itzv{KS3AV@4`T{CTgICthsJgH!{W1IS z+=;_4tKTGrG*3^jgVSos&9f+1<>qe5zlVp`1hMQhhWFa?KV42QUK~571s|HHk?^K`a=VraGV41XuWEM8*y(Pk zxW1!qZf$E=yK9p>e8`#Ar*PuJnDk)j=)|z3=}aW*s0Or6b#QmC${_T$%&rIF0ray3 zY%@wF>@nLZkqPHqWEN*GUjKaG#&;Jq<8?}`_bXTAL7-})vESNh`OxaxjgQyGVm{f} zk=n2n{qxg;V(bA=uaZcgGHaWJaabrJk+-|R(Re5a|&ZDd(JvU^x+t}vw?=4oo zx(e1lUzukv%Rni<@R&3(i|J*9UPBve-qbB%EkkekVsSpXPCZaFg+N0xr>69RfbdH0 zl1A@sw;H@pfmY>|sa|6i$^1!|0fd`*QDR`vE5DH&3$u-|0*af07k&wVnV2!445ip` zY?23`Ul=i*wgIf*HkBd^v21h65*f2}`3C9dhH;oh(?GDzEaen%h-LSSPiKM_wT5ts zka+P`kF|H;jRaDzL_y>B{MN+_O3qIY9pBM--)CUytCk+8W3kQrp6ds}%|^)#bbfy> zGfbuWooKk)j4t+3c1qC;C7=8^^Af3+ZkkYG{yFza2c%HTsd8x!`cZyfU}zn7y`5k7 zDF%G0C7xtu8LV~@_d(jq;Vjov6Kd)->7ITBaJ!nFMwewAEvu7{D)!SgNGVBJJ(iY0 zka~an_Wpu*8-z}<80EPUv#h-0SWET!;d4Nki6!~fP7&XK@ou$) zZ5wwiVt>*PZfy*PDFtJywQ6I)LD{IB(_A;UR<)S*UtoqGZc%nPnkIUo$vYxAMe5iq zK!NqEYN*^;o1P}!5ZH9WYX8@zSb(R3!)F@WkXo0oQJXahi`(I@{W*v%<}KJKP6+Nc zFneS+r3xJg=T;27H90~)U_-GLMQ8?`g1qN^*;s_gDUE8m(fjh?fo?db+_3n)vGk1f z%HMd?DRNAA^nPH+d%y#Q678wgXDV6lRKbGwn!L|gxLPSa7`>#KRDAPhlF+wrO~76V zhWV?q(9&eL2{Xi1JlSj~N4MH+%!9i2}j=EGZ6aPm)>-q$VA&fGz6#6ZTNc@8fPCh=cqW|5(_5288tv4 z=oy}PCzK+@#!^5mWs|mL4_O|o8Zc_9*TIR&Qo^0Xh3dPaa2K632LITo3NmKf~MXt=UQ`mSobd~m^g z*em0nnRGBt8)Xb-X`Cspqa;$A#Hb#wqMp$Ile?W7J| zv~i_19;Z-(%nlTPO{>}~c``8>rBQ?Yz^e6CpoNQJb3wPSZ|1#ve?%Nh4T0vRzuZ?D zMzf--XE#v4aC<6UC{#T2Vz-@7*qoE(TO^WtgExq0k=N=aVWo`JJaCZ!f*-AZj_%xsW$x_8*;XwX;mKjEZNAi#@Maw!sK3S86 zzXg%k){si+dv&j$1{^u$LRAz$x}QK@RLLN^eSi<<1UY9RfBW&JIW>hbB|1FH_}vT7 z|ffs}JBn=+~)E7u6kQ38~!Tr-n0AcuSmWSz-N3*62=6a{m(~- z(l7J78rbbp1!1NW#hJg7v=~w=>ptUx=8?^q$bilBW6H+~9 zq8zYT$AS95F5_x>8!(s+$hn*;*{hWi9bk{AOSg*A4u;3pc0f{`Y=n#4>nK`8%fd7$ z+$?s1J|R=Ij0Ynb1(ALRn_0ee;IPELlCYx21dn;KgzD!I%?m5{Yh`~vrXGUnQo;GW zI{BU0a&9DXQx;Tka@wqMtNBsYm&c~H**!<67ui!EJ(TtY%oft%{xc*Rq9v#}*9tUx zXSWJoCQn4zwK<<{)6Hh4%WS600Wl(7Q^L~)n!}7)pfJDdhE!7P#s)h+7Zu4o#HQ92 z91c0audRX0j{8lUwM)2%S+^-|1`F&ClXm)(=UO=~RXN;m=D*9*R(G;ZAt4sb!%~nN zM4uGBTjH$pG=-mH1a5NR&BbPsX-Wd>Bq;5h0LAQ0)~$;)e|Uo0G@+&hv&`yEwas14 zjT(BUDXYZZ+z*Sr?nmUpw5t?I7E`#4(*2uWacNiQh(C!@N@v?s+-BZ>#;(9|B0j!M zFS%P9jdHO?!_YgPpRnSy6%R2_7pi~qEs3WUWu70yk2e}67%`N<#o_GHIK*#&u5E#1 zTZl>}nYoH@OsUm@F~8wU@zlj()H616ItN*pg6!2Ta*E#~4UOr#-eukK${Za4&bhsz zc)pV9#tmI}8@sQwr3JfMQSraT9k$9i0x`?ZV++3cy~9CqnAJjj#BUJ|R5^s|$NjG7 zeRTaF7IC0mjD5Dhpi5RLj?UWpJ3bUSPTb&cec=@8bVqW*RWGvQLNqyZ>%5mV$;M}| z_l%IMw|3Vzx8eJtPaxYX4@@_)&%*(tSYSdOIeHt>@UY)Ug<06C*+EHghAU_2Y0R(A zZ{Bae%W-pxY&7rOsxjHesI~yA^u9E!HS`9-daYdT3-J_nu_tCNdR-#0CGW!2KH1 zps5aG0_t6f!m7#^Jv8w=Z!K-s=E}i73*_MX7k{G7=S}wEsvAE4QOZu3M<3t|Ol9B_ zd?sy!S#B<89IrofbTtOzTE@)1$c2i_(bu9Gr|!FA^e|UzrzEvKb8NP@zB6d3MWd15Ru!|0>e?6Rc@{9#T)l)V z1DAoe@-*Ult)ISry5d885l`iu%3haVh#~4p^NJ_uxM+Ckjhk2g#&q`m*H#=cpj-w3 zp=*>q(t^*8ity776fjSl`ykwnq^N13p<)zOSErH_<#Ox#;;E(6LKofmP$pwvC^tK3 z5>jd3crewaS3H}vhtbQ0$n$X)ut_CXyZ2Xis8ACqbHLO!EhHQdjX<@C zCXvLKmP0Vr;}(MQ;@)X!Gi2{9%xSyLTk^RU(yitv7YEF5_VCzp_t)+@Xs?ZvmY)!pl98fMaVWHWK#f@Z*tpfV#k)&NAl+}G z*6rJaY~zn#Hmyxxv#y^iHV=DJd(ww3&Onx}1E8+QzO4%0{;RB|LJv{IU+TogB(@{a zJg{=RJZK;f&p^UxN7jdk4-rgh>{NksVB0P}vB<_}`CjDJ52;>on@wqX!a2+q#|dFe zzWS<19B(bYB_KyqKfG#q#f0vbHwP#@r<@ou%9nN?RN{B4Ly06*#Zr(WZ?(2;r#Gjv zr`m(HJS1b`MxGu~E$9PS6$V%M4+>=p3A-2Euf3|uvJnQLVP_lU+}QJuC)n&7va?g^ zkluS`5U}LZlNA|mD7K3Vnf!ydnPu7H!G0!`+#T{X+I#iqGlg%GS7K(#?b@#+Cj#i< zeF-HYh{p=_vDEwNBULP!YmhKeH@RUS2N$!8ChC%nptZ65j8@vu(?I(i_jhv z;!-RUdp8Z@KF-f89RbDJ!`%Z9E2R-c4zq`VcBStFqu zno53vBbd2NWf4Mg+4NgG)RX3%^}Sw0W1+$Vah#Hx3dTPwup{Haa};P3*92u~!tDJXYo8GzbhqAbT(nNmD(5BByf=1FF=FBA zdm2Ju6?&h}SRKd+0z!Z_8ZU(?yH~rNtppfN7y28}Zb(;TTs5L$k#`{SP*IAVd4QPl zv`*YLXFCUlbVFA8TS!0tXh5YEU8fGZUm0&%+9HG&!N~$_;dT3|)Z^j(vKjyb_arJ0 zE+{FK5xgKeg)peUT_7N})J)8>W$|kkxLY%8qN_Ys8veS29Q=1}66Onn6__(f@|FRt)&2rlxb%2qX zgU^zG`dr4!4WaJN@eqIl7vm=i?(?NJroG1EJ8~`9S1Nn}g1d|7$w_k1evn_4&#!WP z6w)~ZHaOk0y7WC9Rnp_rq~aZ#ns`{S7bZv9>G4j$Upuo>y61UM7CfXR_Y zj9vlT7SOYAUu(Q1=zeOgybZRSSJFD%lzF=!VNv#Z{T5MuAZ2=kYja9`-xHLjVC;f8@$0XFC;$)gz zQJ|b)EY03P6upN}2V{f_s>6x=#vcf}LF1k)9cUi#kIKI->Tl%{uutI*yI&-d)(b>%gVs{$>)zGFicYEGt*`?>d6v$n3CDxvJXjTm*jJFXtbc(>6&^mG7T}4YK$^>*Hr=B0&o2!r@ ztKgrfS7#y;05X9I)gd*yDWVL<8%@W~l}&)kWCvX$2px!)NtT+}4^)ZV|ItkPy5yp~|6YKw>Zp^qubVBKqv9Et!Qc;RFBS3C z^V50HjDR}3K1JMxEh>)m&fCDI)r)4qbrXnh!*$gQE7CWCm=`Sp(mxX?vzuLaKAT+! zM>G>suBo&Gwq(v8-6iC+8f{@zOQE&_(C9Z5cRPP2G@g2w=d_0SnQG& z3ufVhGW`9G#^?1T5;=$F&ii?LY%k8fHL@!Qd zppip-LOZ*r#BtZ~C$^vb4DKnwXebW1->Ux&^K>_4aUJ|&^HJkF+)#^&6#y{~rhoSE zvxkv~{J_Y4W^3|shrm#PEXrig3+tCf6#hAboQcWrN*P-CszbPl>t-&SAw_pX>nv}H z>d`Y-KIF+Pa+a9MtfL2P^~}F#=g=KiGC3`4TU|Rcw5$~PWVIR^?!cMs(Et2_Y~?AQ*N4tGnoZ+{Kxg8bM6H0+%Kg%w>gzgk*EYB?l5G&c^=RC1uaR z3vj(fj`>-I;by{)Hrb&-eyO43>(M`WsXkUUTS}uK-yzSVLaPt)TX~#M+HAfWwlL}> z;Amm>8|d)ZR%2q2*h$ClM@gnz9!{retJM#`85nPlI&N0>DSdlHe|%##>T^qH`02u4 z$cK#e(|!p@CD`cUYpxb7d&j)ps}%tkVk0^ZW4$z&p(ipo;OxByaeVV<-npLYW><)J z9gH@Gkon@zgU{7k0?5g9ndI}@=>eA_ySVEnS>DFYEd(K*f&2o96vbe_TQDi@{5t`ZC-L;^I!h`4r|mdn9hfQlVc|9G7S+5r?kT`=q@6-lazZ{x)*L+~m)Y z@rj>(6qUOJ8NxD_mzMp-YWSUqz&ZCs#Z!^{0?VkvvTu-T6YfweXGcJhO`=!=4RBmJ z!vE~j1&3_V+}K&Z;@0WL{A~DoJo?c)>Yn62O9(by@c`Q;VOd$zmqHJ`_!x1Qq%TlY zm^P+tg^b>V!A6i+%EU(WK$TKAlx>bK9+_3th)RSY%ex)Ka}+jJFLZ_6IQlP0xgEhKl3wjahX$BJDF z%<0^h-5nSE;b5yFqT?Yy^kkWTf#TJnX!XS1I-HIPSMX-gJL;R~=;w5k>fB!zUNe_? z+BLVqf&X;A>YL)mu*TMd4EmkdVYkyU53!0L+Ub|%S-XPxjptyi1)lb*0YS|#NVx4SmBJ(eu7Jz_RAY-I+Ae)A=q(%H6h|;hLN&*yq)gt zJ$cXk#<^JW$UTrRHnqjA`eqHUDY`ib{cEPQR1Z^s6qTvo=Z`4A8+H!$r-W>XldXa`kwbD-N+m;K%6FV7O?%XW;-Cy%C?rk&iQD1$X(6J6DKsgP*; z193Sz=vazs%S`ez&*yxxdv!-Ih`)S%zAiQDO{qZmL@{*qt5Q3gy)KU+=7>hv=IiIH zcIn~Tq4>d(8vdwn&)I}1TkF9(RNBBFGw!DWXG~{|#~X12v+fZy6!U9dBsxy|Xr2<;5a5G4XrF!{=wrS8XA?d%ENNA#IKs z8+8t6fTaCl!o*}`>Rr9h=DXlv8yK&Jsb1wA z`w#7(S^4s$ZgGP;pBnzaVoeV~E~lE{VjY+$Zp;LuuD!;Ad!%@jYxLZ|OoCp?JpUvvS}5u+n-hOZk)^ z*8}^7bKn7)_b?z%S)=iJZ*^9MeirB8&p{XIQ0e-3!2#@7l+{ z&4BECF9>OlhEg|mH$sBxtY4CjnkOn6OzpSq-M!_BP-OJ7!!Q=LKHVaB;$*LlU?|nR_Z7&pJYi1I_($+M@kIddal}LWp zrgyE`A1J|}PSw$zmZ!^xXT7z-I!O^XOtrw53DF)WIJ}*K zR@82lp&iu;HL(?ZzXh4uf<~31aH9|%Y=*g619{fDtu~2P_@6gRS~QnF=o_nj#Uj2j z-2Q{y%qqrI=s=l9$D#onLqv;W`c)$_)2Sl7DmW0-Yc_gd>Z&vQK# z>b}L)TjgQxs~CG@=NmLdhmJl3N8EB;)v8?u9Vhz!dK#J>ftoH3|Jh%9DacPK?3iPx z{-|an!G3OHbJrF0jLQ5%SK@%n_3eYtv)i#H*vy+wsXZgT5p5kwYA?oZI++>++H{yq zAy*c`iaq7U=I>J?1g^64X)WsnUrSAZsv7g0uSr}*bd|!d(Eq2El>c-MgdFw(U;s;A z;!Nc0Fp)!obZs*aAoMi8=rZ>(zS&=eG|Y_Cnj?`Kp-zUX^w4Sks1};Lx{KuCrd4f_ zm6?`fVYGv@Vhj;&Ipz1~C!i8IIJa3wfgnU0J{=OECuE~Cj$VisnM1jw2m zCH(8S(*2Rm)$bp`XGG@V3Er_~O;q<~bR0k+8G=p7 zd5bX^eG}J>+kDGKnQq}=B9KskI#3S-sGCZfCDmRk=KptAGJ+8mgqw=LI1S%%F~T2z zSLH#^--^MZ*r-hsY?Yt)gTzG=q6Dx&k4W}MB(~VH`W5I(ha*kC^J@rLBhd*mt`63a z{awgR&Hhk3mckYkg%pl9j|1ia3yhZq*7nwFOKDyq8H@lC@>y?>0FshG*JuW*^UN&K z^l|@s^u}K73HoHCc-%-&w(oUIU;lbkQ!u0jYK8C`A1egT*KUMlWQ{WTpA`gSoBt{| z7>}*S-w>@}o_^g>-c^HNvO@R(a>H`6>en98!d2&~aW9iW+pq9ZfE2@qaaEzR?PuO< zQ5tfr06=V#{ZRr?*Z+evj3TAc*3;qHhg%t!OOfuM&qMP6)0eLYI`GTl%lR@!&&;o-`{4O7f$`2Av{~ z`f_cNdSyL8=R`1Ko?dbq2BU$FjKK8fp(SsYRLI`T{!)c}eP+v$D9)w=^&$mdQ3eA7 z3t#p)Uz@P`<@2vrRg!mQ-pa$tUdFu0deB6MyNA5ceW zq8M~&lrrw<;~MTF6dRJ5Yi+pbW2XLcIK(9Xmzn{lh?Cd6{D65{9i-GJa<>f^k?pg; zVeDB5pL8>Vb1p`aq18XhV(&!KNYNrA8!c0%WHp-7FY#91l2-XEJA%8m0Q4p^(Jtdf z;DJO}yH7gKui~ixwnlL;2#Iv=eAuj-HRD5|)44+eoTVf929=}k%VVc#Kzs`fQ1H}# zc|P9_Rrl`>M*NK7bGC*sZ>kgaEYlL+pc~Y>bn#bI6V+2Go4fK#kV^XslI2FaC$yX? zciFFnfg%O(1SP5%jfDL0M_Cr8cGvrSsgped6d7)4bTnH~)7M>V$scwMR8J-6X>=-& z(0p=fNcCH|v}6M(F3E*{R6-pK;UyvhRUdK^abeX!3^#xT|Nkve-!+>}68REGbWO+^ zx}7()rDDW03yR7_n_gd@%JTcj%1=j>(Jdh3lD;^P!~*`KQ=XlG4*?0X;u2(jm-pUu_+uP-Vt-?vI?1PX*Bt{AKyKVv_`~#ir#Z z4>hYLUiy|$k;&M06}F_Q(bS4XMqmYYf4r>OV~x1=IxOZ}EhnfP$Q8C3)SwzF2Jz|) z3n$L&qTDyQsj+OFSm+h9iljhKUjyswYTDNo|;WwTm=G)RRyhh6<zQw)^(O9uV2Ug4eSgw z-+~4d+}b3R8%+M$^i*vxq6xkkJ`;dtIRGlog$;|-pC;rjQyeK8>vOh}8#Bt|HJG_M zCiB&~mmgpk-_FqYOisD#EZ46!0d?q6!?<{=GaT8yDYbVQVSem3+4%8A`BQMip{bQY zuVH>qZNuJGdzCt$q&6y0 zDb1%nA6ROO^T#j$m0~bm!_wZJFb`Upi|UpaWs%jpQDx-mu>+G}(}6bU0zwQruX~;8 z!@s>~8!gx@lE zA2U%yuA1iI95`<9g1TS-a!v91rcymRvPH%Pio6Fks2OBTv~BgPi;{ETym12EB11;; zG(qT8e?)6nTFVpL*{Z3po(uZCme8QJ#75?OX%sT29gAr5$3{pFA&&|!Pto!x{iX*~ z%`=o}@|lBIK4ZU&CPqo>Fjqi%0ai_-1RK-Z|9fRC`hWR5l>hK|G`xWr{~u=0zwmbw zW8ErbxDsrHly?cBK_0%(>cC4+O=Seew1)TOC1wPvKJs!Op@H#Q7t0C)jIf4%-AFM+ zefkJbClg{yu<*V3s)l|fVU!6C)k)gwYtHABZum>;`CoTz6D``}*%WuT$%;Bt?gTle z!pz$TCpt3g)QE<Q?lO z;g8uyy2VkXR9~z174FJhq4L&o2ibexY6bqA2Jx_x_;+=bAM64fc-VStQmmV30@|i< z56e+XIygY2p3s_cO|6h7V+$xa1bpDGhN@SgBMdPABriNQMkQhGs(pY9H&Pb?aNVh2 zF#M&o7iJ5+7D%v_RbkE{MocB8+tvQQ%BcZXfti-v)tyHX;C9WZFY!}e=G>r7@v*Y} zQ0z7-%qk+ec&WrV`=mV#jQTqKI$^D(j1Ggh;v!dj!g^ zr^*2u43N~cZ-nqSQ-B6T4W0d#)ZH)mlK*%CgwRvld3!@9!JAdhgnIE6(Gb#f!UftK zB@0sUDo>>XO&|$bkYx;tjS`{2sgatYHzjUfe4}9ctD}Chgjz41fLDSqIQ=Pysk+|Et{)7%4ijsiUuHd-EdB)h%p1{b z_Y()g-bP||8uz?#i66d1m&Q~tl;g6VI1LY%fKFiA6L#&R9p>&q5|W>Q1}uvP;MDt% z(+LvwqWnTU8kWwj<>&1$cdHzO7oWuEniL9YSf`>`OfpT92Wu`Ff@LwGB{kw>QC|e7 z#LL9X?iL^~=Vf|>FBu~p%NW98)sE(l<_4N0q$=X;nU^sm!{)*cOGEb`i9L#+w9UHg zD2_1J9Hlqbu*{Z))ZTW4X4+v=jWtY&BrpR6g9acbqAU4@QZV^Z^$^YhM|?tFvVq0| zk{~6T6V^pWj%k@NFazBA5=_AhMy~-K6En}w;4o7`!eG1jJFeVzR2N0!7SQ4 zeO-yXs~TTIFoO&Lng9^(GyMh;*UyQBMlc>O_NI%feP8SOO--wQRdobHpN=Ej|GTza zK}#t9#XT~zzjbfOeC>4EIIT^0A-6By*m$_QMaQXlCsiL#BNP=PrT{k3A3Ep7=QhJQ zE8g5#@LjzmC5uOGmV*s^G7kkk=AF$3UPbIlRWxPt3pnl4IN|3{*8dx8zE2fH_sR_O z<*z9G>?q2>Dkd6X*lAE>F;PcHZL7W=ncTCGzXeg5owy9b6qaJ9R@w<~UxDs=J<2g< zph8C7I`~AxAi;}}9G4VnYh$L7L)-2VumMm*-&&FgKo4oHwqB!})ybKlFfW#X$H`Qv zYY~P~KMDw`UXx|Is?~CgdIrh;33V+HdLG#H!`-8 z`)lR;Q7{4WZ<}T!iUyLZv*+rDiKd?RY!YjOx`kU~*Yh9QL%JN=@hfPMc4<=qN*uN} zXke~Wnet}FkB6)vyr{0W6w{*FIQ)NXJCU*`7s7-k8cdIVYUHH4+2d^cgL6O(Tyr!$=zt<19$T}|}>V8S~a$FX) zrIWE?y9oWwq%|;dH{hd4vF3>6rjb=4;0lu$=HcW01!~mR(;xah2=O}KE19?EdT=j; zVM^89CmkOZ4aA-S#f=-0fnE3^+TrRZFDODO5NG_nF_u8gm8SU6w!fL=RGsKGPH1o{ z(w`QImigw+u6ZC;r9mnZ3=;94RzmzYRw#bVre2;{z-hKsL!2rr+1O2V!rfjwD18f0 z5!qJVMwcX&d)oZSOh})c8Q(nj?i1-@Jmm6)K)X%rE4;wkdYjuD2f+<1jLQ@O35{5s zZRzwx179KUfv@+e62jBv8+a*Z7Zde<#D0#W$kHd$fj^<&h5LLrL-KV2N$MW`Hj~U0Kj!$ELhV&bLg8 zn7Vu&vjnI#uE5iv&-)6nY%kQO^GX|)mG`GJ0e!|^kDhqu6z?k^__IzQxvyu&T za|q_-&W{rlcTrEt(3!PGElxIbDym?KVJma^R__fC4R6*RPLKn+oDX;I-?$o@b9t@}v#i?UQZ% zQxv4G{`$u#j02)S8tw3%Jqw5{4ut0&WNcHH!V>JE>b5h2PK#up*jPSsvhkJ(MQy9> zfJ!o%{syh|b4S%&Ht-AQ{cbOi{05~xd(u&p*G5P=s?iM_gceT=PV*?b^}UaApjwrhOIlm}_=as@ zx|AFuW^2eqMVkp?E_qOZq}T=QCFz){^xzHy`Clz!+%w*tk_V|?vq*ENCW&G5|JI(I z9D8SvBZxP&;H&I9d1YxG!8X8qo3FvixC+%Pg5CNXe9%!9Js%Bi?1 z*%uQGU?_bZl2Z`~zN-J=Y*cSf9`JxgtGy^jFbX%7bFO?H&2=l+rdh4_y@_pgIoH`I z)O2V;)%OSE;NEiLS?V5JjZGDAkssB{6_+Jaw%ki`4K9e_xux=itx|>z5uvV-`*(af z`8SVldJlVS9Q+~Sb+4Q3q4$dsT3G0zjL@En`}*S3Cq)Y5H~xcU0amVD*a#JZ~o z2dNTM4Qu${!{#aRwtO6p%LzQOgu8XsCHT?tzX3Z^7{GP^)Ij(J59+f*QxVt)-{92b zHCAZz^cjmDE#qSru^-at7@PnKXvzXxBc#||*EYcYWYl!PaWjr2`t`Cvi4O8J`DBjNS}FiV;&$U#>S~qBnqj zF8B<8o;{atU>;Mu40rpyjlnh?N{Z&T2(>)(T^=4Q5UDqrz8_G66K(1T_Vu2f$(duX z-z8zyv{Tn6=h#}!4;!7(e@MjX=AQaAhZUEp{%hD7=KX8f@iU@dpL{Imjwnk&DML9n8Y?=r(T``cAVW>ZP8ps@>lttzKBDFdw)|ALMk&Ya|i4- z_TSnImlie8-puJd;r}(z@bW!wYnz#UCLj{{dX`Qd!J9wUrKV`v^NJdM=61hevXCA@ z)tCb>?>k#Js0@u}8eNa(hru;6ic`h`va+!Uuisz=TxROd+}1EtScLGh`!T9K8WGBg zfE&*=K7)RH1C|`0@L7&#*Aral2!u&-3Zh2n6{JL)YYy1zZ90>B8s5w?fV;@Eyh*8m z=qw9*yaTwt< zE|cbw%G)`(d)4z>b1GXe^4+z3-$aH2VE2P*tUCd_oZ{U0KGatP=f)B? zt8NlYQC|ULD#2&@dYy(?4ML`COFki){AkR@MOWIPmY4?A%<$HEh{mI)XLnJ~@WzGL z-T8+BNUXU~G^YQgcqi9t&;oVP{&I~_&YeY^L|=}}rA`BOI~;+y6-_$qZmA_zSEWwM zrpN^(99A&*IwB(lX5nL;tE+tkxon`S`39jGckEcjP_xP=aQV<3KRbd_GlB3;Ala-rxJ8#It~ zD-JA=gBwo9`45(D=p(X6c>OGZbd=h+_R@i`Xaj0|tX{pE-pLtDew5jL7sjeNN)6!s z<{;C!24^7dY|Ns>!*k6pJ51rWwy+!6gp(bF0@8%{ZGpDq?*zVB9Da5xt|5{N*be`b zv+gZ`kO}>iP}kMgM0eDBPLZnZ?2x#o^z*hi0vj=)Ol=PT19c_@8g zB`MKG{lr-P|7xkB&B765OEJ)8dZ|w86=-(kNY9NcGeZCrB!C9qoMmPDhMXkdlJFer=76azuaCRfsAZ69hJ{p>dKv{A*-s!^t>>EQWYrgPv>9`~Tw( zbukGSRi7j*#!63M^RJEmy%7)33Da=-FhVM!?4!d4jc;^c?2~a(1yqX1nS2%pdk7U7 z8p~;#*xk07od_DdagptXuYddL^Sid~2le9aI!8}Y`7^`v_I=xu4+af2Tq1+jYJ^lZ z&~!7hYtWc*c45MP$HQC#-=Z>^DOGzcoVBumAN%UpnvZH|o?rv0{`Yt%`ZIEBk*V0G zH}uAdQNwHRxL8a?#2=DAWH)CyIu%*8T2}nqAASD&Q22BySerC$s$!lsU6gSzX*iBB zj=Hxd)cO5&Wu!{5M#qdvx(bvArDbIxx^>ZiGideDwy{cv@IKTe&@^yG&6Fs0Q_k`E zaUARIQqB~n<(sS~FYE>=*RM*)1A;P)Z4iEJ@D{5Rk%7DOS6uBnX7;APJ-dyj~#dD`~FBJae;W*srMEH z9_d2P5zkJJySI$cKcZSA8B2c_!MieRJg;=JHoVGi)8-K())$1~IA4C^<#i8^%@jO` zoya{W`$Hns^Yd$`4(m#N>)ztD(=$(bOFiUXhksqGhc2NWZbl{*NYPqBG*xs4gb%>y zPCmI*vrAHEPv^DjpYEFPJtRm}?=26&>ub`>Cc(emJs5XDOxE>6aH+Fa?v{oPxWduO z%9F$E?$IA#9GNQt6oQX*SGAusEyR6%(AVSS#{5i4YTW?b$>h#S2Qip zJ{?8%z2Er=S<0S;i3B_HfE43V!-zSianm4EZp%?bWy8c{?MHem8a@eW*+m;@G|&(6 z{_r8;ZF*nS7MF;e9`FmC=0RR0hre>VL(RhOUZ|y~1l|jp#9LM;94vn&=oRvoKmzl z>}U#ZE5ZQDgap1}E8?AZr=qPfVLm4t$meMPC!cGGKKc?5R2|Y+{;4`(|5P2*K%!TS zA*R70L@h(P%O$v%Xohdmq*kp8H8yBfA?pi&jg1d_24JmvTavS7lRd=OU&F`w5p~gLa|Qp(S;OhWpbECqw_5qW!z;oC80^uEVsw zJ&7m6VJfb_KRHN4$9ovys3M=F zdtn8a-HQUzS5f>u=ro|92#Ch~H^soe)(yr?ax~Mt!mpD=K%v*#9l^o$!$9k940nI= z{p0=*MNROzT@Y&A^L210KGOvkBfY`+&{@FM~z>*Kr>bDXp4F~v0qyR-Vp zXux>K;B|1%+tS01?}d%l7IsStIn*henoFx}_O8_vhw*G(H#TxaBq3WG$9f9q8Ia@! z*!Ii|8u3x1&*wvg64BcoRDC8t(3KUF#o&QB*^-BR`;`OHB~Id^7R~fnb_$k zfd>qobYC-NNWcaDO7q+D$>c%!o3)+F9&CR|BmgPYk36c`8R0Fon4z}0+Bwp41wZ$W zG?@xTSEg3p^t&tk;NifY!3 z^^gmj_UJC*4Ib6YlFeHk**5ChJLG{p?Hy;E(imU}1qbg2CVJtWL0mBJfC$Yr<! z(q70ZYKEBZgy^EYOaG8$aC8J@wBS~iiheq=PZysjc$ELh2+4a0ZwfH}L()CEaPJ_m zDx_GHp+>8&b605h%PAbLH2hFV;es=S(UR!`o%e^Npu4nxk!mv}Dn!)`IGdH_n9iWkPa7g?OF1jWZsD+-pAV&b5GcM<*j)xRnkg%DgLb2 zw(jM^oja^{{^Aq&1S`usz2!W(6ZvVxek7oywh$NroFFo~`j*~F&nz!HPo=Q@^(Bcp z$=kvoXO#k6V|V)yqD6PSB64HOjt2~Uv?+TmC$vu^!5tS8Pbl`ibD|HMmEv3$qqd48 zWO7zhcucY>{!W|ceIZKTQLc4nKq1^>p~)Af&{W6!P&%o}*8yNcazLL;cM2F4%hrrM_I}2%J z=7@V0?89wuQ&+(FKI*4>31nr>62;G#aL^qK8wb8ejy@lfv;Br zZU)+OJb0SKw~LCBZWxxlknMDF{ZxC?#5R6_{)REH0$0hswBxqjZjx(kc0x=!nsdim z3FSvS_x8X=rK~PmRSH5^YsBNOxcwx`uiB_+-tkkkv(ZjCjlVL0U(=me1c^uw!9K3& zTe*mF+M2%Yrp(%W#$MGq8cbpPEE1Dqm`DkK$jb#9v={}`Tn(>%b#8GR@%7q6<|uz| zOFa(~3Wsd%mRH*X>qX`2>Pon(;mu@<`h_&T2L|d+@2aR72W1n3DHpeK=KJbuC#Axc z6Zae6QTV;ZJH&dVX_8G*!R~!|9uE`o2XURl+?$o)jfCOx%bw~s=Q0(J*Gm8r?gg)i zKRI`Erhieun--|#72?yk%bd86D^_hvG@^~hM>-wthID8?Y;LO4==n_k2X?AG+d>A@ zciqx+i@f8=V5y3@&}64AMajzQQhC z>N;GnHuWnTC2aQUWAyNC$3H${r@T}&)YqF#_r?H?Fkl}7gti#3oa1GzPDX-1yxH76 z^ZoFLWc_Xe@NO9|WxANQ>UhI;QS^&yO)d3%Al-Sw_Yk%1+%==JV<%VK1g<=@hUDBn z4%9WV6o2P3?^oQC?-dFvY263RyC_RSj%H2lEHdtL!Oje;F5%m z0Ltgu=94q`04J$=b_9}QU@>_YUd{@xmz<=3&eW(e>jHLq^)R4z2uEio_?^gAgMt!VPJ0IO#_7|eA#|vS4RQ9n(Lw#b)(#JG6?3>{4IE!75<%x z-NTpGQ;E&vmO+%=F?LT>DPcDz&}A$5O>nYxRsaBiy&j?zp@Td!W#oht)0^Bjl!{-U?Hs;&xqg`Go6ppFaRiJ(vmP;A4*2 z(617F1RT$CM@4e2M+0M>*0b{6u0MR5qwbc=VT`DD0;xfdDbPy)^Q`q$R;i*I=0MsEIN;^M7)%hH|yITgzT86W{kyM+2o}a*KG{<0^?#04%qWR3JMF@u|$wlNd zrRheg_rgcqXU@{m7fn4O?;oMdwB9IH>OZ^)@VH2}aN1Wd`&Mdq($X*z@*5E58~sB< z@rNYu?C>IcfqYzQuHgLf?yHkKy>n}L$@dQf0Nxf(9uUAY^SF1S$Y4^ol)G~jay)u? z)`V_+v;HXr%kB`ODNT3I+xvS`AqcYlpzgAehy4k%I=kUUh0l!}Q)-fMvcXYmZyG2=n+TLtu?3l4J#SW&bvhyY7DIOSd zH)d8TL|QJ`xdUhd-S4ZiHHl7*+oG-}@)5nm_nF@d;zYA2z9u;pgOSV6RO8*l#O6e* zeT09Me@U7;k#0+iOjlbw1!oooyIxp7&+iYOQ3T6G&P4rk_GIav=zp%1YNN&fbB`#J zw8Op{y<98PR20Ek8vHNMYHhataESO5)ecD`;;%>^> zVP_VbI8|oK`0TNV5VS1%w&+3Ki>w;j=ZYBL|Kx=eL}X8VR`ScVNvEeIFm|xH=av%KqO&7 zgD_1PV80jKS-xlXv_^1!S~y;)&3A;*44SWbkSSY)u8bOFwUsV? zNTy75Q9>elx`t9%G`p8vpc?^+&;#`5XdBqH%-UeObNZLq;pMK10P&mFv(odHO38wY z(bh(y;F)r!z&Njvq||gf&&3MHJLx1Z8sz!kzmT|;ZmI4)^t|8Qb5$yPQtGW~7A2l7 zvQH@b=i!q62b&#zim;yLfRwL2Es0BFla3Lc_qlLYjB={rHdH5s)h%1Blx{D+Cu=TI z>JF4_tg6G!!h6-u+*x0j+0%Y{&gsL}$}U%);+9|nY@6&fqqRv!KsJ|GSRdBie4O=M;85a)+TZTgK*x;_jZVrQ_G zzZY(CJf5@_KT);)=oLAmT$}}3hJ7dI3C#*=JNZg)Q{9v4z2m+IJd1BjDj0=PL<=eN zn`r?7&)fYLon5Si?7wAKFK4`eUa@(gGZ>o{n@nq?{Ydp4F^e@?4wN!%K*u8pzW+t8 zHiK|wXIiSGs*L7NHy-<8^()^k@w=HkiR{zEt$V(SP*^(VEf)$3qXtIV!_<3Qvc_6N z+LVNg3cC2&AO6bl0U&t+7Vs2&Rvlkf^+_prjtQIrs69WvNsH&qbF&gk>yN@Uy}x$R z;4+=l5Crpk_lLyU^vLtA9dH9y(_F@XmUXxPcX=&i>s{eQr5SMaArX(zt1T-LJU|WU z82jw2&lHbZWtWF-9R{}TDwO#g%BOu#J9NZn9cwYNd5r>xs6&Sx0Ci9IXm6}B;N5at z|2EKZT^+kL4mL(elsP_^Xx@?dd1}73?UBw=*9i8SOEbTYkO0~s@8JwiEh$f(w~4bY zW>Yhm#(;FP`NqFjl@C|mWc*&M%7ecX6=jcog&%>^t7srdC9H~qoC3-2!(UF4C1qry zGjOPJup#6+Y$_6WF0=u+P=ZGo0 zQc2(^Yp`ACE5GIg-!uF?Dnh?wan|(X$2W|S=m6~T#zWR%ojiX}gB_BoL(8^x} zV6Hx{H!In>mP^N#78v~=J}*cW4fE}?Z;iu02=`#?Zxb4Ux7dnDy7r3l8QW+}D9adp zY{gO6%zVlv+>MorlU<@n7kyg0y8MKBbD3bt({2ZT@A@Fqp-xhit>WU@n*=a#D%--5 z&Y^`Pj9x7$@0S5b&j(AkZq5%bllYamUhfYhoHG`KJQQ90O|`{xrJ;I*k0OE~68ra1 ze@KFUD2n}@N$&*8hoe*RuRqWDW=$-vC@iK68$YDb7j1h6uUasD|Lkt#qDg6=9v6RS zCI*(9CNpbw5yStdWSNq&p>7?WOTNL|`Z@zb{ zf^W;Jei_~sGLeg!+0%oC&v~Rw)rc9*@HUDvzAt!GfQQlbhj=@jZFG*uf#!t`_}bis zOVZ|-kM-?qu^Ad;J?P=e-3dlGL(j2mwOTeOL%kSd;2R!|(PpCd{3v&Ku6)L_u7`0D+Z(^ff!?{<$VY;!ubJmFxuv|pMB+y2CUS{i1XnGcEBp|-6U*jD z24Su@d|QiVI2&k=xl^_}PJMhf5rZf`Gs4NrltGqAOeX7-b>rzaQt{zgd2B6J-p6gI&=P3> zaZl9qdV1w;(bmuR9b05f{-yW$BRO!bAd7zP*OsLDFD;i6dy*05L?7#(EhS?z%cM1luR=rgjE( z#LehI2AJX~N`9FTH#^Pc<$DQqNDrg&61%4kgPy{2Ohwv!4(2He2sfArXl!(TqCW^% zJXPA{GxW?6IeqWeN|$Lv9#*K}b%@>H`#7}hyxQ7$d$jnqUMle@DD3#`#(*E)BzG#tDztJ>g! z%AEBe{8FrE>s}jVF?z<{vwhV7fdb^uhaO7lWG$<^8!De-h62Gz6ZhVC0dDQvc*{xG z7Q04yd`h^Aj~YQ1XP_A*e$JxkPng0-m}83}8yA&X+Nbe|q6$wNk zW8%xy3*%vH>TYuebxJKn_(;cxwkeMu=i@)=_r^?~OoUk9|I7j&L;|XW(2MZ|< za~5?sW=j^e2qU7BpM}o?dY=zyCA78A*En@nIzQg3+-|pvnW}TCL7+^d!_W_lkPf8b zg;E0a1$j3lnrfs1Os))+J$Bx8&X8#KS}E(l`CN*^~tyN8oL_(Sq>Rl&`gCOeV19esY~>pgED`J~U7T_#HFdd531=Q=o-C)sU&*T>YJ zk_%&hwSK-eXiWe_()6tRV}y9;a?>_Ds-2v;rnUS-(i8)#`k%MODFPY8uh@k;$Pn^ULFwvcnxX+mB_cWEt;wt+H@oH@nZFPhJSB z|F*T)rgyX0yh4*5gkhN#s1FFoWQ)^}TRlCu%)MIG8_#PYKlxSI*nN|Vr9U-)SOTIhtKF!p&&Fu0^TAp4*hu#lI#eN5qyBna4 ztj%f5GH9s5^J< zN%FF8Y8u$KK$VP+bF%;2ROK?*uB(z)JSr>ngi(IzKXQCNK}KM9Z%&=KZ%wA!#`F4*3jEqh|fJTS*Ov4$6-E@BGd zS}Qle;8m~5@5{vK2vFXxR>y((q8eUMX;|jgVw3+BFEXO@uXqt8&%fhEX#X=_WN}vW zCp3hMAS5x*oN?#qqw@f1GsWahCnsO6?>rR!%|GL$TzqW#mW0ACU4mG$QP-S^m&>gL z^F4d}JePN2QmRh)(UQA$yT@J|P0l7X(j(ekjZ9xBO0*;eO3CnfkjbhW@i682WHWd% zV2)kMM^4QbyZczK0CLT`Q+v3eU-fn|NSc6o&-nwB3ED8mn|Eyu<`uMtv4%EAkz?VI zwo|zpu~v0?0MYuv-^0KOuDMf@>gh|(majM0%C`*= zN^Rr15tgllba0N&l6jCEVTgEE_K+SMwj~sQF`nhBl=xBoO^iPn9&5f^UG~ZF5ncmyjg_q2E0*<(o(ep)Vu>ne1PL zx9>P&dk*!OZ@#o^<)_LZfaYcbFhu6#PIW|+8wBK@%tvZ3Wymm~3h2vNGl4o7ed)pi z0GzI}QPX=3dXFR8%iOCcdnOh;45DYgQ4iiR99A8-EHocUdK}5BcAWUb!QUtShX?@h zE=+3EUf}49S5pJH1uB2J1w3gWE$Rzfe-`%aq7#b0@NT!oTNJH31DChFS&5UD4eVPI z+tB6KiK^`DG)t~e1H=uD#uq>UQug=Ae_kqlC=ReQ_`C zY$K=wjz6o`3p$d1P}3c)QstEBx^pAB2N~xKp_vWM4&2ZQuAB3NWocIIq!|zjUkvtrCv;N}1`L#<4(BPbGi4r}# zupbZaBzfF%Q?>x3d7>IWYmEZl&Hu(HSmf(5;_zNd0L8JS%}(Jn&slcBPBB>m+Ck$< z%2CotcmT4&X&*q|;vc$yNf$W2!GDQeLY&l5M+?oDc}Qoan~{n#qd|9SB``{pmGBGh zOihGivy#C+BYmaFu2@D{`Ou0_8agVb!DDR_>Hwjj7GnoDQFo{qTq2FTET~J~cu>oQ z<69a=)W}E<7|pjv#YYG$lNg(fBpir~tiP(4+^DmH;ndPr7t@_JI)~Loz7K9~?0e0O zil1y4mixss$j2;kh;N&jGPzNSdsseHioMSl&9}IHcR-9tGoAm?^NlD)dW=V>XQ(e( z?1wq`N_RFAPJqk;3z3K)dvkF7%QZ`3xcpu8Cw5jpt%2uki!YA+WmW?v7VCueG{Z zIj@@Ots_L7{Ha~X&1!on^G`c5l>Bg>sQ7nm0vcW9diwo>BEiOz<>*!1vPp04!{kLp zF*nk5?hX%%M?{G~BpfYfgmT(f&nqmqq^M)vs%J$^$p*BNnGdr3-ehq;pk+`m2xe7! zcU+!HspzyK>64C-YwB-o%xTeV03MbxV@oE;lB<*I>?o;-*TcU=h{kdkf_aZq>$-gG zmIHh$uLvJ*hi`my=Y~*L>@%0U+z!7?)brdhP2S%GIG=H8pVK zaYsTxjT(pL>K;z_5z|}yhn&Cw6cjs5lE`Zi^DU8q&L^j)EVo4|{%oofIhu^ry#OeqX)&MDq12=OQ9Zuh9< zKkTU`%F`w;`o`p_`B7cJ_1SNQ&rInR!8pm!obQ3???m^M=tmY|XH<8(m@9Sat4R0a zXmu(BAG@nCkW`nzt>2TqV7AbrCmZ*_HG)_v`hf#j5L$Iaa9!40dvpVf5YJR39~KPg ztz>#_teMFjWG-xeiI%7NZt+a9eNULdNgMk;m-dhtL)|dx>OODr zz2P_7))%g2c59LEnrtLFJ}|^o>!plP=Z?cYs-s_TpPx!D1cR#{4y4~~jQ8WF?D`g9c(v}vli$B*68^bsvN zx%zBtdw5i0A1@~S`gHqa(p5+&8Gs1)0??NL3P!i!m57 z{0odxAHAgI^783gz4s|J%;j;cHVUD(6UB!mm-C|I0I2y}oQT>Bbo~9#CLC29B7y!0}%%!^{J@h!C^3!0tN;|zBL=Uh7KrQoF*&$;dp{^6j zD3Bbi=3Zr{6Mp|UcDRgJO!Z@YfdiVm25xjJfN9t<_;=Tm=*P>x7%(gO*-NlTCpQqFA8{oK#znHkT_^M5zPJJ!A~UXYc&f9u-6?^@-s>k2@t zFsr53q5Va#b;@y_@30+KkQ8?02Jj);O2Gp&JgfR$-ti%ExcF8@gp3-BO5LWG_h z*3U6bU2tQmx>|Z!(NPUfa0^_@dxB=ZH?rt+Q_UsV>0CU~0C>Jz*Op4-*-3?;f)YgY zYoKKHVYWFSZX^am3;)?sRh0FGDGv9eC(7&QgQ1%8;yJ@1z_yJTuEub?5pEtPKAjKq z^#n3i`@iUpq_@}Ieq?+7IOB)HElqWyGJADE|K*QgbLzhIS3J*KQ7S>?WeY41aGaS8 zl7HJ>);T(o#_;}@`l;n5FaT`8)Pb{1K7{ArXVQ(5E6Rm=&OM4f#?d1Id)7p3aUBdK zNd_DlNE!KumKgF^(s%vQrsa+$US>9P zOWky{jpV)|T~PhTcG|!YNHS~lKbx$EKmM7{m>;JJ|Hn%Yqal+8ozZ})Ypocq7a9A} zQCQRLxkGpET$Ds<5fBGZq6)Q42Lbo1I{{~D&Pta%nM0Xx1OMteV>3)p`kiTwe)k{EBR2*|q7?!O(5S{A#x!H1m(*k!ShI>&fWa9@i~sjUV1*t? z`%Sm+AE~BneLb~+9IbQy?FB@#ak%%Hq;jesIXDh8qbCYZWj%(V#-h@TA1ed_E~9^_ zRKU4b^dH~{3$1-~- z*?6grY`W3!mFAYANkAJe@PO~26t18pnWK)cGCCq0tws$(5uFf8z}%X|iq>1a8IuE2 z{+6nMwiJYV4gt*}JgjQM9b^;uR5qeR`5{UQQT&(Z6$(dW7=ayyv*VMocS|~#Iynr% z%*rEh##@M;UrtZ|SaJW$;(w{bQHJZSd@7ZN@2T7jJokoc`c(tGiW^hAAQ^=n@STJ^ zae|^##5BaEc;JyVSgTXb{DH19iHf0BjYKjWQeps-@|UT=*k(`KPD+YML7~tWb3=oE zD&TK4*%#l!lz)B}KBZ)$s{@c3v`TK0B!JZd&)e0L|tkfFIa1atxs z&{Vlx7G8l|XXV;Y04Fm7n1^z|B}keA`iJwF$b6^>jXryu;n~s!)ZU0bCb%H~cTH2f zd&2yO@}=f~H}=PZ=KV7ou<24b5_!7Qqzz2`H2!}LfQ7%jx)jmq!Q>`*`qNr_?bOj| zpVp~Qx)*S%J>nayK?;3 z+J78p4YD6QX=>!vW2p4Plm<7P1>g?w&?|!B&-F!C9oOvFWO^hEB8y2 zUW0|r6{-WG0_a%h70XvP?GhG)hWePe1XL?f);#&0i6@8;iO_qq?a=`AEWPRnaMD5l z(9o3xBMFhhW7$o=Qo*)Ky_ZPVe*Gi)WDxw<}t6AoR8S#$qt z3I?dv2%3Io4`R`&ESdm!uQ9(orkD6w%qz5JnHV-1rL&Xhj9M)T4GC#!v^9040d9A7 z00z+bzsF5$yRx}qIo|v@>v=spD+%P8B#PK)19_B@LchF{qvPqAYTI+jEvjr$19EEZ zKZzn!i9M$GGCgc*6)<=|!1){~Ap%$7d_3X~Bj%kQgDikOhVhv!401s$STE}@yC+he zc&CtyFT4`LLxvO=W7SpK{{m5W2z+EDJ!j~Ynkfjl5g0I)iv9z%S`S&9RVSNZ$&;Ig z-or-?XjM)yddU97bib)`rS$$EUFX4nwy6JkaXMyE<5_NPrr5IXF`LF~r@>@?&`H^l22Wz}icS)h`(bV~-E z=js%cR>uw?dABErcSk!+1U+8izq;!ga1pPa{~IDFB{DwLX{ST@oINt zZJ-dBb9&G1k4;wQuB_=lCu-je@v+umpbB@AF4zNZ2vd!z7p@lOb!epSxY28R7C0$7 zN)jMzD}P=p=JJKJ(NNQjd-cwB7xfgjIe@R#Z4kWj$4W1^ql#(cAEy5%4+)?n+=0Rd z08Re9xM*?y6`#%)A3t`r)5>=|3;l|2JM*87r(_D2*zJ zI>_h#rvUUlR;wgd{&xj9*T^67PqBBaiNSfVd_l;)#Yx3!RkkvUTM&TwsoE=B%ukRO zQ0lXhP@%ciPG(hOYO1Se{t4G5#@qR%kNa4;0G#v)11(s|7{UaMZnrUm*zH-}%QS|5 zl~QFK0f1<}2D#xFXQ5Ax-7VWru{gfcAaj78Rwa~}7q_(EjunWczMHQOxyY=4l||na z!eCllZuHb zSXcGG&$QDaT#%v76V(PG8U~GBH$(x9+E?bcG`9o8FhRH&1Gd)6bT$S!RL^tAQO-f7 zIIC%qa2+!ef5RB=bJh0jWyW*Gy}b!eWwr1jxLY*z*=CW3X~O6e`n)@WE)(MykeTTa z8Pk8=5c-NgVX4)$W%Su~t^y~14kF*K!34f$vJz=rNSAI_@0N=Fxq7mbHT>sryZDpH}+3zuLbt1suSjVZ_o z7H6050L!uey}Uu!@_#HJ2}G=zcoxTYiOWvpx%#*oT})8)Q;-qho3^f8L76^DtIjbA zQVw6nl)sz{-w;{Lk8)f)u3Pk=aelb#z{?*P?Sv8K58Rrn<1fx`>i*Xak-ju*Z<0QR zpq+Q*!FfI^hm#earF_$9R8v~<;+4>vZ%S;b!>?s>^Y$5}74{Mzizp~K!Sp*UbR`*l zAR6a=FW+`!vYB>dni~S{A^)}^@O8HZGu7FI%7Ti0dWNahdoXqUz+(leq0uyh1kr{m zwosNYLv>-1sEvZRAdjLHTiQym&{;JX4@zFXGk$q`2qIv|er|1Y*4w~>Q@+#zLHQ*E z94FcY3tJ~|^V~5ozuK?^XM&t~?#nqB85}VlHPv^XY#;YdPX;;_?A_ge>yv!+<1n+S z?s!CFU59eIeQ*E!w#-}jVR_|o{po4L2ZR@zfZ0R1?h>Hj4JF<}$xqR%3Rx`X8Z1&% zfp{k1EV5zQHYE(teR%CvrQ=P5$@&IQ;IUsm6{e->TqTyU=ew8K%1P=byaJZ)sXw@E zbX!zH^Re~ZdI3@%5UJJ0WIG6~?F!LmI}Vay&)+cf=C3iA2fWv6an*b(sb*F&RuUwwWmeGudYH@Zk~ zWMZj0q9wVD45%pMQ3!IwwlLw58L~l$syRNSR!N1SOH2>#$CvOjZlV{KDYotoq8-iz z=2ZfLjrJVfXq=^XU3g1joXB&l@f$BtQ353uqFf^OjTIrOSHGd3KnzaSr3Ta_cZ*u? zej8^V6)VhuiI7uRK?{1Q_v5B}n#vj3R?8z!xR+2?){XL(+3)#Zpa zoV{uZ;z6)3=tYx#*LFtKy&Ew&&9Qn^N%zJR6;me7rO;ZYxg)E(6Dfmiu?iHUw3txY z)=@wGNXy{EJecZ1BLUR}0#kwoTrdj`wnCj-SuN0;rbe1^TpLOUr_;bix2h}e1vqED z;jDZ6`a@PFsL9>74hgD4Ank@NNRuic-)y`Wf#XgGW8xHBxPhxH{HoNdFL~Nh{7cF` zu_g5<`N8t?%X0yuFw(?HtOt@uSBHWvm++umsKZbYFc5sjSp7p<90oa@qWYQzY~fYX zl9N;#`#^*f3NGW1m=Q!`HuNGD@4_)W-!;a;_U7DjL}a-uH#Zk>ykAg^09)-aYO82> zG!~2xfD7G>AV1c=Nd8;G{V_Ky7i{hqiEqvG1}~n9cF7gsae;U_*kEmq#N#DzW2+4q zB)>GESN>fCLm&XN{x9Lu(tt_%_scoXASo2|N_=fL3mcx4?j(5I>*|*iU`e%aEwtFJ*=Lb ztOJ4^3N$W!(EPF|A(zpZrIna3TDmd>k_1Wq?+45LaxGbBMa*fUh;?|DF99kbrgbu? zF3_pelH{NF^~pueehuGCh$Jxw_(TNI6J~crdHLE$S^hICH!f``F&V0n>F@)97tQ08RwPh&HO$#Ye1Z!nuwZQMyw!x!CdbUVpXaW4W(;N z=D|d$iW&qCQV>k|3&b|g4YL}CqeYa+(s}u)y5j6q&F6g4>xnXAPIAPw+`UZw0aJ*P zo_3x(ZA53B`UE-RNZU8~7gU2<2Vw-0M261rrqr0I?b3DdRTMlR;eZ+2u>2haCXRm%xBL5@1K9KqO_2htY?uC_=dOv` z$W_uu!aCqO9xTXxjCnxK1}1m@EJf5F?+C3FZ&V*6tTkNV(&HQJN?-1uPn}N z{Jw>hJHKXg-vDkkk#jk+Jm zzX$H;%*!k4dB!D2zKU~tU5G5>=4%kN>X~?#hFo*KveEA{Cm4V3EZ@zp#&(rB7voTmovgkMi?H$p#eGOb?Lc&|u*rR?1GxfJR%0YmtS) z%PIbK4JqFd_%!rBPPW?j=+hu+1(k!|HK8@?{5+Qt(4nEH2(aO*#N|h#{q==G_#+3W zQas0zpYIx~5p7%-6BJKdBPMXC@(m^o8U3XRiv277(UkQn?3W9#!z!o^XoMWtnPQ433AXm#)tVM$F za(~yL-jQs@n%E#Q;9y#v-GoN(LU zGyffG>*VhQ(kgAHJ4pB21#SLwB+(5488&{-an~kD?)IP4w7Ycfb z*uSwHr5TBeG<-I181x2tp-60d4r(gAbo2mtc9ysxx0x=zql zL~=lKNc%qv7iq&5w+%h1$T|1-Ci71x8=6U2)gf4Rs&V~!iVQHVWl$tepx~u5+W6VB zW&|<|zKblHx$TA%B*7A0+&~;m5M+M4vZ|UfFw_bxcIGJds|m>?+9t|j3_%97$}w^a zmH_<&unAP@W|(qNy&B2KQvH215h-4ytfXeV3h@73Q`cfKuQTLC`5QiKg06y}sdAQ< z)q-_~^onaOzHVarm@cZdvSDaw@{r}1g3&B8f@QvrI|L!`$I|1?&zEuedtbRErNA%f zJ@bnf!D67th($-3rWxhs^Mkqq9t@u-ZB#i6y(f1*BWeSQbI06>xl-FdqN#h z48TVu2g~};z0{2>X4GeBnJ5&^T>-vc!0prHOhz(KSx5?%n~VT$sT^=HZUhoccBT!o zk=g=_n#fjxQ=ATq_V)ecopr9au@5!JpJ^~hPanYDf-9l|ZP5Pwbt$l$d5n+_W zmze^p1iI?cm5Rn-qVuDmN9L!!>a}RelE)x`Hny4?apBa5utV9@m`Qu+6GTRRwYz*u zQrz&Iqn|uY+B6?Q{f06zH%cgvd#z;1C`nmkk|C7(bnCh+Gn;%V;vs55bs|Tj;;9ym zqK7&&+fj#7y}?aNeqb`0n{Po+&-`N&W8iWOzu104uy_8$N!62kL{(5nb~aic!FW0w z!7UN^;wow;0zdUMZmoeqret7E-{l*x-NPxi7M37YN_2!gJ{IXvh;S}OU+9rg*U6go zS9&HQpFejwNp=b$z=t4@=8lJHcD|_>ix8qN@vu}f)ZiFW;~j$34L8a?xZvD$UqTHX zU^ZPgB(b@aX~MJb71mZ{3wx$*DR=;EtR+hGMYS3dl+KKtMTo zUk@~&1#a*D+;xe9V%qDbm#P*TzjxQ^V%}-a7KHFe}guYmEcPAYwimpfy z&+>%D(F6B>qgfU;ZsQ%)Bs}=BZN}ec1P|{IN^7n~th~#oj66PLY;;#`g#dVTLsHo9BEy4*syI5pJckrN?Py)m~kHFRc1g zJY%Cq__83o)r=0@zzA0JH6^Wfh@W9 zYWT$tn5T2Fu13;=e2j%(pLzm`aXgWI2->2idY_B1jH*O@|KQwGB_G?c7%#_}?-EgY z>3ql#xk`0BLXJ*a`|fg7RB90`=S&V>2G=`EXPrenbU%EV2GtJjc&xpM?J;EtX4PaA zf52Y7$VXlR=aMAGa3|TiZY&T68TbhH#-`YWPOo!_ZnDVxj(rQ&AegFU_s1%EjAESH zi%rp`dG+yQ13{(6D&%S?9y2+plZP z3Tjrxphw0WwKsp{(I+iq#-3s#%2z5a9!7?2<=l~F{2}ET5Y!(Os3vkS@I;HvvCZDF zylpTal@%7@EPhMswBqkG^z&7-5dXZz7;N$q4NpnjwA3GKCg6B#V%T>MmZnEDX4SZ!nQ{bm(SaZX;kdjQ|my>=0{c{}J* zRM`$UWyjJc7#b{<*J*3{;~erdisPPZL|A11E$`43x*Bsq7^9tU$p}Hgl4ou|wo&xS zQRaJ`*yZ^!KmHbcqr!8CEuBn@C!UaPj-2myrsPt7L=R$XZD-U<78@k1`0ix@p~X@w zW)|d`_(4WqB;)e_!v<<;%PPme&&VWLN#~ZBNn`=5RbRt|=O|n@lvDZna%stFC`VvG z)tJzm6gh6_2miDr(R~pHrt-m?YgRv8F*ajSpDb=kh@YjV?lj=4gim@LJaz7Hw}Y+> zf3!loLvP^55Ww@B4}WvuN?=8YU};p@krd^h@Ow-lVqHNdt`U)o%op+frjC;4%Y~Nl z;je+_D~n47OQRvJ;VetnjNe>vS%Elp)jDH668#vbj{*I=!;Us6@%#@ICr&+tnIlRW(R761bADX`Np2uNMqOJ=4Vz2mfOdH{(q6*QOv0Mq}c(>l0Ci`S_uuK&@?wddLukx5)}xn)1s z@|S_pwh)s|pxsI)MUpN9H^#Wv(n%k#ZwvwSL~j0R?|<);dpZAHhs4CI%&BDH2}t9h z=p(6ttxHvbZ*kvTGamKd*b8lD5FbISjYUNu?*JDcz-ef2F-nRF<_g}B4nyXg_k|G= zCC1j~AL?R4<7sZNrRtmd0vDpcG{}%wqXAj`0M7nDcA$2kSHWyHzOJMZHb6Rf{*p)& zslCpAS(A1`-JsR@gaeSjBXU4PN$5P+9ZQCun2+w#%| z$%=86!#w-@`&0ey6}N~Y>rSjeZrGTR_pddm7o?zl#2YslD{Xhi0A*}lzJg-SOH0Ee zg(Cxco#B-2#|UjGSQOGsmuG10;a_q$nfFOAV4?#40@>p=!OJ? zncupBJb|E${FY$NG?Aim8QMx3!M`;I*4-IzJOoGw7;ThZ1d3{yDq(6@JOJq2O7L75 zg5^NGv?=h3wE^H$`%==G{rz;(@>>UcyZ|uR^L9ja&);XbY8TC*`v>Mfhuh*@t)jyY>s2?F?+6Tja+cd8{;W)@zL~Dr>us~~34g!7uR}r}`!l+m zb)z1(f3Hh-{4JMbU#|GF}N>D=hy~{O;m1v-Wm*Jk#b0(I21H{B@hDMAO~4@{Uth83#+`%LnCW{wT*gl!6R!d?|w?sZ_r8N0c}74zIX08jBZy84;8`4Kj< zolLpyWhVUj1D3?)zdLA5O8K4^_SZ$X{VeaD;hspa(;Tp>JKP5INbhFoK0KJC=C3c~ z&;46!-`;h`sKahvZ<10tG_v*Nso`lL+v+(up8ib?GU`yxtw}??SUv&sz)Z>s>RyMPIzvX7?1BBV4Ny z{3g^VsKEV;9(oG8^?b78%YwwQF4dInE98=nq`LUZ4A-w>O$VlZ=6+3C#+7t ziBm>P3UwnGGvfs!2S)B%EU0F&kMgNO``t>E{<^QGrl$SgtHz>obj2jI=EVmX;vAz5 zLmg4}&dj45vR`YqZRs$)QM^%65vAx^D{*hyIlVA~W!2&QTL$rVQ~#-Hmzo6vV^1xU zcwO@HVd79 z;JOJsF*_}mKz^RO&z{yDd!DHh>YZNX(6BP(eTAJc<~+jCrRcg+x4N;}DaMW4@c@ZkMj19#;h{Ef(;5mI8hpMdZc!{26>m2& zyR&-1g{Hs>Z!aHD+8&KAxjeXDcrp^V1IXd~Tm z$e}p?YjFh_Vi zneal!ulgM^IN6p6$yjC$Tj3814L!U{M$ciBOi6LpX>+EQMsoPlEP~X0Ic`2Zx}X_^ z?5QO!Dc8Rw2t@~RJT=<;!Hc`Qi8DVJTk?i2)RLyx)a(PRO1z~oJGfOJ#V*a^#v#@9 zrZl%nT$(q6AarFsjHf2YlfBWQi2)T{f>?Z{7iO0P$&zFGi4t3`v=q@RG@ar#KA3WB zn+{n+M&^HzEG}&@9nxc)`TqRxGpXoKAV>e&r=|@#C+W zt(#X=E__*F81YTR=j>GfVn_5k|w?V z*g1cua>TTIq5WMW?_sFWRVT>z5O3N@fA^NV&;1`no?dO`n=ZB;tgsGTsJ-U7|2h#bWp`hB~;9-|ivP;%cqX-pku+GhgR{OVonbYd^x zjI@?|TMMy|cUNdg9E;;|tTtu_-!%_Yh#42xya)ZPd$J;c$wLKv8c7L9jw-OOO*@&?E z#5VfaaGn7xjpnEB#e*(^)to*yeEaD3T~?$!*2nthF*sy$fn;y#(&RVo@>ZOC;9+!X z?e}^&d{Oo~p}RNcV(w#ZKM!6muv*T7l}z)Y4NGRok3H9>&FJW#g}Ru4c{tiD8>{W) z^5BppyaxZ;*i)=pb5V^JM8m>jSYRzI{V8dJT)fNn1GuGw)*XW05UgI>=1+wPV^2Pdt=3aFOej@$fC*y2VD~<*S2=lMmzX z*h+@taPWsbTp~@JNLm ze3fO}w$qy>o}{?B=P?Ru2EK%}&GyJC#Z5kg+miDW7k{4WFba1VP^_b>Eh=GBUsK~n zDw7))y!bCpI(kfi1g@1LMc^d18?(=PTk#c1-CIUP=x7kov)NJJ!kd}%)^P0>JEXbJ zsQ?+k@>a@g#0@;<-23otxa_wa?|rVhY@6owaR8#R6DP*|wN=JGGO+c>le@x2B{SmH zapn}yL+JT|VpX3=gY2_zC1(a`|55o5#HUxz*EcA0eXGMO;BwO)6v zE#cedrl=iFa2XxEL#dZHxXB{O5GvlwqLOR2 z5&19kmCKNVA}>r9f8iR>^>uXZvk7dece@BA@)qBQExI@le|fIim2q)AM72)}Jue3EKFIyY}rbCSBP$PFit&z3J{r?i8#UqrH}=>S13k_I1tR4e1W) z{_{4;ef)FlDxuyREOQf=c{^m|IAB6{X;RHUr@y+G>t$Vk0ExkCxK0{-4vjpdP&1I%iRum*`;u=>Tax0}Fa?gqO zGf*+;SyzqE%w!w0kX=>?YN1YsBJO2*Y{>lwVJbQHQOZgW_1t}*YLOM&0x>SEvG-ad~WQ&$lPZ2 zs}J)?WErMg+Efx}1{6z6A4+f>s+ewm5-3$rwa?xn#0`=Z+y6!ZRXH-KTiHAS>W@>5)o6q*71?<#iuSb zCY?H4rvBLhwWsUssPGkbNls#MNJQE2`h<1R{60U{Pc42?^!`Y5EYF7gw-dBaIuEX) zOy**SLQkF6=H(Ss8A0t+#Kvu}}8myw~ft$}964 z2j$Xjjbzxd$q=4yLWTG9mG7BCs_;=|xr)8htN3WIn62;eA65FEKFeAZ*4R|Z=(n_} zVw*lxNL~n9*N>V(*kH?_bRGs_9~^DT=2g!Q84{2SxToUjDH0tOIo>H${x8M)Cb&J5 zw5uvhwy)qimUf>%9wkez6qj2*a{n3KW_^WhHmt|)-EuJ7sN%=@Rt#GIJz<-v{$Y&B zNVx#lD<6Bq#ij-GrXDp-WV2k{Y2q~pXz;gNLa(i3JbUUCsh)?2(Ah60P9&Va*DGOE zn-vPXN@6w@>2UpVZPB7$YlNpvVO5_lImVkPqZvBD->;z2`u{2@MO z{bp)}W{SHR)|T}L#CKAx^lH~v?+AlRS@OUQFjcy1@(pci)k}VwiT>DhoOArcs!qjg zi;ozGKH9iy$q+-mgXZIu6NlB|*^4(bYR6v{IOQjC)qh*2$`7weWy^C{yfJ5)<(e7) z>RF+1ao0jH9JhZxj$PdgteOf#bfKk5LNCc01#&}pu#sm}Y0VWxbMNNL7nsSn9Qs1s z6VcBrxv0f~Hcn<0hn*Fm|A}6Sc1s}qS6%jnX;J9pm!s)KZ(*&gP~kUB3s+16vc>Z< z8``q_WTzi=7__n_Hr)JZ^CfSk$%j?`%{99mMp!ZeHxBb3iMoH}%bCpCBg`a{*m>#W z6zPKrQ}UGl2XjLF^P-%zUAryJS2-X?V-q5d}HQ54RnN89Z(&S|&zJB0i0I$gO(Y8`^H=Wm^K5bw_4*t(hauE4>tyf zGx~O)6G7Apfbs7;w28%=Z)w!PZXR%X+StP$5+$-VvMGA6Lq&?e>%`C+XuOa5R#(s) zop(3-jqB$hCR#NELZb(7nx`(#)s_WfUktjA-~EEoCI$8^KJ-gx)s+6RZL8y3&G_xs zOx(MS#$j=I!Rq+MB2QtV81ZN>9Rw!a_Iu2bGaZ=VAI|Z{h6J=#zAzWP{6sKJghG8J zn40A9RnoSdo5sRmF9l1B_t2m=^(+J4RF9C=X$trr(rXjrYl?6XQogL<@8hVUQIyqv z5W9FskjZdBkw`OTlHn_O5(&JiMvrracG$IY!(anR&1su&VZ$C^FDKwlHDSv*+wHy0 zak@?S=SN)=Uj9N-tsAmwrjCc*p*Yyso{mGRZ9Oq;)+zPE5859UL!3~nm~F9|(Aw(r zO1!gaFGl?-z*}3hM?AQ>T7{s+xCLpT@$rXCFcZJU+9Pn^)B}-?)+~;tJgxht*WuVq z<>4zjYMQll;;!9h4bQ~B#MvwQ)#%h%aqTa(vX8D6-g^!Tk$5S8%Sch2eU3%?4e;Ig`Q#Cgr6fn3A ziI&>)berEO{&?!n^@njnUZ-q_OS6ENJ_hpAYTfI0LY;fen(ann?N`UCo;0f$lX%PX z)CLyntqoO=ZZ~iFzY%Zq)}c%!Gc}n@xCG80^KPww$8UIYg!mO9T{|ZptmxnM|8!7M zOA07qSHSCD0vq_B`!=%?ozc71oAm79+d}2D6XK+Q4d~dpBPq~u#WADj$iFf@J*^{> zXK}Ip{MefP_)6a8e5457ZTii{Mq90)o0J}$#Ip}9(+!nzo`vcjRxkQU*at3qa+m7p zOHo+{hE;y1i>5EEk|8%#Bt}(MMKp~~vy6=|vam3B1M?OK3=Hce!|XnV51S{HR?3x@ z(g_L*q(wzV0>rn6OBP79k2e*6hudK$8c_&qRElKJ*I}B>A^*U`o^Rcc-QWKEqUL(Zw?@rA)J$ zS5=8V)#sl^MH_4jv0(33%fDBBj1l~7mu|g!ziGmV#mV zxT@g?I$`%1!w;_^G*^TKkL;$Z3*ZxzO2h z^9BEca6xQ)t&ZEwW2d1m7c8`Ay*5SDEz6@H@22#g`s@=WP5@)&*<0Bpi3udn6SuG2 zP_CUg59bm9C9 z*F@q)mKze|<2g4Rav4_o=>sG|f)-&X!SxsB9|ciQokVYiOVlzhOpI+lbd_)dW#!Yg zLnEbQXm8CQ*^SaZl_>ty2h(|49wM5Dt+`+k6OebT_O((UB@^>jVWBx*p%$dEV3~3o zBc1zc-SNni$Nt-lCAT!FOvv!--o%vV+;s;5p`au0gQMulm%6oPRTCt%IQHwuuB|ww ztH`O*sqlD`TSwLW`*TUbbIZ3DRg^gycwHXJ$ExB~1w4<6I%|@~=_g`FV)5Yx?^z)BZ zB6T%A;^_n7XYc8W5j~za>@s4Q+=yp5sWF+h444+C0R{#}JZ&DAa8E?^X3daxc^xBTPe(+L?r!;B8>b8`kWdV_m=7}H)ht7Ur4r)h>Si$fyjf`2bmF`z-e&KpHJS&b zfj5JFo|aA=^P+`zrq6=nmP_XJD?1004UyY1Hve`_ z$nU&2QwO0lJ(?vr?ZC%w!uES2Y_4bgT{U}$;k{?Eu!Tp?2^p9trjeG=h_|BMa_bIC ziLC9{{X@y;=hU4&Q{8LKYB^%lRDUcs(4OfealBya(uRuDN_<(;{VQ@3eBVjN4uc*e z(mLEp6VLGTJox)e(u6GtYrg$RtU+LfPQ9g4IYG-3YzQqK=d9#`2?wkeid2)%5FG9V z-6@HO$a-<63+!JH_QGCnoV{bwb0jAq_Jqc5>5|M&K3zn1WWEP#y7kt#!0BT#UyQZw ziw_$zmd`a4Mel5@8?kX$V>X%f(zS4nT=BEAMHEQ`yRR2S@7sNLI4plRORG(=|Er#VRUR zazFH^MX(E2HRk@DayaAd?w0U#JaJ7(SW(ImyC17EtVKtho9MoF`T^fG&ng^5nJU{q)3w46AnktK`s?rWh zdL}LTndv$03v(02qPeGgzD|Vz*Cg~>N9&W&`@84eU`A~EZ~YXc3_%J`)VRBaqbz?V zy~kk%qDvJUvj6crb2-qgxJ6Y`wLq_6g@U#&ZoDcccVb5yC(oJp1(?%ZzMW63h>p5l zkNs_4uH0H9_uu{WV88}*ZYMzxO!8*WBWo4=#?9L6?<29rvA~zjZjH=X?i9DC0yH@F8N-7k`UwSpa z!)yN*2MYlHW%`y2%8g;8JIrqyisRO5ndX5(Vz_bjCw2SYR?H^tPgig7;TvO5qz3!Z7$j;6+8PY&ikGv+C623q3UoVT{^ z-)JhOJW=L^gneh3u&_-CHBw4&EE(DXBWfuvL&BZmY(Wd1wmo=>g)N8H#F~W16ZSs^ z-VyWjcQhguMJ#CiqR$I!hP5*`9@(oAQ%-#or-+)j9p8Ohyd)?nrs{z-`_PAW^<{8< z00$W=*I5L6PBKs%fIUb@g}a~rI*9B`dXzEyRAFhW)%x3w-nXpIaU$fNM7-;4ef8az zw@23uBwWt}V%* zB1P(kB?4_L6sD&*#!xN?7>dRC%#>1M7w)N8PHNr}hv`P+F6Ps|XhrK0itJSd^c|8^${{Xc&;wQw;w(2H+13z!mV!st+yjnZJX}5RtW(^@UDx77^W=<&~bOOaxlI2 zU%S73Em-(bnbX`(PvcI9E8E^?r=d&UHttl$pgRHG7Cl9D8j#}!6oChs}TEk#o-xVX=E&GBI6ase(F304Jf%#dn4K|I_(xL;!UlRw~@T1pj5|m%HpF z0;SNz)d{Q>F97WvYM*_b5m4y&kYdH`Q?)~wcZb}8>9CfY#S7BzN96iTxqVa18Eg5q z|Jc4O3_?EyY=WKCvxdQ7=%nQIVS`|taQ8;kUg64=8UcV10GLI)AX?&RuAxlMD-lk{ z7iXTp2TRYiY#^vj?8t}jfqi623OCSn0^kh{0p7sK3E&O3=AtTiqU7;$YpCHNh$J#= znKz|)Br!l^u@&H9n7zC>36QelI!Ca4zm@=~ocmXNca&gF96yC3kHQ;)JO;}j((4LT z2)iZaZRJLN`pv&ouAy3nJQ0Bqq0F;96d!KoeIH9Ov+?7(;-$bYLD*3Ku=)kPi7jfi z(=8m{z@Tp_6LG}f#F~v}c%Qug=)J+)dX(s}@tfM>rN%C?){+YK7>U2nT_%NuLkgF&s6m5j! z^BRJ?kp|O$s56P5J;moWzzG4ms_}? zz8xwl$$?O1;BgU92?<1$>9Ny7gJPq*=4j>n>4%5ZS!mtwweB^*e>oLBvK7Hx2Dq09 zVE~CS0$n#2>BwOt?h;mz4a0UK`D3wHLVeCDx^ZZ*w4B-6F?)q3jC>BB?-ts*pLMD=7hwzKE0i?RL=vs8*Phc1$5-f}x6_wlZb-*38;( zzl(xXEHyp~6jscn&u9#n5`XJ-%|iw@B1tMiHAt2n{Y(Cp0038!GyrfZit-}|WdZPo zQbz`+b8F``P$i`htHer=arwY8VH{()Us zjwOqO`Ow6D(aB0Le9kKs%E~kWn6{d;Xbh@)yhuV*_TQ{81FX!iUja=3xe$rbn815B zOi==|uHj4GTI*o}B*wtA`}iT&CH@2Dm&1>@dLMo@`472nA*}`(!=9HHaGl32A!l&G zs4OX&5Ok=R58V!O%idwb7!=@3izyKN=XYc_LvD>1Bjtkq(IFcUarNG~Owq zt^n)40(i7Rg60moX70@A45RA(jMYXs@#&yCK7^y87d`INq0<;h-;B;hpKVy00+A+z zq*r#q+Dl1v!qhI-M&#AGGqtrW7S7~cU{*4~9&jN358~cD9?JLq8!l-<$~IIe#u6j6 z*dnrxwTWRSg`q?-jCIBop@bMqb~REN3^Ot!>j){z*20*`7?mySXt5O4_dfOcy?*!o zeSSXo>-pUGb3b?f>b%bDdU=^+&g(di_i|Y4J%m(TwyiCVAE>9pYTk3q|Io6K^@SOU z8(pL_8^Y?66UmfP+^?#We{KoywbeV-=IKc*b!H|DHKd`bPL?8$!5Ux~E62Wl*SB!W zS22>`S}@Lr%=*tTm|;%;eLZwF-kaVavnu^3NSFE!Z#gzR`8bA>*EF&R#&}`$oCiX& zD7a#KeqzvkQj8M++%mFN$&JIDeZLmHbWi08#k%QpN*nj$tgSGE3H91*ZLTatjJTL9 z;b3O;%`M~dgsp4*D$p)N>xi7N4(faAAb3nVGqz8*Ap`izyp=C!AHOo~!Rw1A+i(IzmN?TJu=-Q|B~)@>c!R?ZA2r-#GY(GFSlE(Pj)dFX zBw|foD&cD5!*LXqjU_9DX%(8I(~?(SYeIJ6u23?y(Xw#~<_CDVbJ#APY zDIsoo{BA;o78eAVBX(y|(#Fkw;lV#ulvAP%#a4V8W&z!p+PBYk7oSkc()f3Kgv{?S zr3Du8-EXv=iuDPfhawS*^5svXM~>Zl8Q1J39yRbAZTu)EEt~$i=^7Bsv<7X(v=k2l zP0#%^Pp!Jpm)wnK$=DIS>x>VqIc4&c{eh2)Ui8PB_d^ldK{6)&fj+=C08jI~qMWpN zW|Qis@u40!DSKW20J|EpKg&5ab%>q15)Xne55y!MHSGL{YAr8cUn;*Sl1VAo2aLc; z+T$wLT1=Xng`6^*1{xYS0^A(a<9OMJngBim4M(CTIpg7ezaKYh=A@S9c#>Qu_**Z~ ztNT19E@AR7TW=;VydRVxjcaTg^kKUP_x;>e5S<6DrmO1`+OvE44A1*8|0+R!Q#)yuBwD(Vjgz z&^3VppbF}w<}7=?aoue=;?w5|q@St>LQE{)WCYW5sP_<7Ef)g2QW)9?Ok@z9XTJ*W z#}ENI9+f0{aeLkLs6#7|7*Kc0Q3(CP={`m4Z$|43v~^!>+kgA6x<5QQ19b(f1AmmmNR52;3w34NV};8mL1lFOEP;gu4ioFI23$Mp zuTi>5-DTh{+uP0l*DQhMfm>Xp6<=F?bl5=FiAYJE(+*jFVd#h$&eHj8RCB@7x0CmA z$N=HWs*9viL1%C2qZY2FpPmgI_;LI(aYsL7{=KUk zjS5Dr9`~p_BYj0tALwBOAN^6c%#6TIF% zQ+-<8%Kvvu4Lht3$B$fj*sf?C9(7K}y{NIFA?gve`ngEEt>@UG%Q9{gt%_RO?0oaV z#4llMT-2DuV(*S_ce9kLuMiLxCU_%tC_mkromj5tw#U?*G?PkevFia_a{P>slK1-_neUh))a010^4Rttk+lYgSGLHOJ-Z&zTww@ zG@a?SK-2lOPRw3ca{Lfs>++*Nc^2*M)w?;n=$}tmyy*(A)0B%`3iBVzjrcz#8FuV7 z`C4Tmu{ELZ;E;+k1M2;05TP4^HdNfFW`552Ql6Rc(`f97a!N!Yi^%?)&5mR-o0je7 z`}V&X90r+tqbQdMRsNl4=o_0>+wzJ11~2L&0S`QZbRzcDiU=*2i1o7kp!EK5 zivslO!61D8ZuvPmo%1z(u4!A@mf=Y~mC|NLZjY#wO=0N2DblU}O_5Gd8_41Qny{O{ zH{t(#<{Ns`_^0K?*=|-Nqp`M%6~$=4R)p>5pD|3klqRhnZiNL>_%$W^1GhL6{nwsu ziWXgNy?dw)O?i3Ry`@t5sV5)3lS&Y+?5~QWG3JYbJe|>!mQ)$3+qFH~+$um<9*$=Zb zZUJ%d)+wS|^vKqE4Ig^?nq@&|bxhTrr%W-Cp6ZoWG%wn$NP#NC>2gXKrX+6 z>HJW4ZMBQM)&~MjnZg74h8jUxAF`7pbAy?ha#02i)Nw7&QWfiKe^xkG}-{}Es`ym6=X7;|}XBY`bJLgfNz)Vo)gP1nliO^Dy zuQ!0golC2ITfARw#_u{sKLuK&93OY%bCqcWFuVdffZ*V!ns$AKk`Xlz?|APhA#*h# zPG7X6{_PFLO&|8QC66wh5-`qIgF-?sCHH0L-&vYcv=0)j;EZ?bN>?)`L! zTp$(Rmm`5*b4VB>VnV6psUlRs-=yQEo+byWRTa-|ZgfV&DpN{$yk-WlS{U^CfiEfh zPu;mUeP77Q51QugiC}E=e_#GLIl7qw?_w;Rw=_OTy1`}D?M(oY;C$<>SLEJQ*kPmd zmvL}QgF&Lp0{r`LASHI_6HE8SPFfic{>i;p-~EY0pj}_D7__ywwJuvr)P2`-@0|nc zAW;wNi%r_E)K+xGs~}u_U7uW@Z?b5m26=K9&UFW?e+pTurG5+DO4!Pve!~|n<3MYN8_dEv`svZRv5e6bL#P&YEbg9(FV8LPX{6^ zE+hEE)WiW<;{Bh_YfAM|A8Y8)7~UOzD%ORk z5YN2NOnekfaHCDR;#3u#?`R}W(%+Ouv<6893zam8WUvW#Hfy)^ef-Z`8d5Rvftb6c z^e~ix*a=C7>Gux!DHE4@1=<(6CeqcowJQ8QDNRqY0s1eDYvX%S|X0;S#~DGfK>fst+zs&WI_ zvFChJ(axLzv?s=%TmLfhsZRp}c5aL1P>ccaQCQXANBlA7^jBs06a?-zPy}+9@J93B z+RKYMYclni-TQ(?=E55rK)v|>Q`%ppp`+>HX5l&m&nvGM-rz%;e|{J0IeukLyY8}n zz2_rfb`af@dW{o;4sul&x0dEB=vo9+~Ir$0tOJ?#? z-t_0k*8pRfgJAYOcsp^RUT~w5iCYjztp{l!veq<@>RMnJq~J!7aU0U1(<$68Dpwq# zMe|uVJgxsWJcXVdJJDhm2UK|c`R2Q_VPVN$AvXrv& z+d1K)&qA_hV4dNsZj+T5 zP#+T~6SU2Euis6l)~1bG4wK5x)7t8i??VK(>rH&zK&Uiy7yB;43ibx;`h8U{5#5Rh zM{{E~zHMK;V*9}i(Q*H_Z^?{WFK;8xt_Vc2yz9K3;~G^%1>gs> z@>BCU0dPN8WdBJf4t%6dm}uk)C2voaP)?7Flmvmr$aMrXqMWmtjsniR1!Zd%PPMhk z;%BI!J?A_AT{-JX*0s#CCGvFp<9tS9`2hH!m$4@AVm8an-{%cB#I_B7O)tg>p?8|E zU@tqTkKZyzzFHBKWDlii^k-)2Pdd*ofR|MkP2(3_K~^E){cx=#%pj($%8K9 z-YqSAe-!eo)2W&o9fCG_c*D;3lnA3NwF?3Ys%@9tMQ6pJObt06Pn&YZhdL*UJ=HB{ z;Yj-2q%fce2RdHvkgxf77Ge1!RJn6%>s~j<~wE1)f_CtSOxto{089^&WN&9^~h<8PXpG_t2p+Af_Ksx?a z0;+%b&bcUXoidWh;g5O4M#q>8l5(?9janc_D5{sgSf6lxWI8Ej;8vXm>;cLIsOD@M zz(wqBf%-Mw7|^EYIygv$0`JAOQ?ew>?56bA_3v#bU{4Z9tjb-Szi1VTdW~NBl1~v4||Oy>d%Dm)+JU~-a77lcwo%h^B4Wp>we2m`UjvKREK z`h)rujQ8f5Z-$5rxtIRXb~%@tGEgO*CEgdG8J{=>MK7X%!%q!(?(%aH#@nHl9H8!n z2~Ko68y9C1*Y>dAe9-|7Ra&vi3Zs{W>h*9)Zz_k!O{NPysTXXg&28Ce{7?2CN}u!1 ze-}3XKXi`&H~x!iNNzh@YL%>z*Q$-N^Un?aW$HY`q!Fb_EvM4<0Hakb^Db9sZY2g7 ztvc{@A<<<}trVgNn_$SqaTW!D&ngAO8~0P@KW*92KEhzA;0Ep|P@};!nk?(ZKabhW z$(2f12~U@}nCzSb2TcETc^c3B=TWf+E7q>PKJdm@?g1@Kno>*N0W1{t!jt1GE;i$P; z(l$wf&wKcF0ys-UJR)PGYhd2)_0L%(2t*pahS*#?1lfOE8V#*hj598yTs0H*-%D=h!8gw(IwevR_$VhR_)MR z-;|A7$+H2GC0OU5R-}8L_{E~8iAS!10)@V31K7g0sG;~~z`%Q(y-I!=^h7zW>{>HQ zTir1j`Wtk}oqu2()jRrKltu4yB3hB!hK|94)ZDEI?Sc@E9d!+IDvuf{k0S~=3$XkM zSRUToc}0x3wvM~#9_wb*Q}Ro&1cP+yN2pEO*6EMTUaQWFgj`y+C;Ex7qqC3bqO?nfiTnTr%CQh$$$hW@U)t)sf z&obxhpY40uN8gSyqd0a(d7{04Qxn<%2A z&W}Xxbb^b;5)(0J%4J;L%wPf|ReyG%OJ>LwvPI@z<(hojOqI0ZV9Cw$kRND6N46na zzYtMp9fwWa8E!=Rs^@|>qV!Y`ST&onm2po`9C4pGISSTyZB%GG0Mh;p>`Al_mQ5vuW1IH+jGA6un<+XuBU>Tq+VT)v0Gdb zV_fq~0X5ghzwW^}0a6%HbG1>}7SriIYKhS4?IEh&Hd1`@=$&ML0V%wew!c?_nv1dfsh{tTRoWo5mHPI)eAO_(X;Z`Jm8fTcP5u>nFv#{!p4iO^d zHFh)>!ue2h^B5^p(N&kQh;n*;Epfm4$)N_mn0K(y1~3WW?7jeh8hFe#L7v0dCc&qC zVtaU&5>$g5AjRSP!b0d)`hBG82a zl~-x`H2>k0sAO5Kcdlj25b{lWRq~QOL`z$p)AM>Q`qZ+TMjjy-Po*_=@=@b}=jqYk zTEO!(xEj+rayb5$WRt54s;AA6)5D%AN%=Dt!{LOxz^B{3<1yiknql5Fn6a@HqXQuC zf4Ytuc&FMdA15g%cOyK<>>RHIK0LbdAD7GX7s16p#!lOZldx>&D(?3DY)K%=C00*3V=FCcvLFt{8Z( zR@8Z`uBh1BZtpyOT*w*|tjO><{D-_W2_98(nJ z*J16YEJ%cubCRyuYV}1m(?am+3D`R=wD%99&9yb}cIYimygzd>*vHRuUj32G- z7jn0W-7@Q_r~rGaLsE1}YXd`Frl_rpCHDSphfNPZQ1GU}>t(=D7Y5nS&UyW)ZRsuPD1+F3%R5(;p3Qpp$2{W$^<{-y-A4?M;9E$n}LRcphwWywNb)CMQw{Jo6-#Y@FJ-Sp^gDF?m!Z^_~$ z*vQQQW6vtMG3I^KZ#$du9iP6P=(t3lD-0Sc+20V1JM4~>mHNQ2XSi$ickgf@G`jmEsLdqQfvOj`qlV^^1kFIwq7t%TQ;$@5vbjzZswzk&5g(ix= zW(x>J8Nw3z^oQt~vKmqxz2Na1g8L0qmU{=dBHTadb3R&#Q8TEqIArj0EBZTLUHfO2 zV%ukK1T|YvjyZ#)%wwMY=PjtocWO5~y<+3}b{es)8hai1gIa{UK6~55H>XqgV@NWw zUb}z`w{378aN)*i4K!sP(x0^-Q&V}W7Y}vGYTH)@LZEGdmeB8UL;j3~Xse0X5JTlx zVLw7gvk2ijUmTEG(R+{?zagB>-uxXr!C2EKsTN`z_-am>&J0~<+-p{I_YD~9?=4Vo za~L|(U`=P_HO>^zclHl*erPY0bOoVmxAS_jrNseZQ>$OAmuh|^B4FqI$Fi^0FKrEy z%)2`RjKld~b2#PqfgAXJjE(PfXJs-)$Fg47b{0UKxP4rdij)I+rSd_6cXArf%wZL# zO3k%gMhkB4qc%M#RT)(93{M4?(I#o` zF`$sc(Ea+fv39#Qh`FlFzhdsd+(Itl`R~(CH6P;|*}#=OW$lRUEy`=k@UMH{CAc(n zu%Ag|^dkEaiBu*kMQxSu(^yfB@+G2=ki>XU$#4g-f%>1=I z(<5=*27TqVbi3ZX?!c|r?Wa-=41V)#V>r@(rPZw7e|~{t%*-4JE>eRIzTkO-USIeg zOZ{|`55T}tcYJ%SBB-bINP6A|4J0rU54@RZdi|8t)e{ebBm&WRv82-gO_!jI6kw>b6!c#D@VMbbY8 zFc0)67kNn!4%U%wG+?%EMMzjK6P~`upDCBN>C~;R4ub3qWs2+|tK8(x#5PSna?{Dm z4DiK{!1m7JhDR1oxs7M-nmq%8% z|7N%8Lig1+PUaFIiMVZ^SM=`{fYP8E)gONrj}`L;K1vkIs1Lsx*wCW23{v}Pq?|s_ApV&`>mV2tW0jXyi^pv59 zI-OKJ&!$D5G;dMkUBaBgc!2p;qjjVHO0T~8-cXlz#LC=G-kt+NO5l?eD|IAk{r-8_ zVTJID)ho=;n|?b5Z9+)Sy^8o|@bQg+<=ZWJ)}qHRJa*8nyLrR^@rHkGNOkpN!5c#E zh1q<^^C1@#iXF`D-jyFno^VP@S-Y+8r92lsyq)S17%fnj`8)qc}|2 zO`Xm6_0wI=5B++Z7u#FzBrv}Hc>3o9?&;r`mi@Z|yPt0&o&e{D@8xGTTpX|TzPP;p zsCw=L@uYNU36+V>gH2Z4HF^H+iow2DpE-99+}zzU!at)uyoqXG{4B^-Gy}r&7Ji;N zs0c>_`=;K;!I!t+Rk~hynLQc;9rnwa{0QS3Da2KHSsINfbn77!q_GG(bPf^WTd!>O z>}@zv;f^=`=Oz9)9}%xt3XTC&!cF(t}ERHNucXjtw4ymexKFQl^T)l@?jD+Sk& z2<6KrFM`ny;=Ir^m$|y3!y&c0w4N6BH# ztYyT4Y-g7SGrE+@8xWoAhl3~B@V}U#)FFGQjwtcrLaG%Lwrv(+9+?GbS7FvqZv6x! zq4f{HzJGU7>2N=zXW+PCgxccoSLuPu#}A^PrX)R@+}~(@qI#w(bm!B1Hou}C73uT` zW(0}hM-oL@C@IKOXkZ#1wb5SoKOTvq7ohh%_&4{ff7lg5?H^LUO?V zR<&V}&PIVslw@lMf9&>6f88{>0+W%hIFXuEx@}M;&EHa@sneI5EB-dWr9q-&Tj#@M zN`fRPjAj85w89X(?$-Mp&Emk!w6_PVNL#{t*xKJ6F;JpCs=eoGP)m#@}Ia&bc7=fEt#p|13{ z3r9*i_jPZXqhk$>HmHLK{c7%T4AHQK+N{H_I1E(|B;Hj&N!Xm9%)>0I@Jap;@ zEEvNY8xOsMLlk-MwC~w&jY{r9AQS~fdp+udh(1wLfcFU4Bc!l+ zwiZ2iXRZAG%SGr-{Rl^3Cxt?xRv-`<_1VjIZ#N&}#u*CTyAgs!I!>ZcV6U!x{^g>f ztqc;4vVexe?edWhrH2Zu)l*Yj{Bf-q$l4>2@`~<2c9@97s#`Lc>t}<^nc7}lzx0oD zZk)J1%OH|${wic<81JoXT?58r!~J*pf@<7HWd>B^7`2k-jJmGZ+F#FNid_SUmmM*2 z1&q9EaPEYD3=H05Y40a9FHg@`#geuSF0lGBiw1#p2Eq!ZIH9~TZ4`zpAtFV+=k~7+ zZ*S~IjtKwPhAgyN8G9xS^scu?db*-b9pDgt93IicEV$QM z@@Bjldh}ROJOX0BQDC#|NixU?R4Bgv?gJ$~O2?r`^@HNUh!?Y9!J|Jc!zd~DPBvE{ zDK?Sj!T3>;J+S+6V-g`>Qx@T}MtM;l)U${T4SA!nBe+&2 zd>|*%48r@(`{EuSa zyLCgS1gqkEj}Do+Q46T-eP49 z4NWHromr&aeNgE*sJD5VXDB(FoDyv_HbZkO7@r&l$-YxlR<)2cu@hN7n@?LpHVQk1 zK5xjg#rl*N7eR+knOh%57eda-pw?=jJv@RsjoNfKGnS|tsC?oSzoZJYWKgg02Ipc! zUk#NTVJKOo;6^f=J6zF}ZL~41>)SOuC;ThWYrxy-9-aEWAw%c6hU_)yrE3P5HgnlY-=!Kl zBiD#t40D}VKmYOdT;*wVN3#g=!QAa#gGk53dzk5_Njr{T+$Yk%x~#$s&p zbAvyVCeM5nz10yF7to;n;<=vrmRfnW=TkV7#r`7GTDRZ0UVk%riBRaZ4CcJHyaa!r zC7m+k7WJt=eK|n(%Gt4FpQPlVp?%O$^75X{|5fdX^ z6GPDHc~0%TbN8NKL1erylS`YgG$|F1w$XzjHF82ue>}$DVxCviYFSuAiisIDCFP>A zck2~ii6_OJ^{YB$X+XEp$L6MnLSesOV(Uk06OKKa$PQ0^_CmwYeQLH*angFl#EdwgYVpYq|ZR$r|NN^5QE(AU|{ zpJOx}JaTe%qW5UE>uo|K#?9x`28kO{elK5a7DqpOE%N!T*QBBcuMeNa+Cso)?Tt%?N!vE8iOrwly#=cH;rX?Lo(%v{5v?{(W&7=BC^X}S10fJ0vW^IMILqBTn_o++I z#Gli4DeC>mOlldbkzM>@*LWWLe8}HM^61f@j}J&-#2$WS!za z^D33DYMuQN24$2cx(A;;7JL1&7!U4sPTqV>di!>|&B2&AJFL3qIpvz#YbL#I9*!|; z^k%sZB!u7^dHHp0YwM5t8FpD_;=aRGX6^2C{u^ya{S5>sXTtDOiU&eH_fV!8k8KyG zD|65ib)BNJ4FW~#Qgfn}9DsF_VYI0IWqt)CwFg{}I=1~59P6SLt`0lCxb<=DaJJoL zud&eYsy^-1(h|FLnNn_z8EK38DAq+773-^WN4Wjb5ysY$q=^r-!&6buW=k(cxbqGq z_UYXt4tuG^GqR_otTf08uv@A)B?tI}2SJhqwF4i2AMKj(fqlIE92a$&SspNtfj&P? zv=;PcXnbOb$|#AU zkX|_bA*`4+U*iK=U$00*fq62(q@Ivqyd(#T%1MMQ>o=!u`OTA z02q92%+Xi9jKk2AR+S^ivNDW+DR_TS&^%{$>002pP?)$kX>@5QO1sJY`?c+&^)-GT`2B2xIVMGtJ;{W@ zoJ<084_-@8I>CJS%$rpBO_Z0hQOchZkHqn=O*iVprWV+vfv>Z#Y#zhZU`C@aJ8c@@ zB_a{|dAmC_88(NN67p5M@?yv$phhXGPt5fKid8b56@15Mj41N$n5ynx<<}K5D>B-4 zxwgVnH+Tp6yL{nS?iA?r=Xf`H|?z`)9-~6KvP5 z7+uz@E*;(nohexomM{N^b`D^I>t&6X9?=(_aywJV1DARUNTk7T26D!PDDVPH;lBUS|NfQ=2APUN~A- z`}Jwwiw&URK2?_r8two-J8^!05CG`Lp8NsmzWxE|417SL&3-y*e^)XsGbF@xVq9BR z`-rU8pnDyyH1komhSB1&}Q_2RS+k<(pn|25ff zluP~sGZX-rG2Y)xQEEFiwMh8n+7--VhwEjo6VY14~GJ!bPH1_^6`7tsVQia}aOEhN5=C|YRrojyq|s5RkR1lc5g{mt~)PM-bl`00Zh z57N*mkl=f7z(Dw`SMjkyXK+?Q&c?HX8u3_{YH>{rt@vG`8mS9wM(W*q7KsPZR&qOR z4q^0C-u0A=gA717_!235vggdZ`msJsKDdU=B`@X!A=_O@q-dMr%C#IcQr4)=`p}jA zcfHE9MR`mPfEk$qT7L!LKV5e`?@9d`x9jv(m2WS#3U9*Zc)Q}}{)FJ=^3 zNai^ib5Zrqk(+}EJj-JRweHsc3y9hJRijxgSJ1b$w=#Lo`_2&Ha>Q*~gUkqjQ;@3t z2S}kVclabAEC7%qjw`WsZCr9z=n8^48g)R86Zp&x#G17w1{B&;4(sLKjfZpKyw>La}EKwKYrN$>Dvi*%{o1$T| zI9U~kV9v36u+G|(g+?qj8Mus=EVm7#y#h|fzN+;QHShHhwZQekv&8jq+LA|%wjHLG zNec1NO7*VDRcip%yW6b4wclWhGkyS{q(RxRcadNcso0MY5$Y|FZ8IGn8t#SNh6409 zfhO{+tTFO68=10hBc$ZT`Uu;zoM8VxcGpALNwNLDbxdXIxuvCP&^Q6(ck>aK$fuBv zW#YN1ebsNC;91_kdHEb(toDe{8H=T=lm38iWVVroC|G6Q2w+O|C#(T%Jx2lBi`l*v zp>vZr4WTbNscvZjMpe7_6BS5db2`ub!D$FaR@*d0D073Fv%$dabLF7TTUfBha>4(@ zMo6K1$B@@2@{fZWEQW5wV;bWbU`Y=G`oYn_`UB#AqM0F=RI#A9kqE$Nb!_m*;M2+j z;Pvy_0kF~#QV6X<=f3f$V-FDz!OQ1E5g?_JHOM|y)%4`S&!=AO-gwrHcWp0yB#tae z#*4kJ2;y~ox_IEy{?U`WyB{A<{xWQm0j8iNe@U8@$@1+8IHml+DQRo^VVWb&LI z%IqJ<4?KK4<6rW=%QFT@`A|?a5!Zx^UPFZMUbK#P1dNW zW2G`~C)d|YoetccI{x$o2F&cphEvb@JaOyG87J4#ZRzvotdsZLtS_uf3oYfYk6<&x zygpDmf@01hq~Co}1CtH?>;SEWI?e0fe)U6l7z{2Y%6R{rQ9_^hmRVI1qUJ6v(r);} z`Xn!erlET!*7%~_<|U5P8ixI>7J?NzVqis|5)56Y%kkc?;!4+Akmoq0>dm+F3eosj zgK)M8G2mAXdkx&y`89OA=1}0QfOxCGAP*)tZ{}WIjmE!QbdrwfxF~%Uv=uiB0rDpS zqs8(D!kcBKJN|r?$+P_G_I=fC;5$)J6jVEu9aJaSsryi*8hlC7EQC%<)^pY+wcMK< z4<1;$YKH>dM_Yt`{FKA-D9K;V2afytgKBF57`V{(H77>C&jxK$x9MMDQMdbUzHe&| z=mNldIU%y~c=z<}@AO`cQk{f|r3(G%osZO2B4yR3E+v{H{f1C|-Ybjb6JD-!gvNBH;DC zsbbyFuI?x$HEf>BD};L|fIp6X&Frt5KGs|W`X8?+)*JdoejE^0wqjKep-l&_Hv3{> zzRlCLOT_3br5eaJ{*b8F6jh(<%HxOxAfI%T{ZM3$i#=;1^Ztth$r5yVsTke&SjNe*>egB1=xfJ zz*?p#0e;0I<4C3W4fV+m30I4F$1oATz}C54fHUjRsL&CD(!+YwLBZ;_ut6 zF=Hl80W-#~dJ$z@N8=3T4w~C5t>GGYdGLiT9$cZzxuWKHh&iZ=7-%9-GDU6LHAj*@o3{!rEhY>3ZCj-+fB73JD!bQH{t1Y_a`iCf7q%(?zq+ zNyEj|+edQVt)XzqW_8?I`T?eZ| zhtsDP7DU;&gxWvGkXP6?}E9H zR*ew0BL>O3G2^F-1AY+x4u%bvs?CeY&Wh`iCDgF(6H#Vb5Y$gvnd3m?rtH2?FCIr=bEK6bejFM&{ZjDQDneDBTvCv-4Mx#KASFSc>wiB8j}scRYK#va zYU|U1b2~@ka+9BMC>z57ktN6V_gBq^-{Dnc9%rrO{=r#wiMrTZ|7*;h_;cAun_CM& zv|rz90VVKtQOIh0)BF!!uWv)Z8d305z#Q(^J)2LzvzoQ8f=VR88+oyk!TaaS{`X_SNT8OCQMxHGaO?O;;mH>m=Gz zypsU#=yNTG~eZig^j#8nCXrfR{W|1C`|-Kbn#_=zP#MovNsVO5iU)5Ibx zYzh-YK*1H?WQn8TfFDHnU6`yMutb|XAOw)w<`_H%^khyZuCs}=+1ebH;iE!Hhfc>k z6U^O<;pNp!P5p!aJ6xat!}n%o2`5BDztd;Y_VQ>kSv;3g{KlC;^RXYuhJq1QZD=tF zQXb91K#XEpWwthPtren|(4nxBRCZ=Wm|2tHji~OSBDry zn@`_M&)=?>cK+Dg!tDkPbrzAiv6~~+jrJzkTgaTQxO>rIi)?=#^{-WZyiN4Mk+!67 z`l$zbjcrF3hE&wP_^>Fb4Ye(?JIwZE1l?u3DFlVd3-U1*?P9fTGLrZ7aprP&CLAL* zY;97am(YEx4a3x}pC@B+OD}J<-i2eXzZYYp&{~6c8zl=zEvj`^FFYHugECs?6R>m` z8E5B~=pgcOfSlgZmcCWaI@}}Oo{feh9RpaO>HVrfW&T!yV@+~jXNO^5w~#m7|EV@r z0(JVQ>+gCFq;wKG()kr7UwwEGvl$`Hzw`QJpQt1?TjGr9nR5~(J(x6hKO1if)Y1gF znKSt`(i83#dq^Mz) zJFh3w=gcH9D_5-Z%R&;j95bA5r;AR;nA_M=!l1rA;^>mJvoCJcpMk&)MdA~zvc&28 z-Qx3r99eSvrSPmYlw;4f_{;>PK7}xu&_7v{T2>(!aQcJQN$)swPtOwa+HP`rk7Jgu zBjLEcOtLJ?Qr4?>yQMdcB$+@jH&?f0V>hK0Fug|~)O?JegB&vL(MC_kmaLQ+2Wt@# zGKB1*L$VaAinB7kQKWhwns)JATSNK_kF9JMpm@w)+SX4KVM@~rbXy{Oy)G5q)*w2z^2>dwjY!8FJZ>Ot}+-* zIwhs#I?K5*Q`&6jHfg#>zTkbeQU<-GfG)T2w!{nfu;pEG@bm7xBu-=tIu@v&U&KhwQG6B|W>T@?dwA;>WtiF?rkJAg?_7GVzAq`3@5$ zTpPc*IR=7fWZViS?(|rWs{iJ1|0KwOgS;Jq+r7g#d4ORiX?oi-HBcjG+t;+5D$I>q zA1MB9QNZ#s!-VLzZ}QbH7i!weyKEXv;#Rb<=37p*2gwZjG7_nYZvD6nkNSc0uIjpa zIkv*D4ur=@mo=RizyJEWc1>Yxt{~nt_*hB$?LgsLX@^aGrho_Lytr%UnTu!6?>vm?-mVUvzh8gxj__V+ zEMWiRh$r6?4Ze^YKmNF>6ZBj&)7kT6!k$s#(!0mQ+dpFN8yx0;>+X&5hCIh?k_Bh- zi{Rn#FXcNsG)_Oqy_PYEAJ6`DTc}1m{cE=P*=Co!IlB`oa`P@Q-6%uy^~#FbT>hX6 zM_h|ypEcylC+N7_&KKn&4{lqkeR*Y=YDTE2JEM7K;*dA#3Y28GBpzAhF3I^=H#Qb$EPAJCpCa`SrxD$^iQUBUT*LJH?XlF{oNz5d{Y>eSOC@ ze@yI5{C(tW)bZ>Cx4*e!l7P2W>obKD=f8*?4XSZ|uHvcc)!xe&`l+C?FIE91th310 zyS%^4{?fka5XM%MLA=J@q)Dc()yzcvWLW*#v9wV^vqm-Bt@;uFnd=YJHaWkI!Di=V5$ zNDG|W^6}#P9-DuyJf2?u>C52gXiLV< zo5_zaoFR@xJx*UCzA-WRdF1AmoX&{eQU+t$;9fQ73t=zp73G3&6fSZ1yYyjh-5mvH zS=WS^!z*)^%ay&aeRjEX{kaQ1{c7EEfy;BGDMlv3OYR@{mdO26FC`<`#knR%Ww^UnGAl0B2m z-fQo5t)C>aM{W;&R^c$sC8KZ^yO-i`kpHoK2{FHt7$tG)dOwGF(iwM$SJdEp4+ih+kYq5v zP%kL0{&k&mR1E8wl%bdaUSE{LMu`&Hbbc5G-f8;j0nK;wqIVF%f%-tZ$Ae@Xdpt6s z>{4Y2ejhE6_oS>0*UK8`+lo1*NY~pG?~ct$f_C;2zezc@lIzqbbV1hcpF#c_%Y`tG zGe(dW+_z-2R2#iW8}fv^+wG9$l~Uqwu3)tWIaY-zhPlOE9dj~2N5B*5s7bvINZAb+ zZYytQCWl8p72}*kctSx;!$09)tZyFoGX|A1s0HN4`R8243`DT$WO^~Y++nH`zh`>R z8et^3|9j$&qa9?af)C}fsErHRUbWs9bN9BJ>Y2a^D*mz~$L^9R-SH(Vn)NRh`{;qD zT?|G)IXG6KuacU6-7b{DT)dun$b*~6z3Kex!m-;@kZ+oVc-8nEUCFrb3S$sFfl;mF zimjm~rRv3>4T0ev_YN}yt)>0Q#iZU0gWPOchoF!#Kgwl-?gO*WPJ`!unDz6esYvB0JI8eN~LD1bdw@W|W`J6SGJ zsYAgjJ$J?rPl@=v%pdm~gfpba%Z~{h@O@WUoGjof>S1m+{fwF?Gj}~ zJ7SI}pAd-lH?oEB{k?|o9v1AuhFhF+AH*jH@9{QGKc(O`29ss@-}1G=RRj8BSsyYE z@{y6)NX}z?Bhfng7zwx<_<2)8=6Qb9iJRMo*>{H&<;Eqg*Heemte^U7k2z0{jPkv$mOc;6b8l!Mx(CjK-Ofeuchs{$32rSaAr!N?+M$dw znyJ_#`%m);d8=!=dHUs}3=rmT1_Q{K*&lle-ZW?DV36RIK_59TXYzDmXW~cQAaW?t z8khn+DaXYcSn==UeuFxPmC{8do1V)N(Hwh>Uyxkoh){jiGE=Mh`NR_3Q_uT(K(uUp z@RNcT-+K^nA3~5)tER+=G16qR-=W|;T7T|qoI#O&%+gdjIqEdz(ZO4{6Kde~)wqbD zVfmnAVY$unXG36Ukbk}9T&R5pEvJ_sW&at^$I3AOr>uEf@w0-v)w0f8TfvB7j*iY9 z$MKaz-?S`#lM#Cpfzcqg!BJi7MsAVq3vF2_prVA=!)BZ#_kJ`ozAA-Q>~g}c^$??? ztubGYBR(rJF3#6Q0Z)#X8)pWhD@4(~<84}v#nw$27DQ)^k^kkv)yJqKstGYS(sXpf ziM*(+;9$U0!PIU2@nqF`!KbhLuK1Tm`Z6pWZHqOQZxXV3^ZA?VO|Kq_+`YUKirRMP zGZSyL!2gT&sKDVXzeJ)9!O&0|^S*Ptby|Mw%v|#${zYT_kR!iNn?_&X%Msu8+Adn@ z<*3ajCbh4urwMEC8aL9V6Z!UYS^v-*iE;CGZBjnj5amUlLBy`4Mw*(6`<6>@is^?9 zjubk0i$kK0wBfEv0xix#H=kKuuVXJMs@jl&pn~1pWK|ds9AO z=eqBlSbI3hI$b6#WYw)%&Fd*A-hIFat5bXK@7YX;1D>;wHI%gjXCqGd(-;H;7=zju z#1)fbgxb)=h-JQ0Ez0qlu9PUjSH00^Qt4KgcxTfCUzM!c){C={0B9BahI!B$%C>dM z^$wDmrsh@iIze`w?!XwFzJ(t0FR0#N09nI$1e0SwOu@Loq48<|9;sMZX`imuId|Dn^eS2bCANH`X$v5&d0HL-SkU(!zNOYW!D;%a=`+)MKht)ndXt(9HNgCj{3x?yl6!f?clz{N{!t!-78 zVUp1wvXBMm*u{fIBRM((r!|pKJ>(dtD!BM&Xp877!@p^mLG}L8J!#l`_pfp{w)bpz zj8_xrXTaWS#!IE^FwWbyqvJj~vAeauSV1)l*J4-L%Xg@qu4BtJx~rV7C!u0@B-f@G zc4b&s7-7iHb-M6?0MRe^Bj>+ZL&52*f3XDacCWna7O(x>8R>TJP3|9xr|@pcHOrBQ zQr$+~PloJYu}_3tr5M+&{?a;H>>3GfTKRLl2&4wh;nG8pr+_y~-5b-Q!IeMcCED;6s|eb&`2 zcM^4VwJ~UnGyWGV?1X{v%3?62ugPslX62~$1LhkinD9LN_VVB^33^Y^^`3w2ax2dC zmNBl2`p@z82i^^>ptfrzvKyk5+Y-0ssw=6iJt-dx&QrPJgyZ}sySl$v*rAW_7)6JO z8m{wC`B&tE1-yb<|b$mKtkiVIa9-?{X~BLFFvpVe5XXlyxsQXHvguLN;xKN?JmSK33hiL zCO{Eee9A>BmY|hHhMBQ5n;eT3V<29;eD9rb6e0@K*0)yq&92$|$1S&{h(dyckc z%In#3#7GrBX`llJ6EPFFLU9Yd5jzU`cxJ);b?jiKO(g#XRSSEDgz8~Hn`Zmg)u~j$ zx6iL58PEYkf>g{|Dv6po{s;AI?jd-K*wa*f#{>b36WsUE?Ec}yG>k>p3EvJ~YW|X& zAGM!!@=2u3T#Zrm=wj~KnM<)ssYjc`Bs2yqqE&%Jpd>vt5R&XSv`+8ImZ2T$)I~oG}1HcYKTw1ZbodkNjc^ zsw6d4!wkuR@@9dGd)&>b`XCZL-Dw>vmc#oB%>6BGwP>#IsgmhjuZKU<03lHcu?xXV z4JN#OekRq=+ptN+keSv75^zZXPm-t47=D8rDy%l-S)InXdOxGHGdU!$Uinv-#cvYs zPN6S?o8r7e>GMk-zZM=oGcT{#PuGgsB>`8J{H|;7o#$XoHB)Ed{)}(gV#3A$qqMG- zH$=|*nX=1AqCrhbQi^X8H97AnsP^=Yb16IX8{%y+9RikC3a!Mc$w$#KzqokfV=T

o7s`fW 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

27;cF0!3yJyX0HgdfJBEwYT_8GL;CW**qf? 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

    Qt>swT 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 z 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

    Bv@jRzrtd|9z$P#q2Way%Hpy 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 z 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

    WTmKHF}%%%8(G~zRzvL1Uh=Xt4;jF0q*aSqV30= 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

    _I{?3^dPTh;QkZc0_YG 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

      ;H{_qrtMrPu47r!)LTcx5{| z2pW~o<|mTjvS1k@ts0Mb`}YKElMnb}Kp)CW^!SS=v=@;lxaC+VnVCo7qhXo&FKH=p z`+5K?f9!%${)B3V;%aqDoNZ|>uX~fSp#RUB`CkoIy)Y@7wN3BBOhHQqzb^X#_n@uN z@e!z#9N+#Y84<%ddjuV1B0#yOe!111D)qB8p`L*JcUj%sg2wQ$@XK)46}hi+D~-ma zl){&jEOf20w81i{J9tt-^jU%f@&k!Pz!hg7(i|s%Sxoz-k(IlDY!>u}PJ-{Q zPf2?GFp976O@d*cAZ=NkD)H-{P)C^bu!r=+)$iXS*c@{$or%qJ0JZ;A?OY}1Mr)DL z?B!8rI#Wd7WSa+*8sn)az2|-2e4$$^`KGUK4=b*9waNW|Jz`+AYLwa{sV;g&QR{B~ z)ivBO6W{9nn^?~geIV?yzw*!8Pqq1nCItV>2Sztfah6gu ztAPC-JdG8bjvqWsPHXi>8QINRN)wlFR5S`0=7H1fOp(!(us)W(iX^1?85yY__bLn^ zF2%_T3!a)TtM81A>X{7aB((UWJgXjWvhaSfyLj_%zR%@4VyDk)^1HM`R4hRO;lMjo zQp9t(G`l#0cKE2%RFJw`r4KOzhI{Z-Z4?&C?Ks(QgShg%blwuEdj~fy%v`EpzC0Vs z3@vH(y^I$CiccWowva3_7+MbBq^F7ZQ1upc9i#jLQ1MvUQ7gTQT3yS<@&qo@``JJ^IZ>j$d5n44FHCR-jEG_ ztER&?kXz!c9RG8y#&OM-9t*laHjo3x{CrAY6V6NwdolAuJA!w*DRX)Q1LmLaa@>0g z|I_F=u$Oi2g&#Mm?6b7{v3!=_R*$(izPA=)6Y1H*!!bz8)TJR9G;E=AnJFC-_j~dm zUXIA&P^S-gLnO~KIdj!3*gtYVIE%3&ktV*`7GdKbu2MZ17q8n6FXHq{)i6;`?;QWY z#`frrp1(}7I)1*g?x35yL)RmojI=rzXNN2;O*prinKz#=ner0;xCJY;%!%^3o%rPt zJrZ2ZkOMs0D9X5{NR&W-L9Jn?O^;^~dlhUZ5!8|7Gi zzEUJ$#tqoX+KX`#%_yeJOf_u{(#karFmZ=qH#_%n{@s-BnswIMt9yNd3_3ys9LKfQ z2O8ibS{v)E-bZ?=C~KwPh@cI&<-+bQStu;qU;-H6l~ZR=al9g4Og-q>EF@ueaoGM& zF~S=dyBb)fsCnz{%gB?8T|&Diu@v~6jRiH03(<`-?g$Xd-EcRLLYB{Zyq4Z~E$8=b zFNH8`+-sH&YY*ofOXC2?@G&nB{?4QTN~`SkM+9wM3`&xZ`(N}gdi<6diSQPdfrLb3Rkk~} znWZN}Uw`Y;#HquDyvME&rly+;XJ@V|MlZnOdhj!?bCvXzEn{3bgKx5OD|X_PCVGik zQbq+*{+XM^u6FFDfv?YFJ};5CDtP2?j64mki#u$hNhBR(Zz3vId7vRB?uQ7dH>OVZ zZdHEmj%gBoIiknCgC_7Te830`#`lfbdhl6EyN`HKX%>eVi$P4ql3UNW420Y4$Q!lK zS{MPAylw2f9lbpeB{9Y8#lh3)y8hh|Q(fB0fr)!FG)(q253R_fU zfAkr`s&gABs?aycS`uvJ7a7*7^7U0tJg2R`n?@_&=FhjSG-Z2*D};PR(Fqx3)Tal_ zB~?YW!u`sQsh;L7g@-UE^GPf{9N#KLr8oR4jh8%gs@5#{)GuHxj^r1pEw%*?*$UZI|pB@PdrCVoS~}; zzubSsb}A?yM3CxDMAr7VSSW^6;zIsJoBc8l-}j_R+2JqyH^EdAjKI8zFpyGB(s(AJ zl54$dw#R#inps>H&0ybR3$Il3Gi&96{@$AuWXu`bOY5_5 z)US`zMQ-`uPCojMzNpJuKZhdpQ~{Odj~D%4G`)z!8kJKJXG1Vi*j*PG(Y%s2GCgqlXHIw)1(D7b*a=epd4T z@C-SI#CQ6IyP#8+89#JU#Uf}7@RCJ0xS3`tJGfGA5aCo!w@0a=S}?I`R*X1Y~yQIDV+dis?O} zrL>bY1?kF-4(A;D&+TS9yd{o&BA^AfrwP`ErLEjkDdLlf!@ZLqtNfkl3*QaDf8*e6 z5-!}Q0h2BmOR8N$RWa;Hj5iMUZgb?UfQa@2^H-S?JayxNt(&F`gJRF?3!LvC`^5aE z*&^pMXh^?@kz``}w)!Qm=_|z_tMGQJzY2oyLRN&oHHu*(_;++2_pssewlE|>Xe!k{ z2=Fbg-b~&*Fqs=AWUNNt`T$}MOw{strX;S))i2%QPu!_fB~E$^&~v^cJVT{jH;te2 zH!oY}49Uw`0+U1uw&AmR+h(Wy4rxy7C!%LAPo)q!g@N~Arg1+JOh)m*yZ}cVHM69n zz$^uM1|mk}qk%S$K=uz`N=x5=Wp_!e4WDxKT~k6tjog$ZFqXg>ZHG+>NI?oD_M}dW z1x@tZiyrJt@7qjEu8|2t>8LBDJ0RmI^XNogTT?>bKVDF@W5JO)R)Y2R-KqWQJ@3A? z!s{Kqdsk~i#iD1iNf4@H01QO(7oCt>x zD@0GaJ@}hxd{n^Pz1)%%&q{NC+!fxoVaM>TR9(ZJLWNp!BhKbWJ?2cH<199_kJ!3N zPXmP=N{;ALc-RI<0*~_cXw$Z(nBB6Y)b!~>UW|eezHVh} z7877s$2R))(1cmHkf8lrQr7ylJMca>^^)ZZ{yX(Av%O}O1&1V?C6B(kh5qWZ#s!Y0 zZ7bTwIPutihZ3Tzkcq=f;T_~Y1uB2rQk>_hFU$6|$rH2>yi%(OHm<0u6Q2CY!`WHE zBPzBN4!omr2sG?RJ{sv>jQV5L+ZgJCgJ@$jXJp&K>(_cIp>`#sq_%|*e0tVdfj9!5 z%RsZ~UnM zvjL@UiIqj}66@h1UO_npR~?g*p~8_@;Dok2Srl?8?L~c4QZtl*S344`+swZhe($xy)|#+=C> zv$0U(k>x-lq}fE!26@+>j%jP>6)rxC03F%zB|Csto+q}uZjskGa`SdPuPmZAXizQV zcYDv^kWjJ{&S^89A0gEI{785#aMEPj_{Eq(i53elI@{Bs4{@0@@#;d7xPE#T2rT+Z zB=VqBGS792>SI?*f=ddu>p#4|Uqa`zfu~S0U7-%W&$%TEzZLklyF81SxWMXJQ5JMN zSg(t7M;~*GqEgl8++u+jnaM9fY0E!_pUu_bo;^hl5rtiM0CzWUd4+h=92T_i9?K!g zwar(a9!c!ya9ph-nhRrdlfLU$OI&w-tS~)u=jitJNDv!l_YcqY1ZS#Oh8>?O42P$5hl6I8BNabweW< z^!^{7ZPZnj*hskQ5theu8h%~R&oR2Exk0>5f|!irs-Gfm*|DcN?+0rHBUa6 zEM~c*YhjijFW;k!uDW`?D$4&-Zh65NTwyPpB7k znl+r}c)n#kX=gGy;z;1lKWwTxT8xz~8l{tv+s|S187YQgLS5}K`vNE;Yst%^ZMBKb z#c2nKU7ANks3t@qBBJHpJ9{iVBgNLWr^tj_x1Y@`WK*7d@OHhcYy{~{bpwt>D}aPl zH)SIp-CT0zT}Duvh8Fbzck8IIIzBxUlU$*VEYy$)`P%__`teC&WEfz?#Knm-Xr~+= z@;KA25hZA7<#!dAxxkMD!-f)}6^4(BuXBGBP~F`d7ttc!Dp-J_XE=8iWE?C$$yAMp z7Q5%}_;CEglly8(ah5|wOM{D;?h5i}Esf;s8^ya<#af5KpLz=R1IYJ7^`UWHXwcqyBxzjw z!xnwXhlXV!5>JMQ&C>qB@~oGa228EbvS-6>Kju>omynIVyQjYJsxj_)X@;O(-AWz& z6v*--G=7If1@oeHMPAGj5-1$47Aw-nkOZ@)vhx3}k zYeJ+R1o|ir7o(SdjleA}`Q^;mSL6dT+g2BW}> zp2Ql^>1fx0pR0*&d(d{vlXObg&hMejdrjQZZJ8q41)15HQ|gI9Z(aM-m+_;mTRJ;v zjE7?!T42fec&Zm1!2Y%~dyP ziGn14n6ZB=IFT6a$>(nritBEynLFzJDGi@&VwQ?XxKHsGsuYR7IkzyD5XI%$b9NWXf6RVI^my?gZ?drYTjAm;?BytGoDMYddCiM4 zS!6s;34RQGNtYeIt?;=;ekL&0yOp!`YDd`CLPvv<7#h1GyT3!?gVN?9gG(7Tc{0`B z$~!r;ucVBQeNltiBfw?gy$TC2L8XrJ=&Q9`ibyvoOvkYO?BStMv$AzFtNDkcEHq`Oe{do%D?=UkA96LfBVTT!e3Dns(#?;q`Xzu#H=ePd(FGh$ zVY9-grZfGiPRr*S-Wo-ZhBC{ayiPCjMV=zMep6^R8FKP?uqROOLlamiW>?hud;M*r%Te*vS;F zeZA3*?)t5e&x1uMNW;~z_^`KzH0W+ z@ftpEs3GoI(^R`e$wkKghC`o%^WHp=kG*krNf~J!Z#34(2Tze9rsjN+I6r?Lb@<1x z$qwzl!crooFm^|=d-xAe0LZioA4O)x?_OG1m7z=4+rF#_&F-lu66^zWTPO^tI;)vr zc;bJIG`qdMPZ!>tF%08Sr6w2)5sc($Pb&3h9|*OsJ?23-fyvos=%}I^W4FQ~$e;Ls z+qCHWodG8lyj*wfg`+8W%)dyciQG)7(an88250|a!+*X0v$E=IZK=`1+R6j5bTBjd zG5Gt_@BZ^mZ>+={3K~zwo|Gp;ey4hNC_fNm(d~Vx&mUF*ZN2Zx;U&v~@YKhfBEU5@ z(k!!C&!(lIu}ZtQ>gwl#Bwtcl@S|2pE-|mz# z4W>1jI4_RX(CHFS+VFz+;ckcXxxH&gE7Ywkz;Nott(0}!)hcNrOJJ05)|0W{+@X_x zAZ^EFt^s+Jo$jOj1in%(eM_%X5P1EIVj(sdbCe^sc&)3EF*Z_+wR7SuK2t|c@{{If z|5kZ9udm~l!Qodz^NU0bwvxj=?_#H}u0h73HhoD`! z?>wXDFN!2%euVzMHLKDOGA%`bveDAgVl!d*gOHYwxxxi))UV?JYU6sGKL9EKYW)ZT z?&@x1j@01|pSPk9F)?=45{&Jw(}3AKEscZ@pve)ZlgDeKPna)lMN0r%Me%z#~7 zKY)snO&6t+6`$33;3K5Oj}!ba4upz&)foxZwFxIUDfchqhaVi|gD`p--dA7;%tkf} zgzwR&Ff@G}u;1w5OlncW_-5RBgM}W=QWSDcuf07-@m#Q%QAA?)n=934K^BVMVEcSu zLnOHeh9R9EzC0#!As2wOg+9WNP)Dw?+wrx@v zz7iBGf9B5MI7IG-09r(M%G6(QNngGIg&&Hj-q;7NATP>S9 zTlaMBvrS}_iIQA%cpp5nennPU5790Nt4ez28!&G~4XA4w4h_LzxcZ+!+$6LAlNavZvp}a2J(p z68}HbH^0AEK!{TS%KD&v?&k`GqcO4eCtrMnjx6eze ze|Vr)7q3gBOx)$YA{b>2Zu*MVR24>?80!$P5S0^OdUzy8jNu}D@ghg7Hqfu4~vsax$ zp5cykuVup>{0b_zLarx(Ou%iH9C2lzq)cm+mHrce_^g`^V}Sm&KMUwhq_ViOAChft z-IiRR7$E6VXS719r9t`y%0|xYPfmtZR#p-uC#S_BDk{g`o2!RCTzMRKRvj0!&CX8m z5*OFa&JK`JnwwMlDKw_6R-~*fNls1%S5{V;C8wyyY!qgcf9Vx`$SE5ci5iQG+xovf z%rS>Un1tDGUY-1mPF0!y5ThlxswIFsJe72UU-jpS#}BB3ebecCcN`YVyw2J(C|uuM zQq9*1M+{+#2${F4&HuX)$R41Mjci7tx~iz4s+%V^vn~}ahJeHKB^mc7u0H!1UHVvm zrT6KygA;u0&-ohTI;K|-$Gvm6GGlDl-maIc{BBK%OVF$<74+@w##ro0Ic((y8cEiW zhYFOIvS-x(Ow<=R9b*8D>_6FO^zPBQd_2}iw_S}(w|BFJ0pk0;OF%t{$#C1TD=-&I z+nyvg6&;O|@j^THT6u|bX>~YCImsevO$*^3QKX`u89uo{!R@^9r49D~@P=k2K_#4B z%x52MUL?{;KbwiPY;Eqc5Hfj^;h+xQXeoH10<6)AQk+k=Q6Ee9N3Mnub~szVytYX@ zEB5vsYP_l_9h+(+D@uQQMOmp4cKOv>K%ylDWq@ZvgY-I4El+IR)ca~&)j&&Io}ubb zmQ^XqzuLG@_4poD<~%_0@Y?-FRt908dE=s7kIBW-W@rh%yE zP9>R(l4Tg4ccU^r%N}jLT9MngaGH-_;o@w0KezgXf8sHxdTDKSjYp`=b}G~F6abI# zh_H0U;4U9rXc$FLJPH#cRL&E^hgm*qfb3Q(YS4Oqi>y6JAk6+xFWq>LRN@8yvY_}k zN@|a(`~cL}k;{$UsY_;0>W1qIYm@)0@=a5Z=RRYkD}YgTK}F4K3};T&c~$!5&>%DZ zTP$lHK<#0NJ`UudqBBvFMPS8e0F)xzq2#OH?5yQ0u8yneGQ@m2tWZZzZGPlk2GFWh z=(8<>xNEvp3~MPKb%&cDN-R}S?UAj8Myp@46(sQg6}7IeEB({h=J{S<*Oqu`%qSH^ z4=L?06F*4k7XDwG=Q)SFT9ziJYO=D6iAgf)8y)9k)wN11Yj9(?3^VAvJwJy>+0kwR z9Kc`5UhsQkq`Y8qEk6Ad+gy0ne*OXf*pmk7^G4jU!-@<*E)KZU@$FU+;E@-UW4$M1 zp#o+k(=qcjQKrVpNFy@!g$ZPh21{}r~1_l5F zfWD4V*8AFqKq4Uhw>VvL%4ntz5pjSx7uAA>764!aHxw5&6qos*W#|7Be>BKS^-{$R zy*^!xYYD&bwT-~=j)VxV3O;hmrEd%Ud!!p!|I}{H?p?#Yk5)ALot8aSO6!OaFDk~1 z-)WBbi`lyC77x|F<<5q}8iqtMHBUTkYlRo#i34>MIy&2u3%qU65s;QDgf~s7yR$et zkWQb9a4hSTCJ?vm%JZVvt>8Lmf)i)?FEhdKM}^Do6OWFrMLTY%H;{Wy)tjKlB}ub` zp`x0Y(8XN09MkGA8c)S7dPT^v%im?!KmH1I@(#l18t3Yd|D0rYGi}k2)Efz5-qqw32YzzU0^;=+U?AfSn=%n4mqcPv?4$>(lzpZ zd#(PAj8ip;N(Wp(t{ zLbsbFA#9#)j9%I)7VW@Z#4go@?2VJNKb9!KaW9^nIZk^mYj$0sOk!a8`!|4iCtCN` z?^{plc1e21rtBq~MKd%OUc+y&xzqL!j}Z9`*s82%pBeZND9Q8fH8)Q2TM>gE9;fkA z8oklwqqkme?`^YcY?C{M+E7sI#ZlR;Exh7m|66ME^V*_wab_VcVYsQF7}LjnWtcgE zvZ!0(5yIT|ppsAVP{zlp;MmI>(z4)A{eU9ES)9I#_Q|&>mi?3aR_$Ri&-|?G{jc>; z+)@3Bf&0JR6Lb31cH$hy)_kyxtgq-c0$UFr8HPjPiJqNWQZcIJ^w(XH7Bcm%h{$6z zuw3xaP$9X02u*IF_PkhCahAxFTrwifh`S(~viR{Z5?@sy4)$4d(Xh?GBqgZRR zJj{t;tOmbt9s6N`rwTL9nUlrtwQ8=N@heI@Kl0#%401_lkhi)c5$pb^1Q>4;SMS99 z%%+ z*5{oC|KW+t!{9G43n_L-QXjaziiR`!b>Vps>lk*-U%zb>|a6(-RzRh>7fqn`TsG2N6?K1N&A zA6(Yd$$HhPi8y+NbvDwtH^?f+0vbNkdgO{^U7iVoC94 z(laMIq4_xO>}S8gHbqBAz}M$VCwjpl%&?QCQP$fXocT`dYv|zcsmMgUx=pS+Cadp9 z80==n9ju#wkUM`df0^1A5(CYSWD<>ph7X(O`z>sKBc{slG$op~6Ye8Cq6uyPUD+QyRF+ z1g{80mj~mm#6LvB{n?C5%dOl8ZFdUM^ z5W2iQhoZx6K6KH02|jbttx3T3;_KMA^oJ+yFPUX$w1!QeyAa8hT9nLSzdbl={>gf~ zLDZ>Jx7}A!>poxM$T61U(h_ty5ZW>w%&7!fxoW~6Ym+?I(NNd3-Z48qRqtH3pEAXa zG8X)qqK`q;&PO6rzw&0VSJ*6xfx>Wk+k$jyyKBZu1nyQ&(d%%67&uQjUO04+WR7xi zGHBzpR|qUxO(NlU`rw7LTytjyAajZ=uHdO>%&)se3~cS_{!Cx(ya;UeU5lneCVF}P zaour5d}>H~QcdwhDxtdD)jBVt=Vj`OP)-+nqo_v|yRBGsi#2zFf#*lLs^${k*DAAq z2Iuu=H|`-5roDsGA;McLJ&cUc!<*lw?i=$I?kex#PuL@xB%nHb$Vo?3Aw8=GSTfj7 zkx!bn$Q=TG$Y4-+@3${mpPG**fWKqCw6j3BJh*3P zg$)+Of6cY#?Wl>E_XKUG*zC(J^q(e1P@>n(ii(njh*vGgI8lqiCPd+{rlywX89wr` zLfU_D7aLn2L#~=U&R4;=Q;d1uTPd77#ird#Hxn$(w!t*!#^t#*s2&B!PW3#Ji657A zpUF0QbUYyqkOrCNHI-!>N3Z=%(YR1oSXUFPZt_`6^N|xe?K6JHi;11%R-!q33x;e@ z`Ikjq8hG!BUteU#LA7SXaFCZkw*h;ob+LEPTH^*Es12!_g-IEgLiz!fXIsOD|N9@Z z(Hw?>d3q{tkQ_xPmNFjbw^!3Mshc_Vr<^lH`Ib|r?ZaTbc5}hSe|TMnaV^~C+C6Jc zIufe_7jfnUmgK-^Z1n+GdMECIXZ+dwz;YHAqKBO;X#PrzP=l#Q9mbz3$CAf7Ok{B_E+;<|CC+RbOS>s278w$}pPt9}IDxPB zm&wJ=k&5jv5oPj2jcJJ7?h&1*vXokK&zx@S~U4cT_!nexj7hf zzO;w)tYShVe@_O;yY#u%v5fV3iegUX;RiQTKKnNB!|_ld3vkBm9wqj@o9KqQls^~L zi`)#6S{caPW7&l|_PqPIL0#=|E6jDwu>#+(&JD*U3x8{GhMu|;*I`quY0rZDFmKs1 zp(k~^R`zP|M0F97U*y2Dkg;^Fc;eiiH2;<~2(i-BhJgi^q3I z2ccG|rj|E8k!wC(Jcmefjc|9QOdqGcEg$y+r{MUGrOw|;q;R@T9@tkQS^AXLjB_HD zQG}6SwjDI4=(yu!Rpj5HHv*aP)wh#r(P0lg+?mUJ;9w`%wa*xMS~qf82YuV65Cy_M zTExcCGb{?{Sagxubso@l32k}jq;6&)Qt77>G+6eEjDLK79j8oMvDJ65EI7SQ-c~Fy z*1}8DGq2&>;_$YO{2lQV66LWBLAvq}j+uxq`cuf4@=`waNTULi^v+lWe@Szx&iOYF=dB9hxQcH>mF50~Ym1bwe!S5xt$56hy#EKs-xR1+hegTc zWy7*l32TqluuksRC4^e4lew+tPDUmOiDD1N`&3glEEpQ<2}oF~0%|e?k!^d;sa)XH zw_3!*4tEX~+hp*HGO*K1xN(?AZ#>#a`AzACN0(NqgMK(-xFoyjkyMeDkF7KfE2D=XR&i2fSbu zEi^#zBTBORB+~#59}N_u{;LGO;>=ff+i)wM^hM4$Ms1>$5>ol(R)ZvA+O@~9pizaO zJU%9ibQ5UiG?ea_L##{DzcaQZMwd!+NjN<1R9ln=59?r z-J=(Q9u{7bXb7nP(dJ^A`QclDzOobLb@C=Kl;$`|@x9^ngN%#~A;#C_0ZLOMjgXnF z-zL4WPeBrf4`_FbWqW+m*7m{oH$G<@(n<}pOS9R7sgc<`*-v#*wh2eEPj${?xy69w zzkWA`tUqWA2`EWPivN})VsO?OTQ$qtQ7bL8F(mI{ZMct`_s`oc7Te|$_MTQ&G_2N zrqHKnB64F=cFKVkVX@dXR8?+RCaqa;PVoA)XZQSvauSJ63f>I9($a&hkMivP;2tE3 zAkT-{@s!V}%G|$m)x9J>XByjSb!b1BE{tK0cS!&LSm?+zP@2;X+?Mjeaf3FE%J%h zrq4G+zo#Wb$K;jvx zjcdA8&7(`G*9Ek<0os|p=06+8&(^weZQAN^bQ0PgSh523x`R9HO|8r&R`1XT)3)YmO7iJ-xvSz_G=%AoT&F2Wh!klQ}#&6+ES`^W_7S9IDpzwN0VCY;%=*$|9gDbcpi9lS)9J}9? z*Pe*ZM8q{+6tHaRW!}uW>&v^JZsZ;X0t~yBZ;Db**5o8p`mH>2%m(Vq07HwZq?v@n7?Rj`t)g+qGmB%{n6IG^Pm0vT4#@Ep4oQ=_kB z(s+{UEf6-2jXI+TiuMI%o5#JC~&@{{4o*y!{a&(sxV}ZLu zU&_CCx@-rByTheMX)xcyY`U%H-MYNM7e7klzvO;iAxZ0C(&+f{MiSCpSsDqgqm@cM zl-p|aPA}W4m_OECWeA$GMvpTF-r3Sx?1)L9_Lyd3mFF zKA852RYO3>?VV$eOl(B)#^~eTI*%h0hLp>1<-LyJ1#+C1c#1uk>*+dqQM^VnQ#hhU zm{=$1ebq|JpKd%_oiIz?{&Ag1StHC@r0g_GwM*+`>-kuH(u9`N8z+d0jILR%jSTzs zG6qVt=Z$c>Nc8o(Cr9y?2P88iiC(l14Z|qJ%N7k3%v>dMYArN$J-Lte$Q`g~Wpq1S zrA=5!TV-Mocv|iOz85e3>~*L|_hu*{gPCIJ&y!%&Y zsiyF!HaY}E@Jl0Zma%@j>)}}btBouEp*_clPj^_X_~qq<98*);&E-kRKfJZD>AT*I zjP%M9TmRaew9pPLzE2a!83ArBK4LR)A5;xp(cS!QL*V-(;VIJ~w9KCmLEc3Va!+~?BWPLA5vkPF zvVEH{xd~m2m@!|sop!57idf8nVI4Bym9l!U^Q)!aC+fktp!#qN17c!a6&)J(Z{2B*{aKY z$ue+uK2_-q$+Wa`9s-Uw;evc-uDc*_A!$&e2LqsQby3hRXutb>^u`WrYT(3 zfNNEWPA_?d`tNYu{sa!co1CB(Li=X*|gHm_r>O9JyWwP>cWaSVkrLXe;=u+ShKS8q~AH;`tWpR%usrPON z|EZ=3gWVrTCQFHZ|OGGhA^3wBnHN z-|Uzc0MCnGM>=pR++%q(9agKXrYSf_88X83=Cyx@aB@2}rO-euNQ?f{Xs(^*&$Bms z$%i2)o*d5I_jN_;b6hX)OZ;Y(YKd<}Q z)5XeFDuz20OtWI(AYTF=bQ6}k&ox$Jc0Ods&8I%Tc;n}hq-F*C&kF${eoxCZ2{8}UKcY9xeVEg?09}%mEF}A@XKEG^v91;N(m%w6WGS%a z(v0rp^}KgrsZjpn7)`7L)vOw0P;BSElBoWYZqXCJ#WqKmfHzZAKv-Oe7vI;s>c4(J zHEYZy+GSYx5~NVWa$xGWlRv^<`EeOFc{IxjoUjYaunx5!{M>>lHO80X+BTT$<;r{c zn0&g5cS3IE>vV8UT~FFcIezSbI$hU8tV%P9Xq$28&)wuI7dLYi3KSdkmiX_L+&0-P zsxpd=fF_B#H+gD&j-rCUq^~{gb4R{tZhhXRU_av7UKS+c=J$FE43f!U36Pbb8ej~f z8Xy|&0v9)X5p_UAr%y3kNmV;wrxpYl-nYS&Qrg(!3cg&vPoqDue%L5V-!K@nSwqrm z@p961r0DbQ=yx?xX}XtL$i`YNz}c7>rj?q zf&4RD+jdoOx8;!Y(`_f;i}^QX~(P zzs8)qZH4Ws2klO4WDwGZFL(}s;wD*-7O1(q>$=`^7kMzST>?6(n%!BppgqtKwlCV< z&Mimt<>ahi`MZ3@o;X+m z18M@1Zl==sg?PlL9DBWx{l($`-kSHO)Q2U#3*SpFH|IoTCuDE=f{4WKT!SVlX1n28 zavjqITQ6o#D3x|_GFW@yy zTZ(&eFBXbxp}0el;DO@B65OSQ;_eQGmS80mP4H4AIHeR#&;%%6ph&Q8{?FZ+-JN;% z&b=@0o4h!`bCS#?$G#r}R3)45n{zZQ!$F(;&Yy|I&t$uDo!ddr9M9GfxZi?o1s~@^ zzDZjn)1=vFxNs&{U%vh%qC_8vbN%v|{Gpoj;nND2@#6h=YF&iDZFA2L*nwQ8r`Rg~ z@iI2b4m>NMqXi`Pvyto3rU2r%Gq0*O@sP?+%F-}w-&9wu_S**^8Y^GXtn&JYSav^k zFm}$r7FuBH17{j=?pG&qjU0jm)618^z1=#zx8eFQD4>4iF^ouGgFq3Y=z+X%WP-#) za+Ec{LTZmA-6HWY9+~A2Jd8&*(=dm}<91q@cdkDcto{eXqxp-+@KnX!{iYrm$kgfD za87{Nf4{hHMZI!SvG7~FKhpr5B1j9auhY#;txK{pWio~Py&Qx^yd*mn39*PfOd3EW@O_o^+ORC%cl!W-;wR%86NFt2vn zFNchF)(aExOOOQJ>C1qdl+uEVy$KCz*A&DNsl%N5qai=^GXP%8cUm1Hnn7am3C}86 z5TE)k!W8f@v5XJeD}qT%d{20^_7u?$5D5^bDWK?L2ubTh4tvtxJn1 zM9`Dy;@Jm9pQ(a=QBee_=x#s@00l0_3wl=Fu6ljNO`FW9=28?KVd?+7-DCPE-saaq z;>8s}Zh0*r;_aB<6#caSfUfUMm}`BIzp_1PBWC=7HsCA?2_i3+bT^*UHJ$zcAJUc9 z#rqL{-O>2WknpNFmyvjpGpyr`&kY~H)ckHQvUNg|F|dd{!j`@u@Ar2;cXrTlnV+tF z!7G17OJ{}@IlV_cUz5gld~K;E$N|_N?a)$PR$11%Cj8#cbKhoO%?T>=BBAh6uJ>Dz zkv=r1a)YUS6H~7t`Hs^+8Og}=z!0#upU#(7Lu)*}UE}_k@`;0&BsPsd?gRI34PS9E zAMe|0<9P~hDts9HFsmu~BTb|+P-eI0f6|<2Rr?;z9@Xf?;IPA%m@5COy8JIEyMgib zDb3zqdeLetX8n=i?{{F<+cTNpk?q01ESnnDeDKxmI97Q19YoaC{BHS^?Og-##4!B? z5m=rzayjndI_aT3ERMgjPOTfyfYB$?8z!5dh+Al9`yYSu(`vX?Mo!@1!%I0BJNaX2 zv@!a;n*G4|ceccChT$aLw-xp5e)KE70IC4l9gU9WzyGiP-0OFJ5TDvs3{{sZEA+ef z`jP7ldYYO~cEA$jzk<|#{t>*54ygL8g>&*Y82S%;B|)@?qkoNLe{F_r#t6i}kw2_< zRfQW8R`XK{EMikymM{FDG;hl7ZE<#I6y>~0a^+=RW>Y#KG*+iJ@-LX-n&Szu`mwQ% zeksP&Jng+*Y4N!od$3!;*d-ea{cu(Q28rz&=UNpn`6%aBdj9=UGOarbEq0B($^~4Z z^!%513w?Q?xpetXt4{0k)rNTe3HtDM>AuM@kb#2=xb$})e;Bt!rACeUC;w1&Z`n^z z;5)eVuiM8#Ai-avv-#Sn=1!GrF>tRM|jEV08z7 zsx;F~AX;3#S=Bc#oAQmXDi=^?#x;b|U%A1?oJ4MoGx>qFsEFczhL^b^jC71tBA9ykSgsqS)N!L<0p?F|6YWeCkrZPm{ z$L5)*UsHcx(T(?pJY7VV2QKN>J0zJEBU&^nlBC2{2xzj@(coojgi`bNuzriJ-~j^~8t;7{+yV)-=>i9+p<>rYd| zW*hMeEN#DWsVyEXgDERcbEx&LX<#4^{SiR^*Yj3A=00%hh~JQ8M=QTmaVErH-wCGZ(dw)dAJ0L`Nn>a zoK5)+gFEHNcjY`4yhhnZ6@G;uDnXv}f>kIz3ic;_;3;2faUcjtxiiJDG3kGZ7k?DA zMP+tck5~@~FdBVFj~80(({%C?U!sIWzyp5i?t=iU_k6o)%k-UAduOYL1PNnwE?nn~ zd+9`ca~qp(sb(&Ht1=@MkGQIte++=DnQb9Ct$lbAFnz8n)b@4 zSqzcpu+(`Sux;`rUyrVzb9>H3p9$P6dg0c3CkOOLPj-vJ$rjRN{h%R}hY8`ptm<%P zmMbyUykArp+M2oTUTxTbWptKJ{#fl{@M8)n29htQo~tmckCV6ZR*w$-`j0@^%Q5p& z5B8_9>>#73&y~mJuAR2yfn$w(oynhKD! z^may76;z#JPW~>LoO-sKlgamD8ivPq%4g56A7?LJ!~U$K9>a9w9a_=2^Js<$q3F25 zVv1qnFIP%(~4JMhlS4o_A;r}Q=nh!v|>iW zr?S>sXjO*}kjhX0ize-v!b=x6W}dX}S!;(yp#XQ6xT2{3+^eQmyY5#A0R7NK@-oT? z>4@GtMoGo`3?3JG@BC@KA_*w#4$)=E>TPAozRw>}z*4(^;Fr8%&it5SX>3_)lb-UT zcf&t%*egQPt6ST?drgw)K-|l5)F*e3LE*bMy>1g9$2RwZ-~gdP{+}hs7US^0X_uc2 z<`q5L*$)m}aK4M|&r2IcuE>DGAI z-oMR`S<87E%vIdtw*_5hDFnwYe##(MY+PxgyKN;zIG4g10|sosERaMRO6(y|>uJnf zPRFp1^nq$r_lw2i0t?}`YsZ0$7+Ub4x#@;xJN756RojP8NQc@b(-f$kG1Yj~x&{_A zHU#uglYKJgMIddg^(6d@&kTUDRQ2 zXJ6L=Dow}dlt-}wn4cVDNSt!&3z$m7Xbc9TlI=Y1)#0S=o=!bmk}=(|676&ME-fPk zwW<>5PR#}g)s=)3iBB|7ZA4nMS6tW56tnJaTW(_`6lYgSZwDf=T*7UWMk3lMg)RBCj$awG|^_y%6MQotdj(PCL=z(WRL z{j21o3ch+vLX*wE{~w;>4-A@r9xtiv)MS|C@*K97K76+x0M$mI>V~$sR%y-(OqT;B z2lw624srrL;vt=u3})*DdYY+^j9<4fo(L^|%IWlFDDfHO^4>ULOGiqrG`Icpm(xrbQ5GtC9Pr%geWDftKTf2*cmHx_xn zxQlR(Xz3?zTzm1T13JLG$XYFfdJJtJ;AX}f;a;1C>3^$Nx{-ocKiUeR`WcwykAvri!gQjBEMKA zGgT&mFPFtXsS!#?fdh!-W&sjyslCN?@Fs5QTJYU%JR$bSy8&M|V*^g0s;X*Ty`001 z10!`e9X|ID!i?4T0kgR{3it$$EIsy`u+54=J0<7@W!S4@M%Ve{{w{@_VO-##q~wAY z2q^l3V|j~$fk8_Rmqv`ARRW}-7Y8VZIQ+_fB;jBPGzMjGM4_C4tx|(2bR@d)bYjL z+YovlMC#Auofx|$_1XC<$NkyZ-3kmd2r>IudbY2J zAxRh)=>iTGDaWg{l}t^ebuG=3WxO(74vE4VFA@iG_Jg20!qT#Z^lz;NzHboIAmgO zy}sxzUQ(z^WK$XXR5cM(WreUh%vhV;={J!Rr$=Zn1P-Z6hMwTv4@H&4RepIiOj<9H zRtC2C1#dS{t2MEii`1^vTm9GC1*`YH4fVNBjM$)Pb~wkMa7+u3=5T*lW!r63J7KqoO(#apDUsa(2?+(3gYEt-njz`%5O7Zfp4 z%5ni8VHOyZD$QtM5Z^ttWSXE6&(Mt~Mr~52jl@N}4L1~iO1Ca{Mp%LgMn8Yac$)Jq zKhVk%$pEN5AY4-?2zeiPGHfk(QpvQA6Tt>%-_AukoolPM>zNOj7hQ#4N63CVCj2GCBt~DL9fXZu3;W_Dve`C(2aL)2PdpAXtU#e5_+5X#h^DQgE znBT5-pUy%v7Dz0e%0EX=MZQg;>B)=O8OHIKUYs7BW1=&u5FOs>QkF?ibTcU0K_T@D}q2 zlUoh$UuBu<@@9Uw96;tQeY2+Z=3R_YK+K^e6J(=<=_BP_7ka7M1zHUK`?E?wc0LGh z9KcEeSn{2-E@>B?W-s=Tt9ukJfK&0z#ONyYIAr zYP*-u1;Y=rB7LC`qTQ|eT=`R!M7|uFTn_jJqW0rt`A_5ZRbHjN2xNFm@*u=rm(skk!_d1 zcRO=^N9rEv;4wpRh4PyQ)%Jkf!(>di&M_QaJ>D>y2yhj%y`A3voUZ>d+8zZZRD>cNj+={G(c=|IJNVAY=wC&RjPu-=CtZm zI-gb(e@!CeFTCaQBGUb+zTF@`=K;avt*miYeS6%2Bb-7hHdo(0-J2Wq+E>i=&C z7`(yWkufqbX^F@CL<8J z{ICL#fs1AZ`3d>2Bt1g(c1p&W>cC1idhyd6rZvI zO2i|Un7pNwkZh6A_qT3h0ekshHl-=ra-q6cv?_6`WG(E9y1vsu5T$iXw&EGV31gh9 zH2# z^6rWYQVl7JdlZXvsp$HK;bRz~T+OeGXo`*5S=Grc@xpO-CR*>iyH&>hJu~Mg0LsYe z&U_3T`CX}mW#^HE0$#G;9f&uyASI~dEmX3diswOP5awG3`+YC!?$^iE|1~@y@lE>< zwY2;R4f@a5EAL0cpZ%!I++$tHBiXCli8@}}l-H(jarif9qJU}=@Fs8eoEYL=SR!6H zyj@oGSzR$A6|zLN2ub^k>%&6WXy`faCrX4ed57rRlfT!S4DXzCX7AUFVAZ^FO7} zIXLZHbaVr1t27E9XipJ@`Bv#K55yKbZwz%fDRv;@VKdVp2|&RwoBAu*lwBQya5Yo-~)EI7T-DDL}<%H6AkjuFPZGA)_TWU$tOT;vyM#}iuLLoJeZ#HklJYb zJq1Ovc7W)W!STd+=|R2#J=$6^^^0Ef+ICF)+-@+T3)gc-XC2n zmqJN}6Tjo&ld-qWx{kHqi3-t5SBkEdylTTpCgH8=WzSoXB>8>_`wRt2JAZ*e!lj>w zChp;z=S~Z0BB-T#_x(^E^+4AAH*}8Wdx9_Tb*%yJ-PKsFXivCC77w%R+!E-vTu%WrCfARhZa+{={O;s}{ zw56sn@v~L>40+31!XM#UsDB9#1E1~*{UhLj!+Wl+y;iofm$OB>6LGoMT3sQBm+?Wj z(N+pSQ%#KVOuI9ltOz4`&$fGksZrGR84{;}OSB*iF^w1@UEezUmVV=grM}n+uaCWM z3MYsFn@7yj*lX>#T;4O?EBqh$z%K2>nfQd&zsu!+gnn6E+cb5F-xN$8E}`Ne%={rA ztZjjNKtipYUFD^$q$(4XsW{U!`JH+>#%jZEqL(Srt1tG0%*i)Pe9%SQ&UgDE%| zo$?F{$RPig#PR!0YE49j?!7ak_1ebs(c{JOu}=H7Zu(dqw*#=!H@hIwFnAO1FpI#f zksD*ggM_t&7YnjrFK=#Ubq00vZ+gkUHOy&m+z-9b&cnA4&IZ?SMcdSM>xT;kR5^t^CrvcTZqQaLhQG2I;A|?a0|RBFxHY=L^r9`(M+la zmD-zz!m3fyh56p+bf@MGoNJz(K?`B`x6RIP?75w2i33+y$!-tbG8;D?`Pla~Q`Z|( zo=|K zmHtps7bb!~uqW0$5Scced~6j_;G<`R^q%Zu8r)lulkKOY6MB05vSG}BjpE>o$Vn4@ z=;!`4z7c{u1<>%{nOCg}TSfl}DuDPh*;;3bOGI}-;>!Lsz6$au!9*ATI;!AXdVckX z^!CzPCE~R9XC>>mV9_Py;|it^GIyTAYN}7)L5um>!{@`NOH>0*u~`##8*Gy^!Y_o-Wwk&Aq5O~ot$)`_pD+r@fBas>bZ6(oYe`S>{|FisydgV@11#H+w7)fY#boEpTi-35>X&Pr z=Cyff;_Z}N$IayNGqfq1@FE7+@{fQD!Wn^BcGlX>>Dd~@^K08~4cv6=9awNGh}z4n z4V#0YG}BF<%c|1j*^85#db#M^^@VKyuiCeM>9^inIAC2{=*2Ckyj8@&WM0G<*^ThD z+dnJE23L5lZh!7@#DRMD&nk)fEj*!DRsok?6Z;i@beecm*~V}~$x=Tldin|#?${NC6ym|I2+R9AY|Lkw2a|ci5A2uh+EWa@!0_Ki8p5k zGmbv^kx@}^w9dn>s5Pk{kg8a>yWtK;A)ReW7t?;WOxG`;T#ZOvm6zu_3Q5X_6LWu0 zVSkd){?$WLu%HHj_c1=5CYRrPaiDI$#=8%>DiKG?#!4HQ!q2mQ2iDFOZ$oFq@fqfD zpz5@L!RgNhxeQmO{{9lC6+U#~sDAK1F4h9h=n?GF(K^~5KJL!2b`a7pmx|$ej18sr zL_)o4yaw6a8kCTX$;XJprM#PVu_B95DXh9n7v}H@GM^kv|5W~d3iqMaaNu07SGPy6 zoO#H4P>zd~uO{A5Rrq+^QlT>lOaIs=guIlS)i(&ldm|5!& zNHI;PVo^2&Jx|T;EazJ?L50pED7)tUa%JM0Ea|gpz3Dwf+%A~CjJxGfDr*VFsZwTqy76o(LLFj9uxZhrkyOquig$TH~9cF#_@byTI9xd(38=B*t5+s zptC?F@Jz}?M*M>?A<^L@IZ^7K4f>hoDZ74w*0#(> zhPu;D^A^<>k>0HDdG$M}WQOOTP(R{lK#`m^aa|~`Zp_6@mv-AB>^9wepN9!~pfyWmtW6mk^F1(wsk&GoVWs#>f zPM;xM%q42goryL=4SZ(21d%VX^LowAh*v+ zg3TfBW1yb+{z|f37p)z(Tu+749iVz2J<_Yy??^TvYhshV4Mh_0akj; z-kEtVxxCbKSc_kymuvA4&^MN`w@d+h75JQNurj_ec(e4JK`U&V^!i87F+DzriT9S_ z5WI3egO}4E0*4|F!b>mwRvL4!+1g0|5d`fPM4&zRD3&Zu7hRw;-+bRukB>aL@7%OU z7OGKDzFQXn5I+z76Ot><@_2oWC=E}Rv>c+RuBAq@YhuP0XU7s}HqDfyn6`6?7|1!q zFcTy&snvHkeAzpp)R!a7(ToMu@vN z_htKb+NBG&UL0zMzAg#+;Z9l2$EDT27qjfHBqGzhryRsg#vPaHdK(vOM5U_wyM69) zu5HX^;}`yfNUk#{-HK=oHqQ&vUvG^%c%)j`OzNUuy5K ze~bsKlZF3ugBF_ptTtu%ZHfKjm!wxi!2H+mjyxxDTJ`SVs!=bMcbOg9<*?$e?fS!- zxkVIC{BKq5|3>R>098x!2!hR_wydD(s7*%eLxiI+O|`RclhLU=H( z<|`=%`#JSMTf$^OjM-%CcmXzJy^)#`JE!`0#mr|dUz24b$h(#I<1vp2&A5NfxuEoq z%irCFJ6V~AoLk(ru5X3pK+S?RT}x}wecHXl%kG55Gr<8aVK%IbA|2k`N=$I^ZmH^G zL9ofUbT9{RJSm43(+8k|kk zZo;2DfpKg?35WO&{S-uowU0Ls^Voz{cAKZ&cWLqao;<@vK>ekcO5-u zkg@@{iB6ffjkH)m_43`}N)1XGeP0uH<#oGGB|#p`qjt~d0~pnxeeD6reHuZm>wda} znJsL^!fW3w!DzS4T-VrFAenqRkAwxuZ5)Scz4ERljnSTr`*%rtm*0B)Ol9*|c1>T{ zquH-<(AW+Rezd2ey1UapQ|uHj8`61nORG=_yH#__IFLy6E&7f_O2E9vVfn=64CL4e zL=+;ppIM|R=OQUH`tH-}S5;L{o1F?NP$J>X=hS@-)uE-{n@MH3*5CRL0Xiatyc?8< zG{471uB#(Ar5dIQvyZ({MrP?Yp+GU3Z}Ae9(O5>e%~>Ib^b-9If%glZ<nuU6LF@QffG!VWTTv*@;5_-zmQ9oOOpf1}+Y5?6Z1IkK+9O;m_FHh+FK1Xq<42YO zklcW#(`^E#GvPIsn!3<;@)S;Pr<-w%ofRI-IdXJ$tDA@ul;!QPLcF_5zFYI8fTEnQ z94Mo@y->r64Ca$a;AF*xy4Ke4?Y;W@vpT~|!Jky<1xkn;gRWY+yE-}V;qyoCnGokj z9=dXnECKG~rMYc&>2aztC)4`C4CQtxkA3`CJ!hSS z1kLvQQqkZ`-;}E8x8+VY);+ogVLhFj$42*#?XRXg3ws>Q3j_G~&k2>sohlArd=I+Y z|Le13`6$&UT7-yeY1dX2aB}j@l-Ws}BvEUpOaF*;WCGkT-4+_Y#b39@^ElTMCfLD~ zdtRcMxN!zuQA1fpYZ;Gr!PfVvZ9`zg9=d}oj=c}Otg?@qhG1rc(&m9~IWStCcMfQ< z)IWlop3IYT)I)7B?dv;`;NeVf__$QU$T?#uRT7i?56Rlh@uiJ#rb@4GNe-(MOh9ow>Z#@;Nrmftlv$>{QD`mqW za~cKo2UARL2~RpAm_UvEt=bn`Quy0uNq@NmBDpmz@v!LboPVb#u5e)aermQ~LsA5P zXFPH1l&9%>RMNQZRb8 zjIYAIV~|F!kPcHs%Q!B?66d|k%wyY(om=Sy&_cR}z6v&c0s(A-LFTDGh|s;k@rl3h z2#b~wQ;&iCa&!;MZ{GACF>o9CT`V4O@)Kd5$^$;PgiHL$Q!dlhM=lQ0}b;X8ZA|p+~Dx(C1YjG!T%p<&AEW ziJ*g1=kYelv?c~+E5|f_*O{!%AZA4mu#faZ&QVdzDE~I?1d2r`?RNmyvN(iBVi^F@ z`^Py$ni87!G!xcneEZ>fiE1d>}NIO=+u-2Cffymv9T)UZe8n97d;)_itA zLd%>$Bd4suz}&K@K@gb$*r> zr~au%OfsD1Fi&AsM`3H;XjO0+C+Y(c8v+M~{xNNE4<0e8P9%H7Aj0VJAt0n)W|Y|0 zv^W%cOq<{NuI*wUQ*_>7HrsJ}LZR8ZRgQw>qEe*LtHbq_jna0odH2}?_^{bFSwSGm zh14enfl^FZ1|3rt1gYm&{>go$6Tob@64+ty!bjAw3c?2oz88SZNe2vbpqmy~1te#( zl62c&Eiz*~QSLIos!upapL@<&DvCmkf9Pb1FKfB|dLV}9P+O~y=Lq?+5ZKP+Z1|65 zu7=D$k2cH7jYe6e=6Wyl-(6$l>Y$iTx9_ZTOxR;>Z=j!|Hz?mzGN4LB?ff(?K8~)O zEG5HOv=Opy7Q*aPhY@P6!+FbY>E29{oX8ACBz)O@;igeGT`5E-@6#S~F`@kVADOxe z-y(c0n`E+%Ws~eAFWNgq^u#Rk`r`;BsHH%x(g5Q`{c|q=l>;Vea8XRXz}XcLmy%e> zcMszaXYKUX{03A69u$5{X#dR#DCcvltl`<44Z0RP4ol^i5_+=1(I{%$ZS`}_anu8E zpg2UcSIgoz1b1lt67Bc51ubg}crJy3H8E>QU}9Fu0p@ZpThO+vM6Xb6ovsDA>8E28 z+k5&s5=Q=;kK>84!vXNlG;VkLr;ib9t)uG?9qd%vXjfAlAo(vCBl!5=T7pF>jER1! zF^MM99Jw2TAtM|eOE_uE2b(HMV+_73adAKsZ>ICjil(QZo-@Q*AW~ePMX9XU+>L1m zjEl`x*lKfbEqlfu?8*7giFhNt5I)@sE`XPibnml28O^c|tui;&UIra_v9!-bKDqGm zO*uQzV8)~&K6K;ODE@%wLQ0w^jq(YJX|v@V$!SIpovpr-cGQ5;!0Pam}Ac_OaXZtv1P4;@foW!rg8pJW@vIN!)2hY_*U zbVUlEv81w95SoX@sy@;IKGGyNFmMxHaIakWe(chK4(7~hNc;t5ww-pln2fH`u9KP` zuVR3Rth2{IDKF!$HrE{b+)3ARX333px$~xN*m1CkHCVO}95y=+S5)bpO(uVxsj8}L z*zu|z*00`L>wxtQ0Jm51!h68jX&_UWn@y?{z-zPHa0?$v;|+P?oy)%Hf!2fbhc(G! zpEd#Dy@>D^NRH5JDf0)5YtO`1azarD@8b7Fn0$d+eR$XQ06y>VkdcMc4ry%Yi731e zGgC-HVxEhYrjlw>pfIPyA*LX-^hv@zU$+T8RY`5}t3#c=^0x`4$rBRgu``Dv0!l6fNlDEBr3snbzYhHH|>ju2BwQ=MFM}&fTh{nsTYN z0`|lEGkAw8TGcQ0LFXGy)+~Qi(3=Ys#B&P6V2^bt;|JMI+x7fyg#p_ zJ8kFBV7kM7b?9$)Ai1o}7#ZY;l?|6VlKWEgG!Xu@8z&`<1}sS;3`maHWsjNK^j*qn zL2&c6uMnw6ic3DNvwsfQxHfUTtM9}c#-{-8F&MY9Frw<7Q?ySC2J`Zjrck17O~ z-@!z4n#$mSdGMUn$J+!zNkQf3MNa)4l>FopYz&<7y{Rg9Gt*j?mpccYu>Uxew=2;wHF)0gW=t3!IM%|ubV1Y!02CH3O=enFM znrK+or>HIU#N&{zX{c>TRy()zoNK^6pp9lbCPQgF-Y%yjI%_{2`u>H+wVEB`qi(3( z{rJ>di9xyXEi;~B39xC0nP94Z;64oGLv$efwnO2e!6%H{;1Mcx)cl*B86{_`8d$oD zGJ@hU`|D5efP&H&6mbtU{SSOmcMYsNEZvR$%m41gWn+uBHq=W@0AcIh9Gl=*lNTsa zOf_8&OO|+~6MW2K62G6(`^;&W*DZ3hdADLr2RblwQd6?yq7AbcJ}K6n_8&o8d?#Bu z{w1Jqfrl9qZ~#)fK1IJbJwxZN;-3%cG^m$7J% zApZSk1W?A+aPuult zGdq+RWX!{z{B#%13{x!4dklnFs1;0$M|oc6EO~ zB_xZ$45e*eOdK;8a`8}F=2zD)Y@U0UWYY*a3eZHSfqF3pTew6P{_r7=F|(2co! z*0lw!$Rrcbj@%y zoC|p+ssTtYodg{9K|H6GSH$5)|#otL!5SjN7&5bIQbKGfi1c-&^N zF^m)nkY$V)9-LyEvQwTN7PbmX_k5kEY5Y19Bwi1PgIsc`E3I6B-&IY<-UB5r`4XVj zrkVR|Sy&uAMvfAHvSPXd48tyNj&@tsGnWo%clW0@n*=iW_0ZsRbBY5>kgF)cd?t({ z@eO-1IR(tL&+X>?`B7Tumj6Tj5JL=o!toO&}+3~EcES|$n-{xc?!WzUTx^*?f!J26Pr)q z&8T@)9?WjM-#k7fJT{axq-`i-$aTY3X$S;b$6M^JF~7xy#NvRXG>o)j8xyv}kRTSm zRYvE*xiO^B*inby?MB9EtYfEYA1pv~Hi}Vxg?fR!*Gyxd<9UjE>XLDvo*;HEJ#b6@ zn7ER97)O~Q6rep35%=aocaCeQ(T!8K6NQeO9nGXeZy(nUN?|34H&rdvEY+q+-Chpp zSleHpkI%|Gj0+<6@nX&iFq{bHm~3ZO@%<{K$D$lv0V=h-zv*tcsqsPCK54l9$Jx}^ zS1K>-AjZ2M6L}O%G~-)w@w1C>lg3_WW#3Pu2Fl;pHTwMpc?CI&C`RNsj+vY02P`Y5 zGoQN*ntk`6x8Yq7E##X_mp>9>%XdP06~Wn>?2wQ1ju?#T{-i~!&HhN!CFH!Nep6zK zX%phKxz1_d6cY7?&o2(_FFXu!8>vea+z#NS&6hxlXR>u#x)V}E?PDUx9N0qMvVY7V zJ`Jpk3!-)C-ZCu-Kwu|YJfq)2SfYZ)JaA7RWbEZnF0s6KYhH$V3T!a7<}r~&$yJvg zP?M$en+#UI@AT0eP$JteYX^|D*JON*&v;nC^CLTTl2`h$Soj}-e;lLN8~hcZ;b`qd zKPl(aw>tb4z|!-3%gRwVXZV$efHn16A^oc^1@AQP1ru3sJ>`UTihMWc>(kNDI_L8z ziP09)l4*5;F5Zxb-vqRl^0A&?8Bqa^UKqHUwr#Sv>#qg?cs%g4&umaU~O(L%b-m`L~RHBqHb1BTJ)yWv2-fmX1xOJe9M^X z2Dx}0vC4~8zopPx7`^82z8ldqcl)4o>L0;}ouf8O=$ithVL*UrbP4~ zLA%YZ58jn$wx&5kIKqsf|5`uZyTdfW9H2ZV*OP8Py>FJh_Jv>Q`_WVOL+?}or8Ki5 zPntkp*XHV(e2vIL>=UYYIXeqdM;*jqw674jCpNJ_&NvemQ=$_D}++8P@D%8Xtdm3W-9uAw9t0^|G6Ept2y z(EE+-=1$Qur*@6=P9q+hcelI)INrMybMALBKQy!L4LplPEb@|_TEUBt-nLfj+8sN9 zU_Ut!ztjyG5ngOEt9hKUBO&C)US_}F65NkzXV366{?5}78%N)hR^njWxg;~=1BsUl z><*V5Zrpw+I%M?&WIhJmw4nKUd z(#BJ`m%kV1jU>is$F4KfZ48ccj1AK{6n|Z?*YcubMuc9~>4X}2e{jn6pYdz4pL7H zbN&Q9Q_nyv#(AwAmNj0!z|m?$wC3S&G3wP_xR|0@<7R3*B+X_Q7`=Hsk~-e}4f!s* zymC^5GRJk3twiTmwpxP^mATQ_iv6QlRCd2|B+R0lVqI=q>c zgS$Ss0Yv?Vo~22~5I*nJ%$C9M!XFwRK(J25E%xeobLgHX2{Pf&z2x@a?R3(Anj%?oY-71R zK3mQpVJlaL1%K;Ukym5GV57>!*MdfXS39~MfN7AwO67-ijFap;ZW1W~ahaDI<3vza zw`qB>YWqEPpLW;nPfaU9SQ>koOA0v!kt1@1Mn~4GbZV-!Ovr@gS@|DQyo7pfFcu?3 z>2)dVN=FmAlJp`e;31a({`^#WqTkw=?p{cAP}f-8Dp3mD*WZmYo_6#7{swI5I(dH= zZ`H&8Ci8{SDonO7eKfEiPYPk?ckDlrm4ni$*;=8715KM_{Imwzyf+xGX6Jjpz@{Xe1A(&{gp>!v z;P!s&*EG8x-e|-|&BHoYQ3=!&Io>_Gl-XrXcL`FtH&qE$J9z~+pFt+gHAko{oY3Ml z`UM6gB*M`$z}Vok4t7c=U?y_%8YFfYw`k10d*@v90?r`je@Igy#^Ge-1yaGg5x_zP zhv+BYSvwU{9zaA^n7tVfWU-sULx!H((Rx{@O3V*g?eA!)pjP`zK2^NQ zOgi4H?2q8mtoA8#f3Y`c!cYWf)UmTUdeL!Tw(Y6+GE9`4NLhjzYe=a2=~Sz!_Q3>Z zFz7fj^?3#C_eRYDYeKSa>*p+2!;gTPatwQ_c)c+v^(Fsb^^v1O=74wy1Xz{2qeML4 z9-icM^{ACWl89N^Bh$5QK=8XqruVAO3y^`q>n<9&>X5rh5ghNqCt0;W*?^t3EKb;` zYRxnfl>EP#d#|XbqPN`_L{Wf>h{>nHY=g5dJ}wFr-y~1(*jN0&9KjeQM097e+*}x|KV_BzY9}x zE<$+*JO6SeqO$U2E!P6iu#bj-Dg9Qei>|KKTb)Zcbcx(JkUk49r;`%i-PFmT#)~n@ z9+SDiA*8Rt-fKI&lVh*-2e`6SB$<7|;b?to;Wy*5k%HtMNCVUu4YhElPE7 zq>o5bd}2jaeeU3_^*}VqWeT}eqRf}OrM4}_l2@s5m#%YwBhU~28b;#=Ia?{3R7jo3 z@Nj9S??D(uo1&gGTxNc;$U*HCmPKz6Oo)JFd;iuZ-DlNUpK6=Ojs*)>iY5V z48ECX-ps|0my!X6#6fu>0Rmq*WeuYdUrHWtsdV^2x23$;WR`YKA)@DQJzk>~5TqE^ z(Y~Atd!`C?%lV6)`k7r%`ZQw9z6S?wFNepnga&*r+|Jmt%`soG#P?ncH0qFk&9igE z=qGcH*YnfW4kUEk{HDZ$)-EaRbH@iGPpge81FT+o>mN>D(}t&Wzco8vRhKf#MWUqNF!yLQCv$Y zV|qraqKnod0ZOW`cn6Us@So{69=r}R?oXMe`L$%QS}loAP7XysSv+!p1qZN@MQ;&I z(iwHhFsV!&Fcs1UxRMf(85jFv`Vm=kB90s!cPQ6V^kaGzPzW~JSlTYB$o65{_qplA z$!7vSn&`fw+4$Y{lYGA9VpS=|oiHJkfu>Z)sOY|)^l_K<#tfT6RHq7AaE5mF<3AJWQ8y7GCR00f#+FVrYUe2V$ z%Q^wS_7&yCghP)Rx##_vfRezTpxjhHBb(XKJ{bn;K^L0c;XaoZ57&}_sOlx~UVPGd zomEz2_?^v+;1LqoZyt(vr}hb24mf29y>Jf{C(fnITcooN_a*)kIz0~9*K2W&JRNeU zposc@*o^MrC#Ci$4JzdjzV#ov@_1r1w;JKK9q1ou>ROXls1NFI3h#oe7v0#A0N@6J zoz3_)5Mg)}dlogVaTjlAqZrb2O%{Fy8xcgk-t44(d`gRk0ek6+leWnB!LE9u&Uao# zOPRmRT-5{1)M;s|yFYxhYJ2<1_AAnOt*_&HT9o_6OIM|ZZCW5TzFk}lwePG-Gxe^K zBg@d*G86BVxm)<@#MmUm+;|hqqyvgcJHj3ui;ii9i=4i;Gp$m2=lgm!M;>s(R-a+5 z`}kcm*%sp$1rJg1A#~-%fUw{e6UWJ>rW7jY03)9-_{Ad?OdJzknAAQW!BM==*KLZ_ zk4Z18%NoH~F#WKp5i78X7S2kcRC;!}hst?ejJg!I-8=|mF&|A#@M(Za9NN;yE(c3&P@*9cMLU^V$d(eJ_VMBm8@57XQ%dARX~GA^(@{)A}SJGGG-P1DUX zl5YkMhzlNTV#IJKkF=vNWiNvTdEx6KTamWX5ACV9-j%o>iOj6KTM|xnh)7S%#3h4; zCAUaq;g~@C?11|bJgU~sh5d)#u(hU%c6sYG!YMhd#hLnN9OqZ@!n_oYu4P`F27`$- z;*L5#)R*#S=x$b)L5VNo5eGmhBr4e~@z23kVS229f3nW3 zSglrJ@H9NB@r@ct^kQ=RWrO@T0~tS`onpAeP3Vs;#}CdGKbd+*aou0*q(S&arI~_O zxuLU?m_or&j`&`Ke)?B=vXmWN(;1+nS7Tuk{IDcxE!W$@4u-qvFiH}F`@QE%kmW`s zVw|WtF^uf2PsG*)r+xbbo4=ciE24j$*O?RO8x_CO(0=m5jU)`Px{RoEgp`$XKvcC7 z9~Gy`2g1VBO88ILx!!IQGeHzHm1N__=7X_mj<5|%CMc4*C zWH{%hFq+ODbI3gG?l?;KRrg{@-1{?mH3(>6keXUo`zM4|x6%oEfcS+G+fmM@<-zG=IdsYcO1i+ci?pki{r?m4XDHp2xXytVOr`s zL-j@JZ6K~xiH0+9Cgtj4Y}-D+Ut7Pt>!UgM)Ds$Fci^DF!F2M-w0Fa|OteF)ECXdd zK?L?`noNQ97o%=EQ`fWZDd>)MKin6JNCS4k@-D#|2pB74^pFCjrVy>KW!1WgrS8Yqv1SNhJlB> z>qXu%XMRU78oq%}qdAE#Z|!`{vPr@>2u9K>z%jrPx{LkA^$R+(O1q;W@K-S0PKm&@=mse?1xYHxqhVz4#Gl@9OG!z&v)Su z9OlQd+bjP5Y9F&*Bs+Iv@8#di6n!xd7@`;37vK9&|HgMh)$dDVu|2DBh8}Fcp6Bks-91?)Fp<6Y8S)ysr@oEw!b2sp93P_ z{j#A3wvbRFh~7%LK1AmTdc}g#mX=@=B?I;BR0+bV$))p-N@8E|);l{vw_U~=cbGHG z#VjY_AI^Jo|A}eJ(Qm3R1z0ngJl;Q3U1`oVULId?e92C4;A^Itor3VES;g|LT&!3) z+UpC)N<>>J$JyP?=VCxce@Ir8zIqqB8U-@yOSv%_L*0-tEWFAXm@IbMIjzX(hXsjG z2nl-3x!+Hr<@$DCJ;5hzu&m;yPg4xnIIbt|NHi?}qkdngYTk=(* zIH#7~7%{QoDo)txghm)p`n##9@~1X!=l@o5Ii(LqY_0 zPX)s71Ts<@qR0!9%rVPgc=1|{L;f)8i_*}idf3F2Of;fiZkaDVlb=F3$&^9#F;1bU zTL18e{*fod1XNmD+SE_9X|W=>TI2e=4HlyC{;uKmyB#Ige>mWIkM*?}l*cXYE!NB0 zUCn^S<3mnakNi$iu_@F;CS341^v zIyZ$b73`Mv;Cc#~KYA-La>0~K18zVfSn1!2zhn`kK|907RSBR_P6b50#8PZ^d5h^Q zyx`_j-jo0!TsZ|vG#EmgYVT>4;J5W^p9FP4I2-bnF__!T^QGeHoOK#t-7}Pm+X5Je z+wams{Zf-#GB54&;bed=ZNUr?Seov{A_p7#vvf&($v-OkN@vxlHQg<2JrU%dbMsRC z^Q6CCSfHfMJLY!j5RXWZGQa{X?_HjNetRKH;bKR+=Ke`pXeN6#@z?`ffO)#e zVfv(1rM>VphS+|@w=3o%7x5EAY{u5iQ^f|HB996v`5B!Lu9n9D{we zn|x#;nfO{EUh7Olu{^TlY^#8H<%IRR>^T|wKu*y#^;b=&j~>@NQzqdjta>val52sg zEoSv3<+eOw9J=?|DfFM9d6{5Sj`zeF#K|w8zYX$=O0b^RigkPeU?RHPOVBs7jH8Z| zG6Wilk8ktJ%3{CY?z)NeE~1c8@JT`KvP)t4BhRCw3uE5vcybKuKe~BG+Rdf?C%)e4{h`3dA677_xW|ucROpW2 zfEbZIBCj)a59*TSAEw@eJUX!jogj+;N(}fqO+xN`{p_xv!hXiF4`)8@o|^{z`h9-5 zh&I=iRLJid-x|+-l|&BzWgaM!X^{;spcP!$S2|&i_cLAeV`fZpx04Qz%5+d50i3{- zucA_5@0=nVpLPJ#xUUCMm+a%k0i$1mKd_ zQO`X4pOkp)TrF#Y!%@l;rSj-BohWjs`=X7sxn={Y+*J}78KTXs{_zIlPQg#{fr6t9 zBIMS$$=g~QRkS#ikG=iAR{*n8*^Q)3MMa&8Ful7_5P1e~2K-9$6PWsOl%fhnijU1! zjbc;!yk!%FDt)Q-MybCojpm2KLiD#-B)d0g!syT?3ccBxhOZ1H2f;6mMZ%jb2ian( zc9hVzNhA(xLlpULc2Wuz6|wVEVG;&kCcSiHi|~p!Xay}1@H_`*Ul8czfF2ka}>PAl}PX z>$#fs4s-I;PCm5}X`;m7EUQZ2dY!xU?hoTvq)5t?k4v-WZF)71uOn~9iJK-8owCxf;}Tk2`c>D8Q28|Pnm z7Qd~y#mKgRmJ8jE*=gPZk^63y*m^onO=?bu+c9efrrUQjR>V%51nMxenh|X$O1}PG z={Bd-YlPEb%dS$TPyBmSu{OQ$EcG47z6+CBSeEUK(5!U&NDui6uSC}`3C~xbO9~E5 z=<_(@Eo->6N}XKXXMB^sHbVPy-;Bf<-V=Dds)KA7kWGEys$rxxRM%~+clE$L^`kyU zkL}ugYrLQ9s^do$@I;H35%A-W%uDIk3y7~-t;U3SZ3q0P-SlkPglbljJ%dU64M4aS z66$2aJAV0HP?H}T?Paz77@alzn(;@{P3~T5m~RyxO|3+Eq1VPhAOgZT zJU}%3vp)sl-ew{ z)V#Fx)LoNeU!ZbI12T|z_?}_dTBzpJz&BAQM&=<|{5dwaAD;)h)TU2ve3%N{-~=*h zPI7APT)hwUL80V&em>*3l*jw&qAodf*rEWFeags9kBxdCimo!3ezJas_!)T_($>B` zKuo0BVVD!MC$uNnyPMccQpPU~K2j14SkFUcoj?OT9yg1M&c_Nb9mX!(jk9-TSUM=c z#Ti}SE}CqP8m(8vS-LGgqMr5s(Xc97MEDQKxsV*p_=?QBxSWIP?dP^7j-Ah6i@5AZdW$rT4zbWg$%61_Ny>v9VG?#Ko^r&=c{Y4x6=-1iAuz!{r2}7 z*(McXd&ao_p-j`5Og{)`zU$(J3#5#CV-c`lZ3OgL=+hqax6b=3o-E*8rjB(x-#o*b z0d&pQ2$`20l#n~?Q>!^-{*7TOcy{OHrl`33+GE>QNcNOQqn)z9;~Td0-l z1~+GgjgukqWnGQaF_z@aMq2NDi2)tbZ?6~Lo4q%meZNJ@T7MfN3ch`r4DRj{+w6cQ zyHJeQi{*!L)flI8^@421y6j2K-Crl^Z}NIMSKX1Rd2;V4Lrp&R8eY@poQ6UbHg*F% z)mzYc+-V%+-tm_LEVA~{W-Q+-$sJu+LBrCqjx3ZNc7HM6t6z0UPA(?4r5jhYKVv?X z@t*9oK`tc~4{*ct%%$71Iksx$U;(S2L<={Ok`z-{J6NQ?Dt{h0jQsnbjzV>rUqi}; zCmKvdi=Cdh33v*fY-$&zY9^8CHLKGcVsPqy1gApSX${W5w1Y|8ppoWMLwQg-WVg*m zuVx9|FO~7L-sc10$qBhJ4==Zawy>Tm>kPB)O@Mcy6m}t)@7Z-l%&K!l$v=LTbg~}7 z!gUf(k6z-!;G-4RY)tWmE`=t+@;tyCOZUbXPF+3o;-L9nqwN*1Ed_T`vejgyq8=T7 zduncB{MBdl!lS5Vu&MdWXnS$Og=B1UUFLvG&n7KBM#Isa^8TiCD8nmSpVcSjQ!*Nt zu}qS^%xPcjIE0b01@ulnait;lR$rU)y;=&7ccWjyQO}tdz3)Z#kguU$^Fxn|nqmQL z9)=GK?$E8`S!0H%C8ZZS*@kB4E9OQ2yB2WK;ph{=$XSoE2lMXTee4ri^>0PSP7&+U zgfGAu8PZHX1V0uSXN1||-R`Fok|Q!-tCqw%UZYJ*SjlUDAPW<-Q3%3gz?F%ng)Drv z1d}Q#tu=mZ&7dmbX*hvjVtjI#6|3-J+*O9+TdS!pmM8^Y8sJy?_LUmWOP8X!i5pwKGNj3aw&rOIObYORYSK zEQycLhW6ok8Dcay8W^T9lOk)K>vUj@iMO}+^U?sjrOGmF_1{hMDWPC~MVC66!K|F| zaJO!W_LK}d#S0WgbQx6wCumQuW6gNFZCj-8-~|Er_M80qg= z<>fwIu_2D)?(YX7T6I;4kM{I(Pzkuae!1!v^1*Xf>qd=j&{LN^J>&m_qYId4E{vt` z+B5f-F+8<@z1|-l&i(ZL(?I4PC53XLH^$mV+znJ0RdMHl%TcU&b23H{Op}=mJV?i7SN#RS7;4Y!#&4@^H(zWUaW%qvR4tFLzedi zhuq9Q2Uw7be(HL#d&l}W%wdOhV>r++GZp4%g7xfZdh|feJ+}P)kfMuN%B{Ahg}gu& z%rI(M*?!0Dnt8R_+{1rzuM2Dash+?NbN=(sexj-dwV8?hn9KL?eg{~WCkdM4EP+x88-BDdBaM|0_TBORLQTynmPNzw& z0;KhW-xL!$J2h5Ua+>R_nNsLgQdu(@VHK_jMvRY8ZB=i{#{_?R&&pRCPbm21AS)fw z)d-ia@9kBqp^7w>wrjC34x2N^j0RO!k?M0+)xd;$ozWiRI0TkT5gZ-W)sa-y_qveM zEITcTp0s^tBK?x!u|Jp=7*-76Y2&5jB=9m#&3HwPUW#q_%=X7<@%4(!o_Up}lDD^R~Ko>UYbTH;3SiP#?&i9)=dW(yZRRp;b+0})RLh@O?Z#8pjT>S4lpu?{TG#R(# zyB^YpheI2VRc{ot=73?aWPh$FLO^4q;7VwF+(l4M7K5=+greVziUoD`RNT``SMa) z{3d8T3OAY4q7^IJXiu&S#tVZun%!z)*XJ*v&CB}2?Ohu_+XX^QnN0aYm z+{*da`qv=^G<_5#Si@OEFGz&b%NHIiD_##p&YQnjM3K*_;m#cz=C4O<#cd^ECtT0Z z{W6Hl&8l|s70y`L+gvBIeXOZW9m@z$s{CIa(~|uNK*X+(7aWK`4IaeKWT4L>b_yEg z5|xe>S}$Ra9ti~(O3wPsy^8eL75T%Yj2`J~wx427!B0p(x2)N4ja?Bw$X zht@aL1^XW@sytY<_AKwi6yehF{ce3;@7JsAZSA#n7Z=Fd z>dpE0=WUCQVMo7f3oV9@__ncirIsd?i-&h-!*|z9_ocOhOUXIivTA3)YUj%T-?5$F zOyv|AnlQMHsLfLKYwIah=&SEps*Lq29BQg9)Fiy`Hipa5dT0bN@TB5j$i6#@K;cynl+H_HZhYd6Iq#~&e6 z|BvqM>&Yb}c##6tK1rK+%p{O}oFpKm(PE7ZO?rDgX*|aqe=uyHpl9^l}Y(2g$9cgs`E@9OHpK zyeUncB9b+UwSRe8^zIVx2=A)gNZ$6;_jJ^!aYo)K5eHQL$yp_*rO%R&@(et+%_M|` zODJ;{>el0DQ}r_es~$L=(|zVWrKT1@ob^he!}ME22gbWYqrIe(EY`i=2UNz1w7O$P z!>zi!p3puCx$QWIMX9qjHJ4T$4H7cQvD zI$MFajf3Y~{HH+Zu0|J2^wZoL!m?gGHz)+K1W1~H^H9@jrj4Q&=|2>rGA!nxigM>i zhl#|2eXTmw(A|u5gJsj9>R(N&G~xAr@JhL|F&?z41+G#BgqQGY1Z|a)F6`IHtPu1I z^Pt_bLU3ZL3!4)A05wMI+& zFW$atV(1T?26_!sj~*~fS|TbrfX;2)r?{S0PJR$or|!N#><_Rrj-LOVcwy?3d1Eijf4 zQlWMxQt+8Heg`RFKYp_)!0Ip>A_NEFxithQ&4)S5tJX22txU{bLm(CSbr2`L8FTt^ zB`GhA+rVv)oeRsR!h;Q(NB2u3gVYQBPruDSxO3=G=|HT733i449`a2B$d-Msqj(&E zi@}|r$PFl!`L(9`EucD6NX35g_&Nh+$tEE#G$=>BA0pq=Y^VKo)i;3*lamx3_$rg1 z)@fsnEjUJ0d#ot@*>cKq{6m_}!H6#tLdzf1l!zip+lBGU%Tw?UI!FK&Jcvm-9)bPVEJO7@Q|pVC z3-50syD^jnozenKkKtFeH!=BxqgyX>$MWyKjiGV9TWt?uKPSQjT&)+gp$!IwSi@6O zeClU`Lp%9?RyU@o3A(0EP5ChcvJE=_gq$G(`I8EV{OEnXR*CurzasZn3SoG!Wj-D3 zz1uI0bI~hOH34<&l6P}=16K?2Dfx$9 zh7l4-d63;~aKvwg_rsYjZ-_>|nT({3PuhLfb2&AtO-^Y+ zPAii3s_-#c7#Sec)wU2jcNiLuS299Bq$Fwimp~ z#Ul0BpT`c~#Lsj=tJzP+v%op#Jo8i^j0_EIt+0h3&?4eRtb+T=P<(SQ*;zrD=}jQy zbkTm6-BzF?OrXr~sGws7tx=$QQ_kM5WTuv!L?tW!%{Kb}R8-vUX{(drLrryRCtWAD z^Q*d#jw#(-UgigyH+-l(>7E%w9A0wuAdY?GmV>B`SnKhkYll;R!4}=-<0JAIl!k10 z$?`x#p_gQbfuQk?MZ`D`u6InbwD7C(AM^(93N;6!W?5AcX&&=R7d=}fzGsXyXFKU) zFX2*X&6N7hInNN-5%Z0GSGH_B+PTvP5RA`uP*p&5*!aL<3$Wu`NLS>*Jjf&y*Rk$t zR$L-hl#CWH)tc-ncSdy}bm|)JB43xqRz&tlVo7j~_=0?!d+J$h93HB#&xGBWebr~1 zs9*P4xD&|<@?8XP{HLh}NtV?;QK-3PX=uSnZn%HGxEG$T9>YpAK`2;qLL(LQUtL+d zDj>os@etp?zg6c65!9nP#C`b^xGz|4NZqJ}^nC2F7}mePBm40h0VFj29BLf%k9Dhm zX6VUPI?5ipBHV92T=gONtU(#$aOTs;V7i&{vK~=W_eI`iU^*}3}fx)FmlbPR> z44IWrhbC$NtFIBaBw|u#4*qGmjGclku_`*Tl$;~cSEq3%j^yPBFDv8Z7mkT?b3v(F z7CxTZCXj`HIFuVhnZKBF=gY}fI8s~J$~#Rgm?(^Xx81P*H+|-Xcif?qzEB<=9%9fE zN1EtDc}K1V^8=&beVRI-@Z7QnXK7N%FUBqj9akFWg}xQ)`8B}){s-d8h8vvi*`fvl ziHJ3^an4gdw*)2ggR%itQHxeOw=TB?Zq1jAC-!AR3?kkovJVso3m#mv;}}Bu-E`yj z{y+-rCBaN~GcMdr1-#OP{F1<$XGex_)Kx5e=deJ}2oIYV?oC`pKK_S~0<#u9$#MsA zqG5#p`4dmrKuhU}FWS7!%r`2QcIU{4+{Yi-g(D&V;d=ge{pM+&LgpC^bT#r`cQal9 znmJ`+I$IuGF}ebM9vJQRsT&AC;1oKnYe1NvCY!;A=!m+SCPbj z#-ga@RRc;|EklMT)q{wQD|(h))id!hfHf42p`Nr%qCib%qYm;tJcpwXb(tzO9^Aa* z`JRld6x@DEcCr=y|D19sqd;sUaF1nvB6GWhsuPp||KprvI1^uCkvjEHZIem^jNWIh zm2bgY3@ACp01D#+dRhB6%(hl`;saqD=QW`Ly=nO|N930Wfs2%05>ITuqJ z-cFc>-t-6LW(ACIxn1UhwN4QzjLX=j7Z3ACvvV3S=6McQoqioA!fywRaPJ-+lV8;0 zh+pc&*W%=V&!FjX_TtX|$o=*6V+o|D$f*Gi)Eq0O%?=#KxS$pO_VfHy5Xl!dP^R#* z#Fg8^YhTUciOCO{y8r$}5N{!Ws=^*TCLu3DHZ5XDm%`o2G4yV&?Cf;`An=ZkRab;It%atG9V|@!%hXlNkuOTa0xokJ_$+HZAUsE~eF<<| zsrz)|6lo;@8%iD07Z-Fkew1pL`Dvu9Bk_8;VAwW(gYvltPSms;{o(cBCCgQ&?EU~y zn9uu8lN3ue)P(>rH(h&8WV2VJKaiBYeK3K+-6e8n<5obn)CszoMxf(|@J)C$;k~)( zhy3_mn)|mSI_KEaoH{*`CpH1eTvOAPp&Y#Uy3|6m$dkKwIdjb7AxQrb{s1m1(@g5og4Oh|f(#J*E; znz_mRBa-(W0;iDYJiN0fBV{JM0rzky<+P9PT{nBe>5jAw?Y$}-e6PEm->z*Aio}Me zFunR#&~9hiAf39^UMZiu0_un~#+ze=STS&dgbPO~ZOkPyokxgMD}~ZV zUM+dn=xMpdO2M6!KAqTN01Yya%ALUva6`ENLAbGSR^TkgsVk2w{w_Z@$!iwLhYi=;Hc6;!bm-VrSG(yv> z0npb8a*qZd_B+_geitS;TJqX>`L2J(w~Y~Un zSa!?yp(g4q~M8QJci>l zVS?}ig2IA43>L-l=*zm#YJSs@I45ads=QXN5wL<#`$h_1jmWfjuS>!<)=q;}jL9!U z7*eQ3m384v98c2{I_KvwN<5aVWFvFPVPOPFf5v<8v%AY8dt9XBZm9L7LjxTyO@>V? zgA_h(V?X~JG|vrBXXYtdZ6Z~DW2nk=e*VZ%?Kh`l>*MfYy z>1rN(`RQhy+~-TiC!a|W8448Wj(;B>&)_z zJV!3-apA=QLSQJRrm1@Cs)T<0#GBD~j@fJD3y#0oV4~E*h|sDn;`*Gvl8TdPLSFt7_R#d=0H?^&!d3?TotR!o8^82V4)8DI9qc$}SKO=Ysacf*3K;&n}Bf#%%^UiM9EY$9G{aX_ zcz$~bo9Qfye>h%boEUY2ltjqbV5`Ol3KeXeg;qQR447F)D3j3QVqJEh5$X%k2GsN8 z|9Ck2L@if;MZ3euL~Y)P_P6eoS^jlp@oAqxAY<|AjD$6X%)aQ>ldCE>Qi@DOeR16r z7zzOB*vpU}$lc<2*Ce#7+c8Jdi=vF3)R#@#gX74Z^;+O1_hn#ix+6S@x^r|CtJn{TIvQjre+ zek<*ZU&4q+0Pp4ajP$u)rXB+vRDZ%E63jpZsz#Ijmp_iCZa`hYT1B! z+E9y*8M@L(Cjj6=vSkXJHkDS4UJ!q^SssM?ml2EOeWZ)C$QC8H)fR(sJ?j^}Xp4+AKz1~9N;yI%2>7fXQ=_M)*0ixj!-_?o%WcBbAoLbAsYQFcHD1RA9C zeErfqn3+`jSCYAM-gmb~D^ZR=)Hxf=AagGDVx@f_fQ@rXrpI?uX4on8b_0iYJ;_b5 z|ADrngrCS`#6J8dVJ!2^G@r& z?UeA=SJ`Cf-n0)#87kPfPb609w{nMDcLDsb;DAbf%;b?Zv)b=*-+wr4LD;Qfw3#u% z-R*72Jw=G|XlKLRZ|UqAq`)oe4|3PSe48$+6Fu zpId}}s4#EymuWuAyb%qWFz+f$XUm7e4Tvz zrHw(-q0mObj}dDni&bH?&oOm-)L!7!q(V-mMg^p-44eD9F$^6}dhqb=@wjl&#Mz45dhv-uHXMvJE)>WCroc;CjAck+z^K<-bX(ItG*n2pjDj=# zJ+=oBYmfCaMA;3-^l*IKTz%B|YLUeUEk9LPEW<%>+ zEuyW80d^*)y2r!WOu*onK>Z?0WQ$1*Ow=C4UdB7jCASL`E-Bcp{f84@Zywr!E&nNd z+?!5|r5cTTIhmV`kqoqWJu0A5_uv~4Kd`YIOK%2zk>-f?kar_!{=CXoE5?P;V_!RX zXT3givqZY4xQ<;OIAyKyP8o@&cdjlcGlgVE#n3ceV2RQbR?c50^2P0oh45jIRFHWV z2YmI%hTE7BKbRNxt^L;}*K=pi-(RSw8F*?oDDF2wilNG*Pts2JZCwkom-&VvYp)ZR zt)gXTvEjqs@AjYOnUjg2|e%d=Tzo@+B-*Io2w8z>z@FIj<|zpA|3cXLhtQcxK&{P zaO6a;e}zxg`Cabav+MUkNtyoPeBPwCSFXRt{`c=j@5OI9@8j}*RDM~@RF=0w$r``^ z3+?;On_D_-i3KF;c=g!goik&llBJ!}=jy1mKhUutBU9|XHVbxW@7uD4u#k#-!Cowr z-?7Bve&_nBy8s67_C?6bf2zQl%1951O5X{qGj#Z-Ikt|{R<+nnimjs<-RXEWUMh?U zoKfBx>SF6Cf!I2VDpr{3`Yn5j8$0sYKO9-_TgU>kHzb^bRahCdGpW45eA=fK9^i4! zcQ=X!JHFiPyX5?~XUJ%Bwh~@kdi!nu#S-Z1@5uceGUYxYZE+|6@2Bw7eo!B3c4~b$ z&sU(u_@M1?%@5ee3gapmq$I7bAkRWxO24gsQqZ5WV7hpzXxRH1uPs-nh_p} z{3|nvbfbT5!&Gf|DB~vem*Apqj*ln4{Id_ooYAeTA{I}^n-F%bWM!8ROa#q=OXa=7 zx!f-D9S_ud(B={2^?`UvT>d3#tk*e5Y4+q9P&F-b($6e~*%lcIu3APKDO%}o;tjP7 z4a$7y$+0q(U8DM$?ssQLBQv565(nm#B{O5EE<9qC0^?0}Rjj$TCW6in$Hmwx0#6&; z9gXFa;k*+X<~Qwj7iuF$OmE(B-l=szzDziNjO;!49}dynChGMlvB{%`rk_pHvY}sV z4tR73m2AnaI%5ll*X|-N!$&4Exxw)x;TVDJH9i?at!qi3464fcw2rs+e_Z^Z>0lwh zqTR31q*4I_JikheoNWO~L$e-q_v+3Em1jhgLMrTnffnf%xL*y}Dxmqk<*$)7Uaar3 zAI%#cV^gdA`n$_fE=LrnL|$g?$l^5bmbLo3)-IcCp>E5U#xI;rqL)p@C|;z=;zskiTFgNik4H(QX+R%=<>yfE|Mm~bMX|2Vy=x5hY6P5T*_tg+sis5Dq0xbkW= zYi$mGGryQFX0nEywjK=WWKC+6=Hsl>Be_ek@;cBto*z@$qO{?J8W*SwHRd@R)x)h0 zeRqx?S~b)TN@H!hX|V13&2G@xPldr!18F?LA8@;SKw4AAuKM|st!adX#2qWJe-|M%(EJJ|wrATO)x?vqA9!HKi~^h?2y?HD+(K9yRN@^Vloo zJ*Bg)#bjYg=K{bU|HquhZ>3veo7tQlQ~4HpryY5Y^gO3IZ;yb7$?!s(i=|7Z9f9n2 z#J2{kFK_p~K4OfTtG{xE1Oa-^lZ`<#Y--8rDDP8HMUenIS|FHv=SqCkyurI-2b9p`wjh0$j_EzSs7di~dY7Nq0NOgq1t+H3lJ3t@t2(ASsZAodRZ z3ZBK%#^DTEf=j zpk2UEocl;-U&OibV}>cXGsO`nhQy#7BN0+C_`G!}Jx^$!P+bx8U6{Xd-6#hb;x zXse;{fkjg6!!=cS3+qw*K-kp{`dDPHAs6Le5H&Hh9doCdtAEq4<||D0QC4Djveb@ z@5@tG_N(0OzM@jhg?u>v{jXoFtEA_KeFJU3pfcChclXNJPbGFs{}1O->i+!b*Zv9b zandAH_z3I4=nYDuvGacC*7pn>PiWYfcWpVk+tsr@Pr^i6_(18%!|8Ai+GiOL+wb-{ zZ=}CCxTw0v!o0<&Wf`vm?+O0l;J607+e}NvY_x8n3i`}$X z4O@wv_C4dgEZGT0FYy<<{}hrN|M>CB;sLqwcf&E-&NgauOUQ>l)jwa_u1*g4iXKmQ zznl`-^0K!Yhz(A4C{J$0=Z-tt8pS*{58Hn^ct(xJ%;zNYUH0m0y2)Kk00nFtvA50! zw;_tB>!ZrgOpuDQq*r)b2fQCgA6ik&k(+mX-5(B~K@wy&X2~ieUxKx|l-^_ZdOljL zX3gpRa#kiJXRD?A^t&ceO_^nOao*>V1?8^JmN@a_brUXa<03t(H=6k*@x`=Gk-3KT zkq#=6H@`O%xaJZ$68X;9XDQVzst7GyygSq1_5SVT(3V8SmnABU`KZnQr-RvNq+8Co zzR{lkc&;IiA^Fu|)hxEs*#J;qJo{;%K>m)){qJqFaLpySK0MUm?##pEu%RTI+D7dy z0b_5UU=l0-5R_zx!pfw*z0u2g@ULGwW4sBwbhcbY%L;^n;ZI^g1dWp7V!;o+mU zWT{Lmo+OC!+Iu6*YuOvj^x{!cb@k?XjiS-s7Dr|d@n%Xz(%1GVF2Zv&}CYywq zPi)PEbIiniNwut@Ih?Qt((vJd1vSOzff#)GZ<~RH`-M*ojTUq_jHr#it;+DgkK>+exj%}r-l3HIR3Z-^M?~1x>bZ!98z;{~9wgl|vf9RyB2>Iznz$o$X+7^jn3dOolpL%vMqp(Pv zMyKe{8(Ugaz515wRS#*R;QC%MdJWu;Bdlx|Qm&rX_)GyYbn7?HFmRHDx4a$7q97l$ zoIv}g{jFHLgCuh7sX3PzzF}9)H#>>P`tn-eql6=}U=TpN#U^RC43xmiY((rvemT}| zNY4Rj7KB1FN~P4YQP@aJZCj6J0etd?g*l&I44ZiZ&FA0H#2&cV_gq*cZYJnT+WZy? zjj^XPF;r!<)i;`ha8&Qqk&fLBDo(b%ayWYyBA+Z%qVlfu!P=)|TID`6vFq=4l3OE5 zGpMt681aB-+P2??67x6tAfsw4h5oZ}-ezP)X)19_9B+4} z_bYKtorF??%hJsD!{!f~ICHL=$))K%E@lB*hRZFYbhY(dUY z1;=S5G4i1elTW+j-u2c(IuM0M!lJEr2bw_Nzb?^Zo*U`J((@-`Mp7nb{?28)33aM` z1!Z?qC8aDv7iGUlh&c;eC*nHBlEWOt-M9z8B)%w%tu4DFT4Fz+HUCXwN5^?BCQp(j;s{5QECnYCqesZC+U%vYVzZ=6PlnIze%$qcDDkXmJOygzyb zT;fkSq-b6UDOF9>pyW^;v#!V$Tt^!|yie!9vrDi3H;wr+|C>h31bjTQN=+M`PUb&g z7GF!d`JO|+i5ED}neiG8&E|ub#-&ad(_xLe%+2%IO2CbNM~0-;_`+B2L&JjWr+L1X zMN;XFJ6ORKB8^i0w%COl8%%5K%9ns#jwyY6o-#_%Lv%gyr)7fedc8@PH~mg>TP zIQC^V^p&)?e8B>R?CYS$)nV8tJ@^g({rBtK^PN%Z#?rRxla#)2=aAgLTSEdw_v@_7 zgC}J$^-%(n)QDOg{jaPuEN7R1KngURg%3<@sb9>1 z<`{LFXj~6pQ}GQ z$b0(QiHp5Zj(7rR z9l~lWkKbl44H_5ui~iI5i!HZ=w(Ar!K)Folhfp^RY@)UE%=Uig2|@*u2RxQBL*^@- zh9u}kTeoA`n>JUvx~RWarwi)ymH1Gfn+!EUOznk(ZaM^E55P;0UsW0L;p7+%yw^m) zvVc8hr%Mgtt)<1kNK7s`>(6RWA(ep4z4bSD)W^e7EQY}YFzu)MRy**AN178FbqPsL zz4%O?^()MkwD!UuA(~G(ki5KWrE&Z?PaUXfuJ<;b0W_#G)QB(RAW{EktfR?$*+I6@G?T~k8a~UPWDij z-6MM)r4I$rJ~fVhJXSm9>Q+E3kOJxe;VOdcxtb|UE!Z_HHn`vP)YMOk@3c2~4AtBZ zbS8$n>h3CSAllL^mu#f}7!H2CW7qm72{bMUParq|>D7{7IW(X8Vt;HA*yGg+M#RQ@ zEuRbqMcpKDMqJ;NskSvja{{82x&G|2ETgoXECh7mbVuDJRz_UUwuR~k9@~plIV`FOc7AE#BIItQDKkH&)Y-zQ1iqMVr*Q8n%6S+{bA?qDg^NuVBROmp!0=-1(YmS6)xHj*Iw?_lT5{Q^vr4k$(X}$^?`~8^lq6oucjjP6y`{#w z5Wz)3<2v^UZ4=>}8elX#XO#7>M__Y+u;__ATR=N&GX@@QpXBv}XX>pcDhO<$)i86X zipahN6T(BCtFGtl-URynMWWP4f3fJNK6vaKNbBs+Lrj+RzDOJlA9)$yD0L#D*=;8l zn$RyeE>)hi%&B+YmACo?JnITW9)nu{A|*T4g0>;IC_7GvANSyzY}E$fEOSIQILY&H zzgP7X^SRqL%VB1cK)0NX<{WOh_75V>8vrBG%+ZwXKzkvP1nL#;VMd`^RB2(m8u5%P z0HmS`R5L`R4H-l5i#8mUl{7Rvw+>6L^Eg@pql#u*xGq`K+&*u`u71{xJ;OgAh z2zxh?qMP61r5(o-i=9#6vL!_KdEHXt7Y#Opi^Iz;{vydSEFkd5GrYe@6AI72jRhN3 zE(kC79y10dstUC@-`e^gk zY>@e)KtsgaL)a0%M#T))TjA1scp&+U^xj|Mq-N{vIxPAK>v`?j-wbT;NCHn<2hCc7 z%WVE48GJ^djC~Ff`e<5+gCH2I@8z|3r%n-ZF)ZNJHE7j)#6w|PA8>VbzxP1@QeTU6 zd7@QmWB?`$w1HQiu5Che&bKFS15&`!7U0O_dK@^p_B!P0=)nRGYXT!OW|XYTp3$k8 z{vvgdBv7B!#emNf=XE8zthVl67Tu_yzI21nbLNJ@evJr~d6Ht$UnFA(i6cfYn8b@= zr;|U=$z95)y^ojmnyzf$&9>jlHb~Y-$}r3I-(AF#50JPyTDjoOzBg|{I#!*9cs`3P zdG#2WZe1-T?Nmyc`Jts`4G2PdA(%YU(&W{mRv68=a%_H03q1NB<>`$0qez_#p8}jyfS8d{P^Rb2ye~S^y6WnwIHdLGA=_fE zi}kyE5J*GcUc|37tjbVj|DZ^342Qxcm+Bl&X1+Df(Zk*L3LW86T#-uB$HC1$AI?$o zzHPrRbjI{}C=O4A?sMi^;zd$ydJ{k)>6jU{#~Vu8V3LN$ZQgT%FfHJ+t2Ue8pC7UR z1k!Nt7yW|ls+cNg;Ip-IbecdOEG@4PK-$3;W1=NQI!|xfu$6*kW|$_BDJt-#JC?On z+Ij?u#i?Vnq-Dd=Wr0X>Fao5#$Z@+!oMsO_iQoDYLg88Wj_uRPr;J1Spx5Dr<}C@F z1ptJ-bXkQ-)J?cflgP=gqm+j1RP#XeS}RS?6q^rVIA0)^`2|<}CV|ZTWt#4VC|boA ztx$L)Aq&J{606l^*mS~yXHste?dxY1XdDcOd*)7$Yf6jv)MzE?qBtUib4C}=y1hyQ z&>0?E{UxOW#Tge`P^khwvJDDf8yKK!@-GXP*@(cs8f6PR^}J+lyCpymPo`qK_39@v z+t7=X+q-zSap*fvTL*;u0;=+QV{cLB8LK~QCBjZjzMjiO`)7WRT6HV_u1Svy+UDD> zczsSabU(V1cI5Q8VICTJC6KB-P^+I(GagR%vSEo(SWFgTx-m|}>B;Fia6;2~5qqN? zS@71I@>$Va^!;m}%U4GHEbIr^Ev)S1m@KfD-QN2#q~oHfu!5w0FE>|gB) zv(J2$y_DZnj`^BlF^!3tco!v{E_?Tsy@iu&dK3S!qv1D6^XDn!tGGe8P$hEu6et zi|)$#dSzP(?eiTNyIS~6^~lOJM`_=hPSYN9slK`u6r}vr_=2bAPMsF}b7UF!uvmc; zKjYqeZi~Wppr$?%DhRg}(bDBPEgmXn zW8cz#l9IcR*Lz?ljKCw(sDEfkY2Fr0%rY4ujSge@q`-u2-f)cKuitv9_Gyq|1@w-Q z$f1mJc_q$6(rG8oHIMEw2_Qlg4rs95>N2wP-hvh0eHhuAX<*y>FDR} z0;tOW#Y}?uc*V{Bf;Z!Xh^*d4xfcQTJLX$teSLol9%OR^jW-3zMWbSOLTma`ssy;9 z7)?n49HYC+bv8?)R|Af!y$(J9^jQpO1nu00eBRD8!^6B8s7c;nI1{=1vigk(AS?Bu zur!0lm$`WYU$UR>9Oe=CnKY%$B3-Cb#@_R}-jC3udE>Y&Pj1C+TYdfGiIn6Q-%{)E zhL>1mmM|EHchEHdJ5kL699tXc>o2t&Ce0+9MiT*Ic>Tt>bk4K7A)qqaqmn?9Jf{bQR^YEz}DsoXh|4&GFBik&o&as~Z5YWSl8oVR83 z?9ns?xnsod;OtZs1XO!}^7lLE?T;1p6&h%39}qY`V@5?GLr%K1n-)g9d8>O^dL1QN zp0thIpn1|qNF9R8CJsY$QFmSlZzBt78Rm6!!wgAT3z0F1}pt z2-=p^3g!8;B&VDaR1KLi8_)P`r{ zvF-{jkKCc*#Olv_wl&`F$tm$MB)O{RoWFZv7?M3Xy1~?ffXhew{`mj6m{*7ddx&%` z2+-2yRQ&E1_d|FV9$1ovAIkj{FpkS2%twLs@^Sa&NcYawK!o|hEiy8V|pK8X{ zsDCDhZP|9p+uUeziOuOJX8rD0PD~xjL4MyzU>vrqKUj&%p&A&Zm2Cxj^bG(xiAzW2 zhSyvg`YBjAe?B~YvzI)cYc!2H9#>O$JJ4SBY)|fFuPl=Fr*9PHD-0{cEtm1*-Doi# ztI!b+-#V?oY*%AWcyfw_E%VRTb#3%F9N~(&40S>%U$ZdQy8B(XvTq3Iu=@?{`>;y+ zKILR+eR@WArO#oyumvs$Pgz!s5UOdAfxFSvtyVRUnxG$Ofrl~iFYmM)&T9k=>|*nM z5x12Dj}Igx{@7G{I&+|=srek4oCs4-z+@(KWiLywU2PG-NR@38rcvDrW^#G@o;Y@) z#=r#p#>k*)C}WiDzw|U^ww_)d(K{(+hCc{PbD|@lB`Oo`iC2#NMOV)rS;7=GU75@2 zDk4;*?Y|U|fW`Ix~JLYhXAn-)2StO=NZeo8B5GdHmUrwvXKL zL%oAmLbA*I#+>64KE8UTc}0J?Kg}i`5NeiTZkq6H8|WevDeM_BLXWDy3^S8l(Ob8` z<(DOH!r|a&s*+1TxbeOFmP)(lF%+>5l5+c$*};+P>knBvYE{YCn<#208AF5%=J_|C zPMp_$57>Y>=Dxr5p&EN?IeCB&EFD$mN;jmex#6V2Z#yR)Pr$E*s>W>~Dya{4FVl?N)0r%ursN-v0UQDI0#X>soeVm35MUrD{U?~ zbCf*`;6K-}+)Yych*$%FuqCtANR%At7d5{iqL|dFyCDp4G@u~8Uq50Y0@JoVNbU4Q za7v^&3ZmwuxgZb8wfTk6Z#ArR5M?43lV&ws(KaGG`&0XvvU4Mjv%Lmg~K{>61tG2m;9Yj=PUoueAWs*-}ljg1pLhu8RbfYW<@B`qKu znfL*0T}$F0QQu5(gKUUMmJeB34u5ykN=lHvoUg6Od-t&_JRGf+0q0Q52HN>CBE}I{ zQKO)Xrqu|)uRc*W7g(VdMjU6rO-mv%3RB#;Ync(l{l8>@2 zQNESMfOltiP7vq`@x4H%BB|$yVJ(GSKqJ&CdXz1oV+|ud=It9&mv6-vw7s#DjWbH& z-@mZXA?Qx}A>AQwp$KBlDn1{U|Laky?`QNygrxD;TaIj+W9u4 zlvO9U`E^Uj2Uv2u=Ue@7f=6VM{f-N6B~4ki`m=Zs2F*vlIW>&|pAD>gu~f(ur)Qsd zWG7C5+Q+;+=Khj7j|!kD;qCRVgtI|hJh$V!k^3T&R+q8Fv3Mi$9jskL3&#z|cI8w@ z>*L>%Umi*Zh15;+WM%q4Vv54%#N^Noj0r?}w8wP3=f5KR*1^|97>_78=H7J0fp*Yn3c4N;8&D$x_R5xMEmRq0b)i~6 zjMsrEH#vk`?o-(2%J;&O!iGerXMw8mT!h9#@TJ`i9gdsPfpbpbV*$T65<$e;jLRdm zmI~T3a4ZQL@M%w&1QZQ17Ye>@CwN+|b9&A&U3+};{EMW^y6G=<`xZfB{VMu#g^v7H+V^0i6JS@%OpJNhp zp5>~NNRKLo4JXHOo2?wftv1+0iVL93k}+k;73&8Z=!q@x@EPH1R?x9RdU+nsy&A6+ z*BvW5$@-YctXFB8#hA2MTShc)0VQ>5br@#f+mg<877iWtLhX^(^_(6|C@xZx)wuj^ zrN3%QNPX_-<3-EBDvK~-VqTWfn`x@!cq|-ieXN?QY)FxC_ErVAZ4EwP(5lOvd%25G zf1J;rNDnKuhjx~}ygSl<+IeP?fbERo<4YC9bzQ~P$2JtXwUcWuLBOC#{`q#Zq?5+A zZZd=VA0=$tRBqLAHIUZ!b{R-r^PF#~U1dYr-r+7cl}rxVPgxH=2T_}eA&h@lg#IES zFiCCPq*B&-)b?c3IQkL$p9~)>1hUA}@bUj$77C-HW2&TO)&!NS_*o(j5bre^e^|fl z;s}tH{X&gz?(IuwyNT}s)Pp#_i6S;K<0x@r!)6S!`IR37DJg(j|2%b<_5H=AVwBuw zE|fs(a31^E!kI@OwQ4;}V3TM4ljVCU>*EWkq2Pa0%(Zr*`vBdbym2=K$dI&56*J8M zraq~mYl3bbOD`+VX{2oxT+EaHoac#_UU9N8%@As8{ZaJ*8XE?%UD@}?%dAXL;~M@E z_gIcs&@==JzXTJ_edH|BlhTQo887<~bc%dA4hz!DJA6ON{6N;j( zrb6?Jrn0yt(v?>>s?^<3y&RMDt1HDPdkE65{cGZ4{jW|zL3**_EqT60@-Ga`QXz~R z!aPLz(v!Gq^O>`_F{<^>7}_Alql0OPcQz(rYVh`;Rt)(kNf|vSRVjX{sXvT{nyFPq z^2=!MEb2xCNwj)=4#=pKHtmwH=dfgu5Ma1bM>Z?m(eucCpliuBA`CSF86_aJ0Ywl4 z%kC$jC4trMV7gP_tuqp}3*6XVL2F=a^cm#_I7^Uy+8xqNV0$R$aa}?6po!$aydB!x zVDDcviiEfdlESu|EcyuomHF3?T9xVhNDm?ze2ir_6J(^chf&4MG^2zZgPGcDM^(Rd zP*)p!L|S;z3I=!T^a)m2OBZ33cw&R$tflWOTWpLAj#+SZ0x05WvRzP;oP3g$%BDa7 zWURu5Hp2f{;T12dLOSFt)BdX<&Bm0l6ejK%ckHQZ0xV`1r#<)5vT&8k_z zG_K4b=*Kdjt5dd-=hP9OTtep@4RDwD$h#plkN<>waYDY|{GYmy%%ilph* zW+ua>SnIx$2cIs3{fGA$a{22An_XsF%aw?vbpx}2R?|gb%AEwY!>GsIueCa?V7V|% zgM~`xzOqb#CG|hud;-`t9znnW3OY$F;q6$-rj<+bipCx$MK*nc0-#j1Eq*0e)HaS7 z%o=$;cB{A;YFbjvHBed^A>Y&fRjk)1w2L5-w=F-knmvq#*b(2pZDL5czC(&BCj@VC zx@s?SUGy791fVBq>BCFUo>>wAIwp`8UaPZEw~+pvY!#Db(Tq;IahG}DzVa|RM1Yx*?s;Ye;0?4PwbUloX^J=pNA2Bu`SaZ^Amlagy z&}#kpnyoWgBoI=gCQz0+phSdU(%F2ZyYBDT{UOBmadw!L?D3k>Ka@zI8brtuO22LdK5J?27#9NrrzK{&xKc4#E6Fb|7nX z=+qxcmtA_H0+tq%KN(yL#=m5~p3^V~8XlUgq0k=r9}2C&;We8iM#FTG>dUWmkSp$tNi}hz#eKY+ z;@|JyL8m1~>43mFYHdA3uwqe>8^GzVZ)WCFQ#}UT;edJpuB?KyvruEEIZyCu z^Wflt^}Tdx<8|EC>jX6qnYsB?x^%xj9q~+U&^Q!!_ zG*9!F#4GH)cn>Vl9blhs2@Na!zc86PvTa{Aj+iuUP}CC8^UywoAJqRymgCc!(*PP5{uHrq zB#*@#q2=MFLjZ4?a&nqUKnD;X=<$EE)9;)*-7KFOSD%Q?P)iAZB7t=LlDEOrrPgKp z?Y5rovWa*<5+Cbhe&zcL&G;x(pc+c3XRB~`LC%y9zN=ZK^!lw1vqF7cztBS6J3!TMC^$k+Stt2F=bTCZEnX3Lbll#>nT z1tIbzfl-OnsWw)P~N@*NCK#XyX5!*m2R~9Iq{CNsmmU!Ug!Z| zr*PHKH$JEUY4K$Sx(5(>@^oVQiK|GoP_hEzryv$G5Z?yU6Dba#-AJNCW{||)` zO>%SXEFleXi*7rcxKSBDYe%BhhIo9H2t0nHWEQPf6EfCO20BI%Ac1;LyVM4{F#j8K z!JeK`*E|?dT5^T=h+m~SrT?E=3zUZ}1+nFQex)bI7ZjKL!ecGYW0Nn*tNN{skbKKE zsvB#C169=!gBmsM|B{JU{I7OdAmHD24Fm>>kdObzc1_2WdjbmULOG__NWpki78TuP zrIoSYSob?Yz~E8qa?)x9Z*hAgU1*7>@(&P5BS{Fr10JcF@V;Y1V@EI-eS|EP1!UQ( z@zi7yraUNWzOy=t{gGW!I9~5y%4A6~iI~SIn(8Qc07*il2C7vm3es^D8_IdVf}>dS zig(B?NTu%^Y5rlMiJC9$>R$nBt-J!&n|Eir1#ew+XFnWu_)0&kpHq;%hhYOQ)?p!t6|A*n%XhGZ zIzyT4naU%gmWk^z5dKG>5C|Zgp5)DSazgfzkZ8FaVDuK-M5n#Xe%!;q@!xLS>(3z_ zaeErueZ_6o)oSR*1}AbJtP~VdTd&3zzfSU~Hb;@eMa5IIgO#2gAQI4CFIn`hY$=i1 z6mHpLxIZ>%f~MQFB`)d)jC49;HHQ6ByW5hJP+s3w57xoiyXx5X_34D3Y8-mJ2Fta{ zzy66nE|P0h8($;{E)FkfS)Sm&=iLxY5O(wVixe+Tjltw4$%A$`W0-7G!f_GxV< zv*xkgBdWt@%g-hc-Z+~pF`=Jr*DgI%M$Do=?m0*JWr9#YKu={(DaXXATvITDU2?el z7DlwxzA}Ntr9CW0IK9vuu@a0NDAODldF@SkojdeaQ0teS?@Bmdi14@@c8k)oGPh!V zB2DjsQ7A3Yv!+Pno%UpX9*i0CG)QK4D}-!BTE)zq-qR#ER2TX z-3UFwJ-*aUw|`iW-=VS_kLu*7jj8xy7yLo`mM@zS#tH%b}z zfy-Ywy|}i5t2{!_Sf7)}+dB8!t_CX=>NmASp$J7Q*2|4u*H0KnTD@_%j-|+V{f?s$ zaHsi#rO0iTMHuzzIM_YOIqVBdBk9;BPFC#%L$e>}Zr1K<>~d|^#3@cYjj0Q#s{NZl z%6|5yEUx${@76U(4ljp!CMDQ*k(ao1e!b==`|qg_Dm1&5z(F6u_hFXb0*3+*9`4hg zeQF%A1IEl6%`O7fqGGy_xI4B*G|YD&-r64E7fxv+lzh2#nJLE1<|M>K$RyEu5g9WrOaBr^~JSt=-D6% zbAQfph%id1brIDbQG0R8%=*G*g&`N5qGV6yY1TUvKIQWrahDqW?(SWlYZ3E@H3ZbY zoXZH_(5piHZ(>@-OWaZS95ExsCVdm4Oo6~dh=Gx;90#P$M-13*YyS*aFZTq#Z zOfc#V?ay>%8#eeIZbF9IL)OzQO(pqu4%{m9jR%+knn~vp*uO(d_WrZ_%Cy`WY%MriFZv$`Z4Z6!&Bxw>ui)MG1h+J9;k7575xM8(Fnyv_g|#w zx~CNdP4eG=k?w&z(O$cGOB_=tT8$lteY~xd$+^kjh#Kz%NnhWd^3#Dpy^v&hKh?ar zvzyW9ZS5c8oM4RSfn;dS5eOlagOmG5cEbbF-dlvlF4DuPx5f>6YpgqItsu4Iw_h3^ zk71kXCHSS(tJR&O;2X2f>)}h4b8bI7a91lr)T}WUEQu9=%>l}wq%EKOqXlC%wt7(oR)Xui@V5IBHjGeQ8kS|7k>~R- z11*N1p(d-yyE}~`kypm_dy7i~uBdA3EVlT1a}d>K(7PiNfwNP2Z31A)zr9u~YEB;& zAC_Uz5GHEjlr;okGjAr<2we~M#{D(mWZgI;Me}M3@mk%6`tKc2=3}v{XL!p^YU|D6 zN_{F}3*JO#Eh)+?z4@I-m{!@Q{%(kVS|*-Oc;-AEV;pl4}m-&vi-VE3_;5r(xpc)oV^|5v!)32vi{LVQTYt^|l$2 zk%jF<#3@+rgDSGZinqbbctodszNN&a83L9iGe@Ofs}PR0wrBFrG5VKm@C5&Ld7ulp zAueQvdr)YA#ia^0kbLYMnz+i{x_6#Ed>7Yh`NM0I4Utc4{P6a`I=$S6NyIpI-(T;b zl&+Ax4g6y4WD6#K$V9$;7344bj5T6l;wSnYZ3G-vMPKXGbXtUIQT_X+C+$l5bBw{w zcd^Nn(Gc3sIK$R>5M#C-6WC2TcK6NHYY#~5&(O$hpz2Ispl`9^`tXk@%O3q+z2&m@ znn_6F!LPKcym`sfa|`)^I+Kb`4hIlyabJJPeR5QL%8r-Bo9DOqQuX`=abxM3y*tNt zi?t=&egh(O#UWEbfm7P51*yN=XiM^!*PHsO0c7pG1>%ZW|L=oG)MFWm{Ew1PA2FGi z+!}5k=YmXg<~ndp9#*ST?M3nKyjaX0e%L<_Al^b4&#hcLJWYa@RSBGH?xWknI@hst zvm)(b`4py449j6XIxbsha~HQMTbz~yqCa{>rJs_r&pVXAjp`KIJc~VWxIRG=Dul^} z9U%12!XCTn_wEy^gL)5fNlD0y%tiKTS{<0#4w>mo+cgXxDPOjf&}wG1ejuTE2^3Ge zFO(txfmO$}-hM-m?3ge&7q535f_$dgD6^^Rnvbl{CkWp^MT-U9#YHbc5|_LgH|h72 zN^%~IDtUF-ju1stGtQRr{+{Nh))?Z<3~uEhTZIzV03w-sJx*>%?zKSieuRT>YdLXd znmhUix@@XCgK~s1DXq?%$ zlk`BaJrI@K?Zs&kUrs!-Yw|4cfE@C&;nY`Neer}v9d`cKu=gUZlivF4j7WOWQfr-G zq-Cjs2m=pI5-lxLLd3MdW0#?7ODQ}VH2(W$_ITgb=o@wlbmd5P!r7}aQ&U%!vp|;Z zSAc?cwq?)BVj)R{iB5a#HoHzpVy39xTYQQvr)>qJ|n?DywJ z{WWuoH-&1blPH9A_EVZ(@a-rdQ1fWISU8MegQ6^Kn-rbRL=gJ2pEK3LQXP9gVg={yfYmwLYuNO{_tDTaGjN1d&^@c1lCkB?~9U**hw07nuVo zZCq9Xl(^mAGwIcSmE2gZF4=qrF%>UxDdq9vSr3;8unt{x?d}?ZZv5u zV|8~Rx9eSsdPOr{imO;#3QG<(``*GVuWhDQNkX^B1=LQ2c(uO-gswWO>H+u1-CI=vXJu3F3yxj#5JFoB;P)g&AQC4qVb& z*ZvWjpZx+fyt$U87PASC%G3GZ$}Ss4SL{FF7l+f|htzyzUeMjNrAVl6C)1z0 zWK_dGxlvm0w81iUSE>9}=afcFvO(}sj)#%>DTcGSvQh5hSDDRu78)9T- zX39yIis%}g@tGxgj7l5+&kOXH^(%BLHV=4D4zF8+4d=0dOoJL5=&xH!UqJmzr3MjI z?~uML3zf#=1r^TCR8BF9ftex<%$I);W?cLX=W{%a#fyAqE7C+p6zKA_$plJVncA%B zu*qBUgH1az59W~MRE!6Ullv`V{ad5MP>>rb{ai&I|0(R7B2q<3?$dls#xJYviar0D zR=JLX;;e16PoHPoV%-vmNZGh-h359f@fb#V?W}Ox8*HxGv5CHw>voKa-aXcz77aD+ zPvxdpu3KAb6#a|jOJlI1{QC6mSC*+3Xj2E5=KiC`V7YPQ6Z6{|UuT zpY~0cupUP`tzwMRH<#uD@<#qNVD(T+V#Szog|^l&QP_MRsiy+h-6s@#Bs`ERk|a?8 z2o(=c`|`TjL7%Q()|Wgos?-aE2v6f+5}*dQLM%O^+^U{`58`DZTU%MW<62{%UTo4K z-BpYo0@vs|s)fr%oNT2vvW4oLan|OQB72yw|9O`m^m<*u#6p}JUb@#n5}uW7y))56 z(X(Bs9c^H0RK4G!yt`Ow627@G$SJU`&`K&p?Q%x4=_8ufi>bsP4`>70Ov`-x70_tl zlq};(VKw1baVmz#zhX8e#xF?=yeUiD>vYV;_RpTsPHOH6)fwYWtcBLxagA9Sq(=(9 zluo>ksXGxh92Qav@^3;op4X>c%P=LqhDsmsjnH7mB5{O&Eev`c z^uDwbfk*H&g7%Z$SA4#jW`Tk>4eWySjq5hNIf9m=HX9>I?8a_JKtW?fO)nck zncvw!>cbrE(}Nw6X7*MA>vyvjpw(fIvg1Q<_yyPf&gsgvUr6BzQHe6z?nL92 zw0+0h>a7@(NS~5*NEB>Cltbj3Xw?>$7vmQd1HH~A*}@fjA911-Km-p_>xXWhGWIm> zayL52K+aV_f3_B*jK|<~Mgq}Znv1#vl)iqwDfqA$ANLpTeq>~1&ezBmo16KM-d>AO zJut$ZXo)oLmCWojVKmfa-78V8xkStR{Ir)knt?Obszy16x$ki`N29wOm+N0|8I(Ly zm()o@Rz1p@?nfSrsg|kOeF*w<6ikHoQhlVYdMUogxQ0<}Ee)_8S^2}cBQ0#^XGN39 zH^6{1e&N5PR;^JtI+2 zO`7wSzM{68;VEa-!;d-Qa-7JQ3V*x}ajCv$jc9MK^KrkB70jdPwa#FeS=$R#baOCR zm1ud4S7$nlvX;Junz+R_yd+Eo;R>UDw9MA$XoYYErxhaUt@@MI*#}7){Gix+ z?{jI#@)UWxjgiumdWU8)`asO>Hjmx4{_g;_D$a9tkTo*1{Oi0q0>?v4-wYH{yJ+}k z6*c8P-T;+IO07!_WyHIk&Kkwbg`fi-L1E-L?&A2Rb*? zm1>ppZXBPwr+8L<8f1M5^NvSDnE3XcXv8RYbL=UIK3P&&V)-eZa1eT|SWLNtrd~%7 zOjlTa4QOo>y72qxm3S{0n!n-G(?}l5e|NOh$!Jl@Yt=INooT&SR=3e2QQt&1(Q`M% zymrJ@t>T0}99sEp>!>H!Ld8A~>A?Z+dBNNN+CYE!Y*R3c%xIY`B#8 zjh7RPc7WyJ2jEE@Vn&&=VB=%VaItmEDV5PvF25c7v4x60Wn3e8o5>ue*2uKw!+!sM zNr1tSW5&p7C)3V#;FM>VyzS+d_;%)wa&?^41tE;$JdOopYuGkPf3g$~{rrf37}*Nq&i)23 zT&suCCdjm#lU1b~6ggPbqI18wN)y^#jUAzLNs=j$+oB@aimo<5w*Q7#mM_`RJ*ycn z3sSX7NvEtp`U(decK%5AO@xEWtDNKF44Ah98H8leT`IW;NH@#9m}IJZ_?uwneO5d9 z6GL2A+3E2XB+^^Y7@S+In%UWe*A)?>8t0vTPUzm-LixR?Z~in%yrv7i8Kk+((VSmmxQhCMPg!A?mqhS$0)OWl7{T0nZt@|!$>GwM_&2eTmJUsnrp zqGH>pDE?-M@ZT+e(lcV{gAT&wVwk(aasEeq$^+QPl%y4PRoswK_)#M5gz79@8!(NN z3Mamw+N;88{*$9~QFUI?J7GSr*fpwg5exqAIC#;UmSPvT*5;6Gvc&42VL9?U+@%Pn=s4bwOFBNJJHyXwjVmrWymX9(of3%sjWfQz z?|+K^2<>WhCQYRKy?Kd-5$T$Op6Qa}W&3o8zHKkV(8bHfJYi6g>u;JKkl~1kZtb|N zQ-rLZAi`VqIB|H_qG%&HoM1Cwtr;RyYzZxuC~PVUGx9j^NapyAf^Bn>E!(J1sy4J^ zDWYt5Vo5i^UCl3vjPux)f03T)F8hI(HBO!f#AW%$9u_{Um&12spMGrlWks8lL;i`N zV>Kh_!!g6Lqeg$IqPk@3J0p?!{?@FIV+p&oD-Dd@0kq7eeZ^KgI^cw`Xu-Lp=Co+4 zuga}kp|bLuG!THCIeeOwBl_@#i2*GmA~J%h^xx}~k(XB_-&+2J+UFzjdZcMfxZ&j? z)XIBj3xBwLP0Xb+;3#fwUBbRqAAV6c3R(T~yh6rAxj0e#DAD}rz^5KG->gtTp zRpzzpyu^K7)PvjWp{Bj~nz(i+Pp)24M-%H*)4}7l05feifzLKi{d2eg5CslS8mlv;=xS%9|D!(}8JS$&h-oM{Tamj>H z!L*-weNYjRR6P8lkW8-?gQVeySiVl7##^vr_1x`kVDy0coCd!if3m!0dAPmYlmU?x zVCoHt6yUMrhvvc&u#EWf3Yy_re7Du-_Cy9A=kxuvejH*$0JO8dxCGA zigsbr4&74t;q-yzHU2zXa6q!Xp|?SAYO`Ri_E-49+2W-H!?|e2(C~dALOw#iG`^L)mxW%RE zbk`u@j3l0lTIH{eqDJ)Cj<=S&Z^69_m7qbM(NyyEaFymuDmBxVMwrOQJ=3;M#~6qH z8d3S#$W&2Jk)Kb|!VKacWbo=#tN3rbZn4jEm)(-;#LX^d-d_?R$S_A}%@+-@r!g`( zV|?{EfoI32FkdS>IWg9NflC|);}d2GZL<>~&`+;ru_L-gX}XAwo+#7zztoUg?;p-! zX5G}}!e0CvZ&e2$(1`uMs)RTW<}C}|9(gx5Fa_kT`9&u(1eGEHx}qr~6aSrK zUdmQQgj29Q?>f1%Bf-@fhF(xi@P= z=rLOmlMMLXoztU(d)0Y@cMn2-nbrDIY#?!vEC;6&dV-fVBTNUl5znxa#QA!zqr_9i zj>Oa4n#931A{N&xcu5ozeu2!zety9 zh)-e4y?0iDP`}Jy=Dr-Bn;JEROEC$9&Hat+ zGE71?>|@Z+(8<7VI=jPUw;X<-lCD6Vi4l$!3D?0&eCOhnbjWOnS?%$s84^fQ4YFBQ zK0~7PPV?%Zgasb|O_l401k-)hAej#er*NiE3Y?p2jrA~9fiFt+yS5Bt1D-DPU~8`o z#+aJ;c*M^4$Yl~JH856vJmYI~$@>m2C!!eQBASzTFB<;i~y z&s2xzLp0_3dz0o~_Yv_Q%@KKAS1}JYp9P(_uB=#b@5VCqUMe_^1Z>4^uf&8cIw3Ah zRs_`s&Ypv|La**cpe;&au2a+EnZ+OOSvewy8Ih}3y_Fopr%lXE4>DUt6nn&62~TI( z;}4J+?l+YaciD}UyU@Ezk$Cg@r}oY>EMT{2p~z^MC+|tiyKfP!1&(j)RbhB8wTvhG zL8hfGAF-zJJg&=)o?5TgPD_OaBdo4k4G( zwgJYdl6+ZB*YcFzIAX?;o)W}b@)bO<@b77<-|Ae6plormJiBk(Z$7=8cDkB0F$-K2 z8YjcVk1soessy=OYF5BZO@^n`UdtSpj1o)cPiko{Gm}UWL|is5)fTgYNJNHnxZyze zWifYO_uIBs9FwSCf$>`fP}yv8f~{kyO}_ z!;&NEOswHiyLgd6y@6Sb5#_nQ$8^@KBG|624{$Z{}BGryetduEg za#X8WyH)eSEn@%Ji(D&{kn@OkR?R~RyNfe7qcBijYN?;8S7r*NN!SA~W)`2u4_h=0 zu(jGQ;K(wy2Lup-Bo!qNgWOJNSpq^9=Ktdk|AV`?3~RIP)&?nsLZQX2#l2W4u0>jc zOY!1Pkpu|tv_NrphXxN2JOpoXZ3`4la4l{{iacMQXU})cJA2;!eY0o&4L@?gS}S*M z$i=m;taYyQgn%bUzK{ecr(ot$n<1T~G8nv;gDRty*Y66^s=$f{{lSkoQVNovKL)DG zRpb!B{;T|l3zn(^kR?|2oJb1p7k2R$k&Z2Bg)B;cT@F^g}ATySD@s%YbK%BTA8 z+AAkPVq$E{ZqIP>7(M#~#yOyxqy#&qFsE4K>Z_t&_zebCfso2K_dKn5>qFr6#5wC{ z7mFT46wmn#4iY!g?2@sd*QRxP(>zdtz9*-`NP<~yjh%ESv|GdKCNj%wS=|2R+@Y5r zah5ioTN#Y1WA%T!<^6?@I`-|~1njQHJX)dGZ_tsA8hTTNDWo+w(dZa`k|=+^us)uJ zkV2V_)X+ekIG}}OciicPb1zF82|P4Kng??QKt71}bYlU9pBg|J_CNYOf-kL9>?yYL zoShRzt>=!wKHN>#(G@u{fokV4efN2nYzCA^!kH9((iC(EQ`g^Br(tm+XQo&2+^sZj zyNPp)6gZ~Nj=Q!ZPF(!vyX&q0@szJ?Rd9mkCR(A>>Ltj=txqVu8=M3YJEco~p}i zCYw@1jH#_#{|M=V$C1&e0f|CO!rP*)=^d7*PptO7Nu(*J+=>AV4BoGwV6u{s?T`UW z=7`|0g|vPR6D8KdFRF3@j?6?L9J|5w7Z>A?Mc#Tf&nY`Z)I5W--0N#Nt$q%Ozc$=z z;)$fbnqJ!n`Cq0OAJSYX4T(t?Y-X*~G)Z`0%p*_GcOo2UR( zSvaxe%ZVKd%fvP=1+KBtdAc#apW5wu_K1KDzfx4&N4ku8_uFYqQn`kKc8#c-gfIYE zsEj*B)K}a_K9a6s$GwjJq^U<$bwD|N3NNrsrkZ70+aEx>3&XI7N$f@~$GW@j=3$FD zeH*X%q%y1I-UVoiM569f%WxxCd_7a1!Gsu-;2O+<$DHTj6O-}Q*xJypH=O)x&3(XX z?a|XgaJHzVPBFf;oEp<}-}pBNOrp+Zq0O7YI1(-Cf+%^S;l`JKw!MHPLHo_FJ3FH% zOl@+oE5vTbvL4m2=T0*qxiAADKquDLuJS1^7j`WvrI*f%&f!i`Z-kQ`a(B>)9}ct{YWFrinlQ9LrRVH?iBh6qb!! zx5O5dZrw6PFcY6PfMg>0D^)>r?}pv$D?5<|P8lYRgMx~D$`D2S=;`2`?~IAwm4|MO zcv%7!g(Q&AF_%Uf3U#C0&>c8SSw(aDJyY{{k7#7)7n`>-Qa$R1Z6i+X@h13&KnSG> z@Q*W#sk2kTHoYas6DQ73)@3}4b|Pf;a(ZTzeR|VWt@J5dzfx-k(5Mp42R_ARDYM*(QJgvO;)UBZrpV@IjM%W z2)q4AR1OTvX*@vnZoYjx65ND-KXSDawHpnq60IS}aL8AV<|>~5;%$=3gN%Q`v^W$( zqjFM;%Bp_XfGvn9GHT9fAf51b^g+V087hZVD@p|@qW8z3@!&uCe1usFNsXKw#grqL;S;(hP|FZ;!$uWl z=c#D1vK+a)5Ofrk-06OG!?nSWC4s4R<))mRw-3=*G54aPJyPx>IJ6U#+l=8akFpM5 zi;k8knQ$JwU1SAECMm>c;fYejac*zivyV1gE;5 zaJf*MltT`K(tPw}zb`!l)X2mgblg!PL`+NFf{^k!Uav$oG*KDmh}{@k2;v%57d zzF{&R>Ecxht;{!c)#e5spVqS#_U$1u8)NS4zRkc~NS%tmI*;=yL!+kGP~R^lD>H)@ z5WS~HByt-defgkQ$Plc5{a9>?USn#eI;ek4(d*B95ImVqgtV z_{M1d42HQa28r#&v&*d<1MMW=uT`DF!%$3JE!$ZvFbdvxT&>k<9XQ_FxGrPREcdN$ zBYjFOgBNZcAaa`}+jQTjlImv1mi z_Qsi+boL7AByp%`+Di$Vq7?~PUGu_a1Qit#FO17KYcU_f%V%N=hijyfh`+GLmVTOR z*!p~Xz4~^{MD5iP-Y3z+)M_eFMn9zObs;hLIvUMqSOKv$HL5GB-C?Iua#wi2fEV8G zzijCftafp?%`-kFuud}k@DNqTN2M{iRYQeZgn@P@*OrfOODs*-mHchI^Qq6Zk{VnE z_bk__#-6WU@}BhqjN42F194o7PsN`2OPvKECbfZtoP&m)NY=FTppnip32t}~ytv=XD4O%BFP04X&yi1!25 zwkJtPqly&ZCLm;4-re4|H5Hm&;xhL3Ee4g$BBHNAL8eW?2IMnTIR6veesBRqDj|Kl zliwtO({k~I>_BLv!{#MhfOr8TfFjf;#E*4Y=?T`wj^Z#hD1CA_2yQ1P6b9cHl+&EQ z=3#Pj4w`ANi9-i4BvWp_5Ak{yf_%+h7Os)QId6>Qcb!!wAR#~nG)Y_cR z3CQ<78xQ2d^bv%`3#nU|Ab!+=V$%MXP6)NG*F9&|M3kkKgy~GB%zwKsdt zN=C-=Q5$qLV!fskyXdoTNG6?4;R@a4tn@0v&!hTKvu?u<5=puj9zgUaK{1r5W=q(U zlht@D2u)N4f6-*?f}M0LId1wcZEV|KblAIpAijlEj0igAq@c_VW9_7r{PoMc*y&Q{ zG;_>^wu5uMB~H6KyUWVe)PilJbm-78f+woCz2}-|M&Z`5o{+DY+$w_JYldi3#uov5 zTI`f>45dgl>$WoN5S`%(Y=@%hl`-(B4_PLK2M=bGGK2ybDGeiBIs%}KqminvPX@}tU z2{*P=`))VY9TR0!;F-oeOFB@$|K|rWm|Y-!i{a-1^1G0`3E-pXo~g^ai>S)yhw+;R z%rDvg;HywlwNbY?+t0q(ju+=95(~?<$H^g~u@(Ku%=U*uMc6pA?mX?3ANI0)=cAF{ zrSb_L>uGJ+0h#Y9t09rjT5iXFELD^E9_c7sqZw3)ntOnGI0Y=guq|%+CjFVI0C=z{ zmZ#k73IEx5e!3&+yZ(&ry17-MS6={vwW5R&

      ^YCwkh`hT>!76QHFRA0CuntPE$DTZtD2w`Ip$1N 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 Date: Thu, 21 Mar 2019 10:30:38 -0700 Subject: [PATCH 027/223] Bounds check. Fix #849 (#851) --- .../Formats/Png/Zlib/ZlibInflateStream.cs | 9 ++++++++- .../Formats/Png/PngDecoderTests.cs | 3 ++- tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Png/zlib-overflow.png | Bin 0 -> 10725 bytes 4 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 tests/Images/Input/Png/zlib-overflow.png diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs index 583175b56..71141a893 100644 --- a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs +++ b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs @@ -126,8 +126,9 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib int bytesToRead = Math.Min(count, this.currentDataRemaining); this.currentDataRemaining -= bytesToRead; int bytesRead = this.innerStream.Read(buffer, offset, bytesToRead); + long length = this.innerStream.Length; - // keep reading data until we've reached the end of the stream or filled the buffer + // Keep reading data until we've reached the end of the stream or filled the buffer while (this.currentDataRemaining == 0 && bytesRead < count) { this.currentDataRemaining = this.getData(); @@ -138,6 +139,12 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib } offset += bytesRead; + + if (offset >= length) + { + return bytesRead; + } + bytesToRead = Math.Min(count - bytesRead, this.currentDataRemaining); this.currentDataRemaining -= bytesToRead; bytesRead += this.innerStream.Read(buffer, offset, bytesToRead); diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index eca7a2543..fe406c992 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -41,7 +41,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png TestImages.Png.Rgb24BppTrans, TestImages.Png.GrayAlpha8Bit, - TestImages.Png.Gray1BitTrans + TestImages.Png.Gray1BitTrans, + TestImages.Png.Bad.ZlibOverflow }; public static readonly string[] TestImages48Bpp = diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 3f12fab12..909969624 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -85,6 +85,7 @@ namespace SixLabors.ImageSharp.Tests public const string ChunkLength1 = "Png/chunklength1.png"; public const string ChunkLength2 = "Png/chunklength2.png"; public const string CorruptedChunk = "Png/big-corrupted-chunk.png"; + public const string ZlibOverflow = "Png/zlib-overflow.png"; } public static readonly string[] All = diff --git a/tests/Images/Input/Png/zlib-overflow.png b/tests/Images/Input/Png/zlib-overflow.png new file mode 100644 index 0000000000000000000000000000000000000000..979e94274c60b2e886614cdadc0b0d917ceb3a3c GIT binary patch literal 10725 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 X(w@Bf`q(In00000NkvXXu0mjfk^tow literal 0 HcmV?d00001 From 13e2aa7f1dfcb1424f4d1ff92cf911ceece14135 Mon Sep 17 00:00:00 2001 From: Kjetil Klaussen Date: Thu, 21 Mar 2019 18:43:38 +0100 Subject: [PATCH 028/223] #852 Adding instructions to add submodules when cloning the repository --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index a72074f8f..079f2106f 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,14 @@ To clone ImageSharp locally click the "Clone in Windows" button above or run the git clone https://github.com/SixLabors/ImageSharp ``` +### Submodules + +This repository contains [git submodule](https://blog.github.com/2016-02-01-working-with-submodules/). To add the submodules to the project, navigate to the repository root and type: + +``` bash +git submodule update --init --recursive +``` + ### How can you help? Please... Spread the word, contribute algorithms, submit performance improvements, unit tests, no input is too little. Make sure to read our [Contribution Guide](https://github.com/SixLabors/ImageSharp/blob/master/.github/CONTRIBUTING.md) before opening a PR. From e780d609fe026c10a0340e0bebeababddaddbe0d Mon Sep 17 00:00:00 2001 From: Kjetil Klaussen Date: Thu, 21 Mar 2019 18:48:23 +0100 Subject: [PATCH 029/223] fix: Typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 079f2106f..ceb28564b 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ git clone https://github.com/SixLabors/ImageSharp ### Submodules -This repository contains [git submodule](https://blog.github.com/2016-02-01-working-with-submodules/). To add the submodules to the project, navigate to the repository root and type: +This repository contains [git submodules](https://blog.github.com/2016-02-01-working-with-submodules/). To add the submodules to the project, navigate to the repository root and type: ``` bash git submodule update --init --recursive From 5eb01223736de14ccb8abd990dbd3aff6d42d903 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Mon, 25 Mar 2019 18:30:29 -0700 Subject: [PATCH 030/223] Updating some readonly static data in JpegEncoderCore to take advantage of compiler functionality. (#855) --- .../Common/Extensions/StreamExtensions.cs | 21 ++ .../Formats/Jpeg/JpegEncoderCore.cs | 185 ++++++++++-------- 2 files changed, 124 insertions(+), 82 deletions(-) diff --git a/src/ImageSharp/Common/Extensions/StreamExtensions.cs b/src/ImageSharp/Common/Extensions/StreamExtensions.cs index a200ffebc..505ecccdd 100644 --- a/src/ImageSharp/Common/Extensions/StreamExtensions.cs +++ b/src/ImageSharp/Common/Extensions/StreamExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; using System.IO; using SixLabors.ImageSharp.Memory; @@ -82,5 +83,25 @@ namespace SixLabors.ImageSharp { stream.Write(buffer.Array, 0, buffer.Length()); } + +#if NET472 || NETSTANDARD1_3 || NETSTANDARD2_0 + // This is a port of the CoreFX implementation and is MIT Licensed: https://github.com/dotnet/coreclr/blob/c4dca1072d15bdda64c754ad1ea474b1580fa554/src/System.Private.CoreLib/shared/System/IO/Stream.cs#L770 + public static void Write(this Stream stream, ReadOnlySpan buffer) + { + // This uses ArrayPool.Shared, rather than taking a MemoryAllocator, + // in order to match the signature of the framework method that exists in + // .NET Core. + byte[] sharedBuffer = ArrayPool.Shared.Rent(buffer.Length); + try + { + buffer.CopyTo(sharedBuffer); + stream.Write(sharedBuffer, 0, buffer.Length); + } + finally + { + ArrayPool.Shared.Return(sharedBuffer); + } + } +#endif } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index b3f30f815..4544244f0 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -27,85 +27,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ///

      `V!j!cc(}uB0IO{{He@hc!mFdZ5 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 {%M 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
    ?C16kgK{lOEiz6=n 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

private const int QuantizationTableCount = 2; - /// - /// Counts the number of bits needed to hold an integer. - /// - private static readonly uint[] BitCountLut = - { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, - }; - - /// - /// 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 = - { - JpegConstants.Markers.XFF, JpegConstants.Markers.SOS, - - // Marker - 0x00, 0x0c, - - // Length (high byte, low byte), must be 6 + 2 * (number of components in scan) - 0x03, // Number of components in a scan, 3 - 0x01, // Component Id Y - 0x00, // DC/AC Huffman table - 0x02, // Component Id Cb - 0x11, // DC/AC Huffman table - 0x03, // Component Id Cr - 0x11, // DC/AC Huffman table - 0x00, // Ss - Start of spectral selection. - 0x3f, // Se - End of spectral selection. - 0x00 - - // Ah + Ah (Successive approximation bit position high + low) - }; - - /// - /// 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 = - { - { - // Luminance. - 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, - 40, 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, - 57, 51, 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, - 109, 81, 87, 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, - 100, 120, 92, 101, 103, 99, - }, - { - // Chrominance. - 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - } - }; - /// /// A scratch buffer to reduce allocations. /// @@ -167,6 +88,103 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.subsample = options.Subsample; } + /// + /// Gets the counts the number of bits needed to hold an integer. + /// + // The C# compiler emits this as a compile-time constant embedded in the PE file. + // This is effectively compiled down to: return new ReadOnlySpan(&data, length) + // More details can be found: https://github.com/dotnet/roslyn/pull/24621 + private static ReadOnlySpan BitCountLut => new byte[] + { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, + }; + + /// + /// Gets 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 C# compiler emits this as a compile-time constant embedded in the PE file. + // This is effectively compiled down to: return new ReadOnlySpan(&data, length) + // More details can be found: https://github.com/dotnet/roslyn/pull/24621 + private static ReadOnlySpan SosHeaderYCbCr => new byte[] + { + JpegConstants.Markers.XFF, JpegConstants.Markers.SOS, + + // Marker + 0x00, 0x0c, + + // Length (high byte, low byte), must be 6 + 2 * (number of components in scan) + 0x03, // Number of components in a scan, 3 + 0x01, // Component Id Y + 0x00, // DC/AC Huffman table + 0x02, // Component Id Cb + 0x11, // DC/AC Huffman table + 0x03, // Component Id Cr + 0x11, // DC/AC Huffman table + 0x00, // Ss - Start of spectral selection. + 0x3f, // Se - End of spectral selection. + 0x00 + + // Ah + Ah (Successive approximation bit position high + low) + }; + + /// + /// Gets 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 C# compiler emits this as a compile-time constant embedded in the PE file. + // This is effectively compiled down to: return new ReadOnlySpan(&data, length) + // More details can be found: https://github.com/dotnet/roslyn/pull/24621 + private static ReadOnlySpan UnscaledQuant_Luminance => new byte[] + { + // Luminance. + 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, + 40, 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, + 57, 51, 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, + 109, 81, 87, 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, + 100, 120, 92, 101, 103, 99, + }; + + /// + /// Gets 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 C# compiler emits this as a compile-time constant embedded in the PE file. + // This is effectively compiled down to: return new ReadOnlySpan(&data, length) + // More details can be found: https://github.com/dotnet/roslyn/pull/24621 + private static ReadOnlySpan UnscaledQuant_Chrominance => new byte[] + { + // Chrominance. + 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + }; + /// /// Encode writes the image to the jpeg baseline format with the given options. /// @@ -259,9 +277,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The quantization table. private static void InitQuantizationTable(int i, int scale, ref Block8x8F quant) { + DebugGuard.MustBeBetweenOrEqualTo(i, 0, 1, nameof(i)); + var unscaledQuant = (i == 0) ? UnscaledQuant_Luminance : UnscaledQuant_Chrominance; + for (int j = 0; j < Block8x8F.Size; j++) { - int x = UnscaledQuant[i, j]; + int x = unscaledQuant[j]; x = ((x * scale) + 50) / 100; if (x < 1) { @@ -357,7 +378,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } else { - bt = 8 + BitCountLut[a >> 8]; + bt = 8 + (uint)BitCountLut[a >> 8]; } this.EmitHuff(index, (int)((uint)(runLength << 4) | bt)); @@ -871,7 +892,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { // TODO: Need a JpegScanEncoder class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) // TODO: We should allow grayscale writing. - this.outputStream.Write(SosHeaderYCbCr, 0, SosHeaderYCbCr.Length); + this.outputStream.Write(SosHeaderYCbCr); switch (this.subsample) { From 45b7490c73d71be9c3781733d02604e107ff0570 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 26 Mar 2019 04:29:08 -0700 Subject: [PATCH 031/223] Remove enum boxing allocations (#863) --- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 2 +- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index a922f3011..c8580144a 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp.Formats.Gif ImageMetaData metaData = image.MetaData; this.gifMetaData = metaData.GetFormatMetaData(GifFormat.Instance); this.colorTableMode = this.colorTableMode ?? this.gifMetaData.ColorTableMode; - bool useGlobalTable = this.colorTableMode.Equals(GifColorTableMode.Global); + bool useGlobalTable = this.colorTableMode == GifColorTableMode.Global; // Quantize the image returning a palette. QuantizedFrame quantized = diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 216f3129f..96e2dd946 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -185,7 +185,7 @@ namespace SixLabors.ImageSharp.Formats.Png this.pngColorType = options.ColorType; // Specification recommends default filter method None for paletted images and Paeth for others. - this.pngFilterMethod = options.FilterMethod ?? (options.ColorType.Equals(PngColorType.Palette) + this.pngFilterMethod = options.FilterMethod ?? (options.ColorType == PngColorType.Palette ? PngFilterMethod.None : PngFilterMethod.Paeth); this.compressionLevel = options.CompressionLevel; @@ -217,7 +217,7 @@ namespace SixLabors.ImageSharp.Formats.Png this.writeGamma = this.gamma > 0; this.pngColorType = this.pngColorType ?? pngMetaData.ColorType; this.pngBitDepth = this.pngBitDepth ?? pngMetaData.BitDepth; - this.use16Bit = this.pngBitDepth.Equals(PngBitDepth.Bit16); + this.use16Bit = this.pngBitDepth == PngBitDepth.Bit16; // Ensure we are not allowing impossible combinations. if (!ColorTypes.ContainsKey(this.pngColorType.Value)) @@ -329,7 +329,7 @@ namespace SixLabors.ImageSharp.Formats.Png Span rawScanlineSpan = this.rawScanline.GetSpan(); ref byte rawScanlineSpanRef = ref MemoryMarshal.GetReference(rawScanlineSpan); - if (this.pngColorType.Equals(PngColorType.Grayscale)) + if (this.pngColorType == PngColorType.Grayscale) { if (this.use16Bit) { @@ -761,7 +761,7 @@ namespace SixLabors.ImageSharp.Formats.Png private void WriteTransparencyChunk(Stream stream, PngMetaData pngMetaData) { Span alpha = this.chunkDataBuffer.AsSpan(); - if (pngMetaData.ColorType.Equals(PngColorType.Rgb)) + if (pngMetaData.ColorType == PngColorType.Rgb) { if (pngMetaData.TransparentRgb48.HasValue && this.use16Bit) { @@ -782,7 +782,7 @@ namespace SixLabors.ImageSharp.Formats.Png this.WriteChunk(stream, PngChunkType.Transparency, this.chunkDataBuffer, 0, 6); } } - else if (pngMetaData.ColorType.Equals(PngColorType.Grayscale)) + else if (pngMetaData.ColorType == PngColorType.Grayscale) { if (pngMetaData.TransparentGray16.HasValue && this.use16Bit) { From e217d13cc5f03e9346f2aa675f36ea11f726a405 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 31 Mar 2019 22:55:14 +0200 Subject: [PATCH 032/223] make .FromVector4() destructive --- ImageSharp.sln.DotSettings | 1 + src/ImageSharp/Common/Helpers/Guard.cs | 20 +++++++++++++++++++ .../Argb32.PixelOperations.Generated.cs | 4 ++-- .../Bgr24.PixelOperations.Generated.cs | 4 ++-- .../Bgra32.PixelOperations.Generated.cs | 4 ++-- .../Rgb24.PixelOperations.Generated.cs | 4 ++-- .../Generated/_Common.ttinclude | 4 ++-- .../Rgba32.PixelOperations.cs | 4 ++-- .../RgbaVector.PixelOperations.cs | 2 +- .../PixelFormats/PixelOperations{TPixel}.cs | 12 +++++++++-- 10 files changed, 44 insertions(+), 15 deletions(-) diff --git a/ImageSharp.sln.DotSettings b/ImageSharp.sln.DotSettings index 432f4524a..8e7b5dd48 100644 --- a/ImageSharp.sln.DotSettings +++ b/ImageSharp.sln.DotSettings @@ -382,6 +382,7 @@ True True True + True True True True diff --git a/src/ImageSharp/Common/Helpers/Guard.cs b/src/ImageSharp/Common/Helpers/Guard.cs index d8cf69a52..e86da78e3 100644 --- a/src/ImageSharp/Common/Helpers/Guard.cs +++ b/src/ImageSharp/Common/Helpers/Guard.cs @@ -257,6 +257,26 @@ namespace SixLabors.ImageSharp } } + /// + /// Verifies that the 'destination' span is not shorter than 'source'. + /// + /// The source element type + /// The destination element type + /// The source span + /// The destination span + /// The name of the argument for 'destination' + [MethodImpl(InliningOptions.ShortMethod)] + public static void DestinationShouldNotBeTooShort( + Span source, + Span destination, + string destinationParamName) + { + if (destination.Length < source.Length) + { + ThrowArgumentException($"Destination span is too short!", destinationParamName); + } + } + /// /// Verifies, that the `source` span has the length of 'minLength', or longer. /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs index 2ec965dfb..add48cfd8 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + internal override void FromScaledVector4(Configuration configuration, Span sourceVectors, Span destPixels) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs index 711a9d1c1..372c71b32 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + internal override void FromScaledVector4(Configuration configuration, Span sourceVectors, Span destPixels) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs index b669dd534..aa4680dcc 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + internal override void FromScaledVector4(Configuration configuration, Span sourceVectors, Span destPixels) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index dbf3102c4..f87ed88e5 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels) + internal override void FromScaledVector4(Configuration configuration, Span sourceVectors, Span destPixels) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude index f0675cb5b..bfeccfca5 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude @@ -111,7 +111,7 @@ using System.Runtime.InteropServices; { #> /// - internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span<<#=pixelType#>> destPixels) + internal override void FromVector4(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } @@ -123,7 +123,7 @@ using System.Runtime.InteropServices; } /// - internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span<<#=pixelType#>> destPixels) + internal override void FromScaledVector4(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs index 004b25cd3..2801b8225 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4( Configuration configuration, - ReadOnlySpan sourceVectors, + Span sourceVectors, Span destPixels) { Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); @@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromScaledVector4( Configuration configuration, - ReadOnlySpan sourceVectors, + Span sourceVectors, Span destinationColors) { this.FromVector4(configuration, sourceVectors, destinationColors); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs index bffaf57dd..0cde00736 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromScaledVector4( Configuration configuration, - ReadOnlySpan sourceVectors, + Span sourceVectors, Span destinationColors) { Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 115dd7a43..61e338b9c 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -9,6 +9,14 @@ using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.PixelFormats { + internal enum PixelConversionModifiers + { + None = 0, + Scale = 1 << 0, + Premultiply = 1 << 1, + SRgbCompand = 1 << 2, + } + /// /// A stateless class implementing Strategy Pattern for batched pixel-data conversion operations /// for pixel buffers of type . @@ -30,7 +38,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the destination colors. internal virtual void FromVector4( Configuration configuration, - ReadOnlySpan sourceVectors, + Span sourceVectors, Span destPixels) { Guard.NotNull(configuration, nameof(configuration)); @@ -64,7 +72,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The to the destination colors. internal virtual void FromScaledVector4( Configuration configuration, - ReadOnlySpan sourceVectors, + Span sourceVectors, Span destinationColors) { Guard.NotNull(configuration, nameof(configuration)); From 877f31487c835ea765006ddb30fcfe99429431c1 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 31 Mar 2019 23:28:34 +0200 Subject: [PATCH 033/223] replace FromScaledVector4() / ToScaledVector4() with flag usages --- .../Argb32.PixelOperations.Generated.cs | 17 +--- .../Bgr24.PixelOperations.Generated.cs | 17 +--- .../Bgra32.PixelOperations.Generated.cs | 17 +--- .../Rgb24.PixelOperations.Generated.cs | 17 +--- .../Generated/_Common.ttinclude | 17 +--- .../Rgba32.PixelOperations.cs | 24 +---- .../RgbaVector.PixelOperations.cs | 35 +++++--- .../PixelFormats/PixelOperations{TPixel}.cs | 88 ++++++++++++------- .../Utils/Vector4Converters.RgbaCompatible.cs | 4 +- 9 files changed, 97 insertions(+), 139 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs index add48cfd8..e832bc97f 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs @@ -42,29 +42,16 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels) + internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } /// - internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); } - - /// - internal override void FromScaledVector4(Configuration configuration, Span sourceVectors, Span destPixels) - { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); - } - - /// - internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) - { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true); - } - /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs index 372c71b32..f1885c71b 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs @@ -42,30 +42,17 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels) + internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } /// - internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); } - /// - internal override void FromScaledVector4(Configuration configuration, Span sourceVectors, Span destPixels) - { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); - } - - /// - internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) - { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true); - } - - /// internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs index aa4680dcc..2409f6784 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs @@ -42,29 +42,16 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels) + internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } /// - internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); } - - /// - internal override void FromScaledVector4(Configuration configuration, Span sourceVectors, Span destPixels) - { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); - } - - /// - internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) - { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true); - } - /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index f87ed88e5..ddf9813ab 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -42,30 +42,17 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels) + internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } /// - internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) + internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); } - /// - internal override void FromScaledVector4(Configuration configuration, Span sourceVectors, Span destPixels) - { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); - } - - /// - internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) - { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true); - } - - /// internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) { diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude index bfeccfca5..0ff5b8605 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude @@ -111,29 +111,16 @@ using System.Runtime.InteropServices; { #> /// - internal override void FromVector4(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels) + internal override void FromVector4(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); } /// - internal override void ToVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors) + internal override void ToVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); } - - /// - internal override void FromScaledVector4(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels) - { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true); - } - - /// - internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors) - { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true); - } - <#+ } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs index 2801b8225..7e8bb7f29 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs @@ -22,7 +22,8 @@ namespace SixLabors.ImageSharp.PixelFormats internal override void ToVector4( Configuration configuration, ReadOnlySpan sourcePixels, - Span destVectors) + Span destVectors, + PixelConversionModifiers modifiers) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); @@ -37,7 +38,8 @@ namespace SixLabors.ImageSharp.PixelFormats internal override void FromVector4( Configuration configuration, Span sourceVectors, - Span destPixels) + Span destPixels, + PixelConversionModifiers modifiers) { Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); @@ -47,24 +49,6 @@ namespace SixLabors.ImageSharp.PixelFormats MemoryMarshal.Cast(sourceVectors), MemoryMarshal.Cast(destPixels)); } - - /// - internal override void ToScaledVector4( - Configuration configuration, - ReadOnlySpan sourceColors, - Span destinationVectors) - { - this.ToVector4(configuration, sourceColors, destinationVectors); - } - - /// - internal override void FromScaledVector4( - Configuration configuration, - Span sourceVectors, - Span destinationColors) - { - this.FromVector4(configuration, sourceVectors, destinationColors); - } } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs index 0cde00736..777d0da6d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs @@ -18,32 +18,43 @@ namespace SixLabors.ImageSharp.PixelFormats internal class PixelOperations : PixelOperations { /// - internal override void FromScaledVector4( + internal override void FromVector4( Configuration configuration, Span sourceVectors, - Span destinationColors) + Span destinationColors, + PixelConversionModifiers modifiers) { Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); - MemoryMarshal.Cast(sourceVectors).CopyTo(destinationColors); + // TODO: Repeating previous override behavior here. Not sure if this is correct! + if (modifiers.IsDefined(PixelConversionModifiers.Scale)) + { + MemoryMarshal.Cast(sourceVectors).CopyTo(destinationColors); + } + else + { + base.FromVector4(configuration, sourceVectors, destinationColors, modifiers); + } } - /// - internal override void ToScaledVector4( - Configuration configuration, - ReadOnlySpan sourceColors, - Span destinationVectors) - => this.ToVector4(configuration, sourceColors, destinationVectors); - /// internal override void ToVector4( Configuration configuration, ReadOnlySpan sourcePixels, - Span destVectors) + Span destVectors, + PixelConversionModifiers modifiers) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - MemoryMarshal.Cast(sourcePixels).CopyTo(destVectors); + // TODO: Repeating previous override behavior here. Not sure if this is correct! + if (modifiers.IsDefined(PixelConversionModifiers.Scale)) + { + base.ToVector4(configuration, sourcePixels, destVectors, modifiers); + } + else + { + MemoryMarshal.Cast(sourcePixels).CopyTo(destVectors); + } } } } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 61e338b9c..44c7f2e30 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -17,6 +17,12 @@ namespace SixLabors.ImageSharp.PixelFormats SRgbCompand = 1 << 2, } + internal static class PixelConversionModifiersExtensions + { + public static bool IsDefined(this PixelConversionModifiers modifiers, PixelConversionModifiers expected) => + (modifiers & expected) == expected; + } + /// /// A stateless class implementing Strategy Pattern for batched pixel-data conversion operations /// for pixel buffers of type . @@ -32,71 +38,93 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'. + /// TODO: Rename to DestructiveFromVector4() + add explain behavior /// /// A to configure internal operations /// The to the source vectors. /// The to the destination colors. + /// The to apply during the conversion internal virtual void FromVector4( Configuration configuration, Span sourceVectors, - Span destPixels) + Span destPixels, + PixelConversionModifiers modifiers) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); - Utils.Vector4Converters.Default.DangerousFromVector4(sourceVectors, destPixels); + if (modifiers.IsDefined(PixelConversionModifiers.Scale)) + { + Utils.Vector4Converters.Default.DangerousFromScaledVector4(sourceVectors, destPixels); + } + else + { + Utils.Vector4Converters.Default.DangerousFromVector4(sourceVectors, destPixels); + } } + /// + /// TODO: For compatibility, should be inlined! + /// + internal void FromScaledVector4( + Configuration configuration, + Span sourceVectors, + Span destPixels) => + this.FromVector4(configuration, sourceVectors, destPixels, PixelConversionModifiers.Scale); + + /// + /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'. + /// TODO: Rename to DestructiveFromVector4() + add explain behavior + /// + /// A to configure internal operations + /// The to the source vectors. + /// The to the destination colors. + internal void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels) => + this.FromVector4(configuration, sourceVectors, destPixels, PixelConversionModifiers.None); + /// /// Bulk version of converting 'sourceColors.Length' pixels into 'destinationVectors'. /// /// A to configure internal operations /// The to the source colors. /// The to the destination vectors. + /// The to apply during the conversion internal virtual void ToVector4( Configuration configuration, ReadOnlySpan sourcePixels, - Span destVectors) + Span destVectors, + PixelConversionModifiers modifiers) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - Utils.Vector4Converters.Default.DangerousToVector4(sourcePixels, destVectors); + if (modifiers.IsDefined(PixelConversionModifiers.Scale)) + { + Utils.Vector4Converters.Default.DangerousToScaledVector4(sourcePixels, destVectors); + } + else + { + Utils.Vector4Converters.Default.DangerousToVector4(sourcePixels, destVectors); + } } /// - /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'. + /// Bulk version of converting 'sourceColors.Length' pixels into 'destinationVectors'. /// /// A to configure internal operations - /// The to the source vectors. - /// The to the destination colors. - internal virtual void FromScaledVector4( + /// The to the source colors. + /// The to the destination vectors. + internal virtual void ToVector4( Configuration configuration, - Span sourceVectors, - Span destinationColors) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); - - Utils.Vector4Converters.Default.DangerousFromScaledVector4(sourceVectors, destinationColors); - } + ReadOnlySpan sourcePixels, + Span destVectors) => + this.ToVector4(configuration, sourcePixels, destVectors, PixelConversionModifiers.None); /// - /// Bulk version of converting 'sourceColors.Length' pixels into 'destinationVectors'. + /// TODO: For compatibility, should be inlined! /// - /// A to configure internal operations - /// The to the source colors. - /// The to the destination vectors. - internal virtual void ToScaledVector4( - Configuration configuration, - ReadOnlySpan sourceColors, - Span destinationVectors) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors)); - - Utils.Vector4Converters.Default.DangerousToScaledVector4(sourceColors, destinationVectors); - } + internal void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) => + this.ToVector4(configuration, sourcePixels, destVectors, PixelConversionModifiers.Scale); /// /// Converts 'sourceColors.Length' pixels from 'sourceColors' into 'destinationColors'. diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs index 06c33d79c..006ebe828 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils private static readonly int Vector4ConversionThreshold = CalculateVector4ConversionThreshold(); /// - /// Provides an efficient default implementation for + /// Provides an efficient default implementation for /// and /// which is applicable for -compatible pixel types where /// returns the same scaled result as . @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } /// - /// Provides an efficient default implementation for + /// Provides an efficient default implementation for /// and /// which is applicable for -compatible pixel types where /// returns the same scaled result as . From b0ff7cf6b6929f35de310b7d61c24ae839fd95d7 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 31 Mar 2019 23:40:56 +0200 Subject: [PATCH 034/223] copy companding refactor from #847 --- .../ColorSpaces/Companding/SRgbCompanding.cs | 24 +++++++++++-------- .../PixelFormats/PixelConversionModifiers.cs | 16 +++++++++++++ .../PixelConversionModifiersExtensions.cs | 20 ++++++++++++++++ .../PixelFormats/PixelOperations{TPixel}.cs | 14 ----------- .../Colorspaces/Companding/CompandingTests.cs | 20 ++++++++++++++-- 5 files changed, 68 insertions(+), 26 deletions(-) create mode 100644 src/ImageSharp/PixelFormats/PixelConversionModifiers.cs create mode 100644 src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs diff --git a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs index 5ae462913..bbd454fbe 100644 --- a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs @@ -30,9 +30,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding for (int i = 0; i < vectors.Length; i++) { ref Vector4 v = ref Unsafe.Add(ref baseRef, i); - v.X = Expand(v.X); - v.Y = Expand(v.Y); - v.Z = Expand(v.Z); + Expand(ref v); } } @@ -48,9 +46,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding for (int i = 0; i < vectors.Length; i++) { ref Vector4 v = ref Unsafe.Add(ref baseRef, i); - v.X = Compress(v.X); - v.Y = Compress(v.Y); - v.Z = Compress(v.Z); + Compress(ref v); } } @@ -58,17 +54,25 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// Expands a companded vector to its linear equivalent with respect to the energy. /// /// The vector. - /// The representing the linear channel values. [MethodImpl(InliningOptions.ShortMethod)] - public static Vector4 Expand(Vector4 vector) => new Vector4(Expand(vector.X), Expand(vector.Y), Expand(vector.Z), vector.W); + public static void Expand(ref Vector4 vector) + { + vector.X = Expand(vector.X); + vector.Y = Expand(vector.Y); + vector.Z = Expand(vector.Z); + } /// /// Compresses an uncompanded vector (linear) to its nonlinear equivalent. /// /// The vector. - /// The representing the nonlinear channel values. [MethodImpl(InliningOptions.ShortMethod)] - public static Vector4 Compress(Vector4 vector) => new Vector4(Compress(vector.X), Compress(vector.Y), Compress(vector.Z), vector.W); + public static void Compress(ref Vector4 vector) + { + vector.X = Compress(vector.X); + vector.Y = Compress(vector.Y); + vector.Z = Compress(vector.Z); + } /// /// Expands a companded channel to its linear equivalent with respect to the energy. diff --git a/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs b/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs new file mode 100644 index 000000000..536a23061 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs @@ -0,0 +1,16 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +namespace SixLabors.ImageSharp.PixelFormats +{ + [Flags] + internal enum PixelConversionModifiers + { + None = 0, + Scale = 1 << 0, + Premultiply = 1 << 1, + SRgbCompand = 1 << 2, + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs b/src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs new file mode 100644 index 000000000..bf77f8511 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs @@ -0,0 +1,20 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.PixelFormats +{ + internal static class PixelConversionModifiersExtensions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsDefined(this PixelConversionModifiers modifiers, PixelConversionModifiers expected) => + (modifiers & expected) == expected; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static PixelConversionModifiers Remove( + this PixelConversionModifiers modifiers, + PixelConversionModifiers removeThis) => + modifiers & ~removeThis; + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 44c7f2e30..ea5bc876f 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -9,20 +9,6 @@ using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.PixelFormats { - internal enum PixelConversionModifiers - { - None = 0, - Scale = 1 << 0, - Premultiply = 1 << 1, - SRgbCompand = 1 << 2, - } - - internal static class PixelConversionModifiersExtensions - { - public static bool IsDefined(this PixelConversionModifiers modifiers, PixelConversionModifiers expected) => - (modifiers & expected) == expected; - } - /// /// A stateless class implementing Strategy Pattern for batched pixel-data conversion operations /// for pixel buffers of type . diff --git a/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs b/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs index 91cacfe3f..b2ee03048 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs @@ -53,7 +53,15 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Companding { var rnd = new Random(42); Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); - Vector4[] expected = source.Select(v => SRgbCompanding.Expand(v)).ToArray(); + var expected = new Vector4[source.Length]; + + for (int i = 0; i < source.Length; i++) + { + Vector4 s = source[i]; + ref Vector4 e = ref expected[i]; + SRgbCompanding.Expand(ref s); + e = s; + } SRgbCompanding.Expand(source); @@ -68,7 +76,15 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Companding { var rnd = new Random(42); Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); - Vector4[] expected = source.Select(v => SRgbCompanding.Compress(v)).ToArray(); + var expected = new Vector4[source.Length]; + + for (int i = 0; i < source.Length; i++) + { + Vector4 s = source[i]; + ref Vector4 e = ref expected[i]; + SRgbCompanding.Compress(ref s); + e = s; + } SRgbCompanding.Compress(source); From d126b8591ebdeaf6f997f7b0a87aed465ab0de86 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 31 Mar 2019 23:49:43 +0200 Subject: [PATCH 035/223] add (failing) tests from #847 --- ...xelOperationsTests.Rgb24OperationsTests.cs | 23 ++ .../PixelOperations/PixelOperationsTests.cs | 270 +++++++++++++++++- 2 files changed, 280 insertions(+), 13 deletions(-) create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs new file mode 100644 index 000000000..fa51c2278 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs @@ -0,0 +1,23 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class Rgb24OperationsTests : PixelOperationsTests + { + public Rgb24OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index d9845e474..9433e19c9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -6,7 +6,7 @@ using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.ColorSpaces.Companding; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -70,25 +70,33 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations internal static PixelOperations Operations => PixelOperations.Instance; - internal static TPixel[] CreateExpectedPixelData(Vector4[] source) + internal static TPixel[] CreateExpectedPixelData(Vector4[] source, RefAction vectorModifier = null) { var expected = new TPixel[source.Length]; for (int i = 0; i < expected.Length; i++) { - expected[i].FromVector4(source[i]); + Vector4 v = source[i]; + vectorModifier?.Invoke(ref v); + + expected[i].FromVector4(v); } + return expected; } - internal static TPixel[] CreateScaledExpectedPixelData(Vector4[] source) + internal static TPixel[] CreateScaledExpectedPixelData(Vector4[] source, RefAction vectorModifier = null) { var expected = new TPixel[source.Length]; for (int i = 0; i < expected.Length; i++) { - expected[i].FromScaledVector4(source[i]); + Vector4 v = source[i]; + vectorModifier?.Invoke(ref v); + + expected[i].FromScaledVector4(v); } + return expected; } @@ -120,6 +128,112 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations ); } + [Theory] + [MemberData(nameof(ArraySizesData))] + public void FromCompandedScaledVector4(int count) + { + void sourceAction(ref Vector4 v) + { + SRgbCompanding.Expand(ref v); + } + + void expectedAction(ref Vector4 v) + { + SRgbCompanding.Compress(ref v); + } + + Vector4[] source = CreateVector4TestData(count, (ref Vector4 v) => sourceAction(ref v)); + TPixel[] expected = CreateScaledExpectedPixelData(source, (ref Vector4 v) => expectedAction(ref v)); + + TestOperation( + source, + expected, + (s, d) => Operations.FromVector4(this.Configuration, s, d.GetSpan(), PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Scale) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void FromPremultipliedVector4(int count) + { + void sourceAction(ref Vector4 v) + { + Vector4Utils.Premultiply(ref v); + } + + void expectedAction(ref Vector4 v) + { + Vector4Utils.UnPremultiply(ref v); + } + + Vector4[] source = CreateVector4TestData(count, (ref Vector4 v) => sourceAction(ref v)); + TPixel[] expected = CreateExpectedPixelData(source, (ref Vector4 v) => expectedAction(ref v)); + + TestOperation( + source, + expected, + (s, d) => Operations.FromVector4(this.Configuration, s, d.GetSpan(), PixelConversionModifiers.Premultiply) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void FromPremultipliedScaledVector4(int count) + { + void sourceAction(ref Vector4 v) + { + Vector4Utils.Premultiply(ref v); + } + + void expectedAction(ref Vector4 v) + { + Vector4Utils.UnPremultiply(ref v); + } + + Vector4[] source = CreateVector4TestData(count, (ref Vector4 v) => sourceAction(ref v)); + TPixel[] expected = CreateScaledExpectedPixelData(source, (ref Vector4 v) => expectedAction(ref v)); + + TestOperation( + source, + expected, + (s, d) => Operations.FromVector4( + this.Configuration, + s, + d.GetSpan(), + PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void FromCompandedPremultipliedScaledVector4(int count) + { + void sourceAction(ref Vector4 v) + { + SRgbCompanding.Expand(ref v); + Vector4Utils.Premultiply(ref v); + } + + void expectedAction(ref Vector4 v) + { + Vector4Utils.UnPremultiply(ref v); + SRgbCompanding.Compress(ref v); + } + + Vector4[] source = CreateVector4TestData(count, (ref Vector4 v) => sourceAction(ref v)); + TPixel[] expected = CreateScaledExpectedPixelData(source, (ref Vector4 v) => expectedAction(ref v)); + + TestOperation( + source, + expected, + (s, d) => Operations.FromVector4( + this.Configuration, + s, + d.GetSpan(), + PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Premultiply) + ); + } + [Theory] [MemberData(nameof(ArraySizesData))] public void ToVector4(int count) @@ -148,6 +262,115 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations ); } + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToCompandedScaledVector4(int count) + { + void sourceAction(ref Vector4 v) + { + SRgbCompanding.Compress(ref v); + } + + void expectedAction(ref Vector4 v) + { + SRgbCompanding.Expand(ref v); + } + + TPixel[] source = CreateScaledPixelTestData(count, (ref Vector4 v) => sourceAction(ref v)); + Vector4[] expected = CreateExpectedScaledVector4Data(source, (ref Vector4 v) => expectedAction(ref v)); + + TestOperation( + source, + expected, + (s, d) => Operations.ToVector4( + this.Configuration, + s, + d.GetSpan(), + PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Scale) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToPremultipliedVector4(int count) + { + void sourceAction(ref Vector4 v) + { + Vector4Utils.UnPremultiply(ref v); + } + + void expectedAction(ref Vector4 v) + { + Vector4Utils.Premultiply(ref v); + } + + TPixel[] source = CreatePixelTestData(count, (ref Vector4 v) => sourceAction(ref v)); + Vector4[] expected = CreateExpectedVector4Data(source, (ref Vector4 v) => expectedAction(ref v)); + + TestOperation( + source, + expected, + (s, d) => Operations.ToVector4(this.Configuration, s, d.GetSpan(), PixelConversionModifiers.Premultiply) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToPremultipliedScaledVector4(int count) + { + void sourceAction(ref Vector4 v) + { + Vector4Utils.UnPremultiply(ref v); + } + + void expectedAction(ref Vector4 v) + { + Vector4Utils.Premultiply(ref v); + } + + TPixel[] source = CreateScaledPixelTestData(count, (ref Vector4 v) => sourceAction(ref v)); + Vector4[] expected = CreateExpectedScaledVector4Data(source, (ref Vector4 v) => expectedAction(ref v)); + + TestOperation( + source, + expected, + (s, d) => Operations.ToVector4( + this.Configuration, + s, + d.GetSpan(), + PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale)); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToCompandedPremultipliedScaledVector4(int count) + { + void sourceAction(ref Vector4 v) + { + Vector4Utils.UnPremultiply(ref v); + SRgbCompanding.Compress(ref v); + } + + void expectedAction(ref Vector4 v) + { + SRgbCompanding.Expand(ref v); + Vector4Utils.Premultiply(ref v); + } + + TPixel[] source = CreateScaledPixelTestData(count, (ref Vector4 v) => sourceAction(ref v)); + Vector4[] expected = CreateExpectedScaledVector4Data(source, (ref Vector4 v) => expectedAction(ref v)); + + TestOperation( + source, + expected, + (s, d) => Operations.ToVector4( + this.Configuration, + s, + d.GetSpan(), + PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale) + ); + } + [Theory] [MemberData(nameof(ArraySizesData))] public void FromArgb32Bytes(int count) @@ -477,25 +700,37 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations ); } - internal static Vector4[] CreateExpectedVector4Data(TPixel[] source) + public delegate void RefAction(ref T1 arg1); + + internal static Vector4[] CreateExpectedVector4Data(TPixel[] source, RefAction vectorModifier = null) { var expected = new Vector4[source.Length]; for (int i = 0; i < expected.Length; i++) { - expected[i] = source[i].ToVector4(); + var v = source[i].ToVector4(); + + vectorModifier?.Invoke(ref v); + + expected[i] = v; } + return expected; } - internal static Vector4[] CreateExpectedScaledVector4Data(TPixel[] source) + internal static Vector4[] CreateExpectedScaledVector4Data(TPixel[] source, RefAction vectorModifier = null) { var expected = new Vector4[source.Length]; for (int i = 0; i < expected.Length; i++) { - expected[i] = source[i].ToScaledVector4(); + Vector4 v = source[i].ToScaledVector4(); + + vectorModifier?.Invoke(ref v); + + expected[i] = v; } + return expected; } @@ -513,19 +748,22 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations } } - internal static Vector4[] CreateVector4TestData(int length) + internal static Vector4[] CreateVector4TestData(int length, RefAction vectorModifier = null) { var result = new Vector4[length]; var rnd = new Random(42); // Deterministic random values for (int i = 0; i < result.Length; i++) { - result[i] = GetVector(rnd); + Vector4 v = GetVector(rnd); + vectorModifier?.Invoke(ref v); + + result[i] = v; } return result; } - internal static TPixel[] CreatePixelTestData(int length) + internal static TPixel[] CreatePixelTestData(int length, RefAction vectorModifier = null) { var result = new TPixel[length]; @@ -534,13 +772,16 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations for (int i = 0; i < result.Length; i++) { Vector4 v = GetVector(rnd); + + vectorModifier?.Invoke(ref v); + result[i].FromVector4(v); } return result; } - internal static TPixel[] CreateScaledPixelTestData(int length) + internal static TPixel[] CreateScaledPixelTestData(int length, RefAction vectorModifier = null) { var result = new TPixel[length]; @@ -549,6 +790,9 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations for (int i = 0; i < result.Length; i++) { Vector4 v = GetVector(rnd); + + vectorModifier?.Invoke(ref v); + result[i].FromScaledVector4(v); } From 1a922f6e14b358ec5d8345117538903581ed6124 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 1 Apr 2019 00:56:11 +0200 Subject: [PATCH 036/223] all pixel types implemented except RgbaVector --- .../Argb32.PixelOperations.Generated.cs | 4 +- .../Bgr24.PixelOperations.Generated.cs | 4 +- .../Bgra32.PixelOperations.Generated.cs | 4 +- .../Rgb24.PixelOperations.Generated.cs | 4 +- .../Generated/_Common.ttinclude | 4 +- .../Rgba32.PixelOperations.cs | 6 +- .../RgbaVector.PixelOperations.cs | 6 ++ .../PixelFormats/PixelOperations{TPixel}.cs | 20 +---- .../Utils/Vector4Converters.Default.cs | 74 +++++++++++++++++-- .../Utils/Vector4Converters.RgbaCompatible.cs | 46 ++++-------- .../PixelFormats/Utils/Vector4Converters.cs | 48 ++++++++++++ .../PixelOperations/PixelOperationsTests.cs | 8 +- 12 files changed, 158 insertions(+), 70 deletions(-) create mode 100644 src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs index e832bc97f..c49f3f834 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs @@ -44,13 +44,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs index f1885c71b..a9eca8994 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs @@ -44,13 +44,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs index 2409f6784..73eddc235 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs @@ -44,13 +44,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index ddf9813ab..1648f5341 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -44,13 +44,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude index 0ff5b8605..6286eaf72 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude @@ -113,13 +113,13 @@ using System.Runtime.InteropServices; /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } <#+ } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs index 7e8bb7f29..aa9b82be7 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs @@ -4,6 +4,8 @@ using System; using System.Numerics; using System.Runtime.InteropServices; + +using SixLabors.ImageSharp.PixelFormats.Utils; using SixLabors.Memory; namespace SixLabors.ImageSharp.PixelFormats @@ -28,10 +30,10 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); destVectors = destVectors.Slice(0, sourcePixels.Length); - SimdUtils.BulkConvertByteToNormalizedFloat( MemoryMarshal.Cast(sourcePixels), MemoryMarshal.Cast(destVectors)); + Vector4Converters.ApplyForwardConversionModifiers(destVectors, modifiers); } /// @@ -44,7 +46,7 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); destPixels = destPixels.Slice(0, sourceVectors.Length); - + Vector4Converters.ApplyBackwardConversionModifiers(sourceVectors, modifiers); SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows( MemoryMarshal.Cast(sourceVectors), MemoryMarshal.Cast(destPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs index 777d0da6d..3c4d951ee 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs @@ -5,6 +5,8 @@ using System; using System.Numerics; using System.Runtime.InteropServices; +using SixLabors.ImageSharp.PixelFormats.Utils; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -26,6 +28,8 @@ namespace SixLabors.ImageSharp.PixelFormats { Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); + Vector4Converters.ApplyBackwardConversionModifiers(sourceVectors, modifiers); + // TODO: Repeating previous override behavior here. Not sure if this is correct! if (modifiers.IsDefined(PixelConversionModifiers.Scale)) { @@ -55,6 +59,8 @@ namespace SixLabors.ImageSharp.PixelFormats { MemoryMarshal.Cast(sourcePixels).CopyTo(destVectors); } + + Vector4Converters.ApplyForwardConversionModifiers(destVectors, modifiers); } } } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index ea5bc876f..53181e7a9 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -37,16 +37,8 @@ namespace SixLabors.ImageSharp.PixelFormats PixelConversionModifiers modifiers) { Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); - if (modifiers.IsDefined(PixelConversionModifiers.Scale)) - { - Utils.Vector4Converters.Default.DangerousFromScaledVector4(sourceVectors, destPixels); - } - else - { - Utils.Vector4Converters.Default.DangerousFromVector4(sourceVectors, destPixels); - } + Utils.Vector4Converters.Default.FromVector4(sourceVectors, destPixels, modifiers); } /// @@ -82,16 +74,8 @@ namespace SixLabors.ImageSharp.PixelFormats PixelConversionModifiers modifiers) { Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - if (modifiers.IsDefined(PixelConversionModifiers.Scale)) - { - Utils.Vector4Converters.Default.DangerousToScaledVector4(sourcePixels, destVectors); - } - else - { - Utils.Vector4Converters.Default.DangerousToVector4(sourcePixels, destVectors); - } + Utils.Vector4Converters.Default.ToVector4(sourcePixels, destVectors, modifiers); } /// diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs index e784e3b5a..4c4e60276 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs @@ -6,6 +6,8 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using SixLabors.ImageSharp.ColorSpaces.Companding; + namespace SixLabors.ImageSharp.PixelFormats.Utils { /// @@ -15,13 +17,75 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils { /// /// Provides default implementations for batched to/from conversion. - /// WARNING: The methods are operating without bounds checking and input validation! + /// WARNING: The methods prefixed with "Unsafe" are operating without bounds checking and input validation! /// Input validation is the responsibility of the caller! /// public static class Default { [MethodImpl(InliningOptions.ShortMethod)] - internal static void DangerousFromVector4( + public static void FromVector4( + Span sourceVectors, + Span destPixels, + PixelConversionModifiers modifiers) + where TPixel : struct, IPixel + { + Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels)); + + UnsafeFromVector4(sourceVectors, destPixels, modifiers); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToVector4( + ReadOnlySpan sourcePixels, + Span destVectors, + PixelConversionModifiers modifiers) + where TPixel : struct, IPixel + { + Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); + + UnsafeToVector4(sourcePixels, destVectors, modifiers); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public static void UnsafeFromVector4( + Span sourceVectors, + Span destPixels, + PixelConversionModifiers modifiers) + where TPixel : struct, IPixel + { + ApplyBackwardConversionModifiers(sourceVectors, modifiers); + + if (modifiers.IsDefined(PixelConversionModifiers.Scale)) + { + UnsafeFromScaledVector4Core(sourceVectors, destPixels); + } + else + { + UnsafeFromVector4Core(sourceVectors, destPixels); + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + public static void UnsafeToVector4( + ReadOnlySpan sourcePixels, + Span destVectors, + PixelConversionModifiers modifiers) + where TPixel : struct, IPixel + { + if (modifiers.IsDefined(PixelConversionModifiers.Scale)) + { + UnsafeToScaledVector4Core(sourcePixels, destVectors); + } + else + { + UnsafeToVector4Core(sourcePixels, destVectors); + } + + ApplyForwardConversionModifiers(destVectors, modifiers); + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void UnsafeFromVector4Core( ReadOnlySpan sourceVectors, Span destPixels) where TPixel : struct, IPixel @@ -38,7 +102,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } [MethodImpl(InliningOptions.ShortMethod)] - internal static void DangerousToVector4( + private static void UnsafeToVector4Core( ReadOnlySpan sourcePixels, Span destVectors) where TPixel : struct, IPixel @@ -55,7 +119,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } [MethodImpl(InliningOptions.ShortMethod)] - internal static void DangerousFromScaledVector4( + private static void UnsafeFromScaledVector4Core( ReadOnlySpan sourceVectors, Span destinationColors) where TPixel : struct, IPixel @@ -72,7 +136,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } [MethodImpl(InliningOptions.ShortMethod)] - internal static void DangerousToScaledVector4( + private static void UnsafeToScaledVector4Core( ReadOnlySpan sourceColors, Span destinationVectors) where TPixel : struct, IPixel diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs index 006ebe828..efe4dc69a 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs @@ -7,6 +7,8 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using SixLabors.ImageSharp.ColorSpaces.Companding; + namespace SixLabors.ImageSharp.PixelFormats.Utils { /// @@ -41,7 +43,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils PixelOperations pixelOperations, ReadOnlySpan sourcePixels, Span destVectors, - bool scaled) + PixelConversionModifiers modifiers) where TPixel : struct, IPixel { Guard.NotNull(configuration, nameof(configuration)); @@ -52,7 +54,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils // Not worth for small buffers: if (count < Vector4ConversionThreshold) { - ToVector4Fallback(sourcePixels, destVectors, scaled); + Default.UnsafeToVector4(sourcePixels, destVectors, modifiers); return; } @@ -70,6 +72,9 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils MemoryMarshal.Cast(destVectors.Slice(0, countWithoutLastItem))); destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4(); + + // TODO: Investigate optimized 1-pass approach! + ApplyForwardConversionModifiers(destVectors, modifiers); } /// @@ -83,9 +88,9 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils internal static void FromVector4( Configuration configuration, PixelOperations pixelOperations, - ReadOnlySpan sourceVectors, + Span sourceVectors, Span destPixels, - bool scaled) + PixelConversionModifiers modifiers) where TPixel : struct, IPixel { Guard.NotNull(configuration, nameof(configuration)); @@ -96,11 +101,14 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils // Not worth for small buffers: if (count < Vector4ConversionThreshold) { - FromVector4Fallback(sourceVectors, destPixels, scaled); + Default.UnsafeFromVector4(sourceVectors, destPixels, modifiers); return; } + // TODO: Investigate optimized 1-pass approach! + ApplyBackwardConversionModifiers(sourceVectors, modifiers); + // For the opposite direction it's not easy to implement the trick used in RunRgba32CompatibleToVector4Conversion, // so let's allocate a temporary buffer as usually: using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count)) @@ -115,34 +123,6 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } } - [MethodImpl(InliningOptions.ColdPath)] - private static void ToVector4Fallback(ReadOnlySpan sourcePixels, Span destVectors, bool scaled) - where TPixel : struct, IPixel - { - if (scaled) - { - Default.DangerousToScaledVector4(sourcePixels, destVectors); - } - else - { - Default.DangerousToVector4(sourcePixels, destVectors); - } - } - - [MethodImpl(InliningOptions.ColdPath)] - private static void FromVector4Fallback(ReadOnlySpan sourceVectors, Span destPixels, bool scaled) - where TPixel : struct, IPixel - { - if (scaled) - { - Default.DangerousFromScaledVector4(sourceVectors, destPixels); - } - else - { - Default.DangerousFromVector4(sourceVectors, destPixels); - } - } - private static int CalculateVector4ConversionThreshold() { if (!Vector.IsHardwareAccelerated) diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs new file mode 100644 index 000000000..447869a7d --- /dev/null +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs @@ -0,0 +1,48 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + +using SixLabors.ImageSharp.ColorSpaces.Companding; + +namespace SixLabors.ImageSharp.PixelFormats.Utils +{ + internal static partial class Vector4Converters + { + /// + /// Apply modifiers used requested by ToVector4() conversion. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ApplyForwardConversionModifiers(Span vectors, PixelConversionModifiers modifiers) + { + if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand)) + { + SRgbCompanding.Expand(vectors); + } + + if (modifiers.IsDefined(PixelConversionModifiers.Premultiply)) + { + Vector4Utils.Premultiply(vectors); + } + } + + /// + /// Apply modifiers used requested by FromVector4() conversion. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ApplyBackwardConversionModifiers(Span vectors, PixelConversionModifiers modifiers) + { + if (modifiers.IsDefined(PixelConversionModifiers.Premultiply)) + { + Vector4Utils.UnPremultiply(vectors); + } + + if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand)) + { + SRgbCompanding.Compress(vectors); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index 9433e19c9..f51c79034 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -148,7 +148,11 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4(this.Configuration, s, d.GetSpan(), PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Scale) + (s, d) => Operations.FromVector4( + this.Configuration, + s, + d.GetSpan(), + PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Scale) ); } @@ -230,7 +234,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations this.Configuration, s, d.GetSpan(), - PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Premultiply) + PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale) ); } From d1dd90c5cc6adc1a96915f68452aa344c4726bac Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 1 Apr 2019 01:00:34 +0200 Subject: [PATCH 037/223] fix RgbaVector --- .../RgbaVector.PixelOperations.cs | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs index 3c4d951ee..2d52f98cb 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs @@ -29,16 +29,7 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors)); Vector4Converters.ApplyBackwardConversionModifiers(sourceVectors, modifiers); - - // TODO: Repeating previous override behavior here. Not sure if this is correct! - if (modifiers.IsDefined(PixelConversionModifiers.Scale)) - { - MemoryMarshal.Cast(sourceVectors).CopyTo(destinationColors); - } - else - { - base.FromVector4(configuration, sourceVectors, destinationColors, modifiers); - } + MemoryMarshal.Cast(sourceVectors).CopyTo(destinationColors); } /// @@ -50,16 +41,7 @@ namespace SixLabors.ImageSharp.PixelFormats { Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors)); - // TODO: Repeating previous override behavior here. Not sure if this is correct! - if (modifiers.IsDefined(PixelConversionModifiers.Scale)) - { - base.ToVector4(configuration, sourcePixels, destVectors, modifiers); - } - else - { - MemoryMarshal.Cast(sourcePixels).CopyTo(destVectors); - } - + MemoryMarshal.Cast(sourcePixels).CopyTo(destVectors); Vector4Converters.ApplyForwardConversionModifiers(destVectors, modifiers); } } From 70c4e117f1743488dba5b76718a51487a2df12b3 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 1 Apr 2019 01:05:59 +0200 Subject: [PATCH 038/223] Inlining temporary compatibility methods (FromScaledVector4, ToScaledVector4) --- .../PixelFormats/PixelBlender{TPixel}.cs | 36 +++++++------------ .../PixelFormats/PixelOperations{TPixel}.cs | 15 -------- .../Utils/Vector4Converters.RgbaCompatible.cs | 8 +---- .../Dithering/PaletteDitherProcessorBase.cs | 2 +- .../FrameQuantizerBase{TPixel}.cs | 2 +- .../PixelOperations/PixelOperationsTests.cs | 14 +++++--- .../TestUtilities/TestImageExtensions.cs | 4 +-- 7 files changed, 27 insertions(+), 54 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs index 5c8e506ae..e81498463 100644 --- a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs @@ -112,21 +112,15 @@ namespace SixLabors.ImageSharp.PixelFormats Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); - PixelOperations.Instance.ToScaledVector4( - configuration, - background.Slice(0, background.Length), - backgroundSpan); - PixelOperations.Instance.ToScaledVector4( - configuration, - source.Slice(0, background.Length), - sourceSpan); + ReadOnlySpan sourcePixels = background.Slice(0, background.Length); + PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); + ReadOnlySpan sourcePixels1 = source.Slice(0, background.Length); + PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); - PixelOperations.Instance.FromScaledVector4( - configuration, - destinationSpan.Slice(0, background.Length), - destination); + Span sourceVectors = destinationSpan.Slice(0, background.Length); + PixelOperations.Instance.FromVector4(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); } } @@ -161,21 +155,15 @@ namespace SixLabors.ImageSharp.PixelFormats Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); - PixelOperations.Instance.ToScaledVector4( - configuration, - background.Slice(0, background.Length), - backgroundSpan); - PixelOperations.Instance.ToScaledVector4( - configuration, - source.Slice(0, background.Length), - sourceSpan); + ReadOnlySpan sourcePixels = background.Slice(0, background.Length); + PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale); + ReadOnlySpan sourcePixels1 = source.Slice(0, background.Length); + PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale); this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); - PixelOperations.Instance.FromScaledVector4( - configuration, - destinationSpan.Slice(0, background.Length), - destination); + Span sourceVectors = destinationSpan.Slice(0, background.Length); + PixelOperations.Instance.FromVector4(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); } } } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 53181e7a9..6dae22c5a 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -41,15 +41,6 @@ namespace SixLabors.ImageSharp.PixelFormats Utils.Vector4Converters.Default.FromVector4(sourceVectors, destPixels, modifiers); } - /// - /// TODO: For compatibility, should be inlined! - /// - internal void FromScaledVector4( - Configuration configuration, - Span sourceVectors, - Span destPixels) => - this.FromVector4(configuration, sourceVectors, destPixels, PixelConversionModifiers.Scale); - /// /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'. /// TODO: Rename to DestructiveFromVector4() + add explain behavior @@ -90,12 +81,6 @@ namespace SixLabors.ImageSharp.PixelFormats Span destVectors) => this.ToVector4(configuration, sourcePixels, destVectors, PixelConversionModifiers.None); - /// - /// TODO: For compatibility, should be inlined! - /// - internal void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors) => - this.ToVector4(configuration, sourcePixels, destVectors, PixelConversionModifiers.Scale); - /// /// Converts 'sourceColors.Length' pixels from 'sourceColors' into 'destinationColors'. /// diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs index efe4dc69a..5188a89a3 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs @@ -32,10 +32,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils /// /// Provides an efficient default implementation for - /// and - /// which is applicable for -compatible pixel types where - /// returns the same scaled result as . - /// The method is works by internally converting to a therefore it's not applicable for that type! + /// The method works by internally converting to a therefore it's not applicable for that type! /// [MethodImpl(InliningOptions.ShortMethod)] internal static void ToVector4( @@ -79,9 +76,6 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils /// /// Provides an efficient default implementation for - /// and - /// which is applicable for -compatible pixel types where - /// returns the same scaled result as . /// The method is works by internally converting to a therefore it's not applicable for that type! /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs index 43f6c8a45..6313b74c9 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs @@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering if (this.paletteVector is null) { this.paletteVector = new Vector4[this.Palette.Length]; - PixelOperations.Instance.ToScaledVector4(configuration, this.Palette, this.paletteVector); + PixelOperations.Instance.ToVector4(configuration, (ReadOnlySpan)this.Palette, (Span)this.paletteVector, PixelConversionModifiers.Scale); } } } diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs index 3b9b046a0..a70cfb660 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization // Collect the palette. Required before the second pass runs. TPixel[] palette = this.GetPalette(); this.paletteVector = new Vector4[palette.Length]; - PixelOperations.Instance.ToScaledVector4(image.Configuration, palette, this.paletteVector); + PixelOperations.Instance.ToVector4(image.Configuration, (ReadOnlySpan)palette, (Span)this.paletteVector, PixelConversionModifiers.Scale); var quantizedFrame = new QuantizedFrame(image.MemoryAllocator, width, height, palette); if (this.Dither) diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index f51c79034..b9d3fcff5 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -124,8 +124,11 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromScaledVector4(this.Configuration, s, d.GetSpan()) - ); + (s, d) => + { + Span destPixels = d.GetSpan(); + Operations.FromVector4(this.Configuration, (Span)s, destPixels, PixelConversionModifiers.Scale); + }); } [Theory] @@ -262,8 +265,11 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToScaledVector4(this.Configuration, s, d.GetSpan()) - ); + (s, d) => + { + Span destVectors = d.GetSpan(); + Operations.ToVector4(this.Configuration, (ReadOnlySpan)s, destVectors, PixelConversionModifiers.Scale); + }); } [Theory] diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 29d39596b..ad31319bb 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Tests { Span pixelSpan = frame.GetPixelSpan(); - PixelOperations.Instance.ToScaledVector4(configuration, pixelSpan, tempSpan); + PixelOperations.Instance.ToVector4(configuration, pixelSpan, tempSpan, PixelConversionModifiers.Scale); for (int i = 0; i < tempSpan.Length; i++) { @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Tests v.W = 1F; } - PixelOperations.Instance.FromScaledVector4(configuration, tempSpan, pixelSpan); + PixelOperations.Instance.FromVector4(configuration, tempSpan, pixelSpan, PixelConversionModifiers.Scale); } } }); From 37563cca01699160d962d84e1e46520d8491e55d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 1 Apr 2019 01:42:17 +0200 Subject: [PATCH 039/223] Optimization: omit premultiplication for Bgr24 and Rgb24 --- .../PixelFormats/PixelConversionModifiers.cs | 24 +++++++++++++ .../Bgr24.PixelOperations.Generated.cs | 4 +-- .../Rgb24.PixelOperations.Generated.cs | 4 +-- .../Generated/_Common.ttinclude | 16 ++++++--- ...xelOperationsTests.Bgr24OperationsTests.cs | 1 + ...xelOperationsTests.Rgb24OperationsTests.cs | 1 + .../PixelOperations/PixelOperationsTests.cs | 34 +++++++++++++++---- 7 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs b/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs index 536a23061..d66dbb57a 100644 --- a/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs +++ b/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs @@ -3,14 +3,38 @@ using System; +using SixLabors.ImageSharp.ColorSpaces.Companding; + namespace SixLabors.ImageSharp.PixelFormats { + /// + /// Flags responsible to select additional operations which could be effitiently applied in + /// + /// or + /// + /// knowing the pixel type. + /// [Flags] internal enum PixelConversionModifiers { + /// + /// No special operation is selected + /// None = 0, + + /// + /// Select instead the standard (non scaled) variants. + /// Scale = 1 << 0, + + /// + /// Enable alpha premultiplication / unpremultiplication + /// Premultiply = 1 << 1, + + /// + /// Enable SRGB companding (defined in ). + /// SRgbCompand = 1 << 2, } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs index a9eca8994..92925898b 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs @@ -44,13 +44,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply)); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index 1648f5341..6de8c92bc 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -44,13 +44,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply)); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude index 6286eaf72..584615532 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude @@ -22,6 +22,7 @@ using System.Runtime.InteropServices; // Types with Rgba32-combatible to/from Vector4 conversion static readonly string[] Rgba32CompatibleTypes = { "Argb32", "Bgra32", "Rgb24", "Bgr24" }; + void GenerateDefaultSelfConversionMethods(string pixelType) { #> @@ -107,19 +108,24 @@ using System.Runtime.InteropServices; <#+ } - void GenerateRgba32CompatibleVector4ConversionMethods(string pixelType) + void GenerateRgba32CompatibleVector4ConversionMethods(string pixelType, bool hasAlpha) { + string removeTheseModifiers = "PixelConversionModifiers.Scale"; + if (!hasAlpha) + { + removeTheseModifiers += " | PixelConversionModifiers.Premultiply"; + } #> /// internal override void FromVector4(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); + Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(<#=removeTheseModifiers#>)); } /// internal override void ToVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors, PixelConversionModifiers modifiers) { - Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); + Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(<#=removeTheseModifiers#>)); } <#+ } @@ -130,7 +136,7 @@ using System.Runtime.InteropServices; if (Rgba32CompatibleTypes.Contains(pixelType)) { - GenerateRgba32CompatibleVector4ConversionMethods(pixelType); + GenerateRgba32CompatibleVector4ConversionMethods(pixelType, pixelType.EndsWith("32")); } var matching32BitTypes = Optimized32BitTypes.Contains(pixelType) ? @@ -151,4 +157,4 @@ using System.Runtime.InteropServices; GenerateDefaultConvertToMethod(pixelType, destPixelType); } } -#> \ No newline at end of file +#> diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs index 323d3914c..afcec7938 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs @@ -15,6 +15,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations public Bgr24OperationsTests(ITestOutputHelper output) : base(output) { + this.HasAlpha = false; } [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs index fa51c2278..1c7d312d3 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs @@ -14,6 +14,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations public Rgb24OperationsTests(ITestOutputHelper output) : base(output) { + this.HasAlpha = false; } [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index b9d3fcff5..659da47a7 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -33,6 +33,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations null; #endif + protected bool HasAlpha { get; set; } = true; + protected PixelOperationsTests(ITestOutputHelper output) : base(output) { @@ -165,12 +167,18 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { void sourceAction(ref Vector4 v) { - Vector4Utils.Premultiply(ref v); + if (this.HasAlpha) + { + Vector4Utils.Premultiply(ref v); + } } void expectedAction(ref Vector4 v) { - Vector4Utils.UnPremultiply(ref v); + if (this.HasAlpha) + { + Vector4Utils.UnPremultiply(ref v); + } } Vector4[] source = CreateVector4TestData(count, (ref Vector4 v) => sourceAction(ref v)); @@ -189,12 +197,18 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { void sourceAction(ref Vector4 v) { - Vector4Utils.Premultiply(ref v); + if (this.HasAlpha) + { + Vector4Utils.Premultiply(ref v); + } } void expectedAction(ref Vector4 v) { - Vector4Utils.UnPremultiply(ref v); + if (this.HasAlpha) + { + Vector4Utils.UnPremultiply(ref v); + } } Vector4[] source = CreateVector4TestData(count, (ref Vector4 v) => sourceAction(ref v)); @@ -218,12 +232,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations void sourceAction(ref Vector4 v) { SRgbCompanding.Expand(ref v); - Vector4Utils.Premultiply(ref v); + + if (this.HasAlpha) + { + Vector4Utils.Premultiply(ref v); + } } void expectedAction(ref Vector4 v) { - Vector4Utils.UnPremultiply(ref v); + if (this.HasAlpha) + { + Vector4Utils.UnPremultiply(ref v); + } + SRgbCompanding.Compress(ref v); } From d2fddce2153124e450012ff30d4f1f61a6891743 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 1 Apr 2019 01:45:39 +0200 Subject: [PATCH 040/223] extend Resize benchmarks --- .../ImageSharp.Benchmarks/Samplers/Resize.cs | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs index 148b25328..239e2fc6f 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs @@ -14,11 +14,12 @@ using SixLabors.ImageSharp.Processing; namespace SixLabors.ImageSharp.Benchmarks { [Config(typeof(Config.ShortClr))] - public abstract class ResizeBenchmarkBase + public abstract class ResizeBenchmarkBase + where TPixel : struct, IPixel { protected readonly Configuration Configuration = new Configuration(new JpegConfigurationModule()); - private Image sourceImage; + private Image sourceImage; private Bitmap sourceBitmap; @@ -31,7 +32,7 @@ namespace SixLabors.ImageSharp.Benchmarks [GlobalSetup] public void Setup() { - this.sourceImage = new Image(this.Configuration, this.SourceSize, this.SourceSize); + this.sourceImage = new Image(this.Configuration, this.SourceSize, this.SourceSize); this.sourceBitmap = new Bitmap(this.SourceSize, this.SourceSize); } @@ -65,26 +66,29 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp, MaxDegreeOfParallelism = 1")] public int ImageSharp_P1() => this.RunImageSharpResize(1); - [Benchmark(Description = "ImageSharp, MaxDegreeOfParallelism = 4")] - public int ImageSharp_P4() => this.RunImageSharpResize(4); + // Parallel cases have been disabled for fast benchmark execution. + // Uncomment, if you are interested in parallel speedup - [Benchmark(Description = "ImageSharp, MaxDegreeOfParallelism = 8")] - public int ImageSharp_P8() => this.RunImageSharpResize(8); + //[Benchmark(Description = "ImageSharp, MaxDegreeOfParallelism = 4")] + //public int ImageSharp_P4() => this.RunImageSharpResize(4); + + //[Benchmark(Description = "ImageSharp, MaxDegreeOfParallelism = 8")] + //public int ImageSharp_P8() => this.RunImageSharpResize(8); protected int RunImageSharpResize(int maxDegreeOfParallelism) { this.Configuration.MaxDegreeOfParallelism = maxDegreeOfParallelism; - using (Image clone = this.sourceImage.Clone(this.ExecuteResizeOperation)) + using (Image clone = this.sourceImage.Clone(this.ExecuteResizeOperation)) { return clone.Width; } } - protected abstract void ExecuteResizeOperation(IImageProcessingContext ctx); + protected abstract void ExecuteResizeOperation(IImageProcessingContext ctx); } - - public class Resize_Bicubic : ResizeBenchmarkBase + + public class Resize_Bicubic_Rgba32 : ResizeBenchmarkBase { protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { @@ -115,7 +119,15 @@ namespace SixLabors.ImageSharp.Benchmarks } - public class Resize_BicubicCompand : ResizeBenchmarkBase + public class Resize_Bicubic_Bgra32 : ResizeBenchmarkBase + { + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + { + ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); + } + } + + public class Resize_BicubicCompand_Rgba32 : ResizeBenchmarkBase { protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { @@ -144,4 +156,13 @@ namespace SixLabors.ImageSharp.Benchmarks // 'ImageSharp, MaxDegreeOfParallelism = 4' | Core | 3032 | 400 | 36.21 ms | 53.802 ms | 3.0399 ms | 0.36 | 0.03 | 25300 B | // 'ImageSharp, MaxDegreeOfParallelism = 8' | Core | 3032 | 400 | 26.52 ms | 2.173 ms | 0.1228 ms | 0.27 | 0.00 | 25589 B | } -} + + public class Resize_Bicubic_Rgb24 : ResizeBenchmarkBase + { + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + { + ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); + } + } + +} \ No newline at end of file From acb1dbc319ba4190e3e253f6126b082eb82a21a5 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 1 Apr 2019 01:56:14 +0200 Subject: [PATCH 041/223] update ResizeProcessor --- .../Transforms/Resize/ResizeProcessor.cs | 102 ++++++++---------- tests/Images/External | 2 +- 2 files changed, 48 insertions(+), 56 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 189e21de7..6904122cc 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -9,7 +9,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.ColorSpaces.Companding; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; @@ -216,27 +215,33 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms workingRect, configuration, rows => + { + for (int y = rows.Min; y < rows.Max; y++) { - for (int y = rows.Min; y < rows.Max; y++) + // Y coordinates of source points + Span sourceRow = + source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); + Span targetRow = destination.GetPixelRowSpan(y); + + for (int x = minX; x < maxX; x++) { - // Y coordinates of source points - Span sourceRow = - source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); - Span targetRow = destination.GetPixelRowSpan(y); - - for (int x = minX; x < maxX; x++) - { - // X coordinates of source points - targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; - } + // X coordinates of source points + targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; } - }); + } + }); return; } int sourceHeight = source.Height; + PixelConversionModifiers conversionModifiers = PixelConversionModifiers.Premultiply; + if (this.Compand) + { + conversionModifiers |= PixelConversionModifiers.Scale | PixelConversionModifiers.SRgbCompand; + } + // Interpolate the image using the calculated weights. // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm // First process the columns. Since we are not using multiple threads startY and endY @@ -251,30 +256,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms processColsRect, configuration, (rows, tempRowBuffer) => + { + for (int y = rows.Min; y < rows.Max; y++) { - for (int y = rows.Min; y < rows.Max; y++) - { - Span sourceRow = source.GetPixelRowSpan(y).Slice(sourceX); - Span tempRowSpan = tempRowBuffer.Span.Slice(sourceX); - - PixelOperations.Instance.ToVector4(configuration, sourceRow, tempRowSpan); - Vector4Utils.Premultiply(tempRowSpan); + Span sourceRow = source.GetPixelRowSpan(y).Slice(sourceX); + Span tempRowSpan = tempRowBuffer.Span.Slice(sourceX); - ref Vector4 firstPassBaseRef = ref firstPassPixelsTransposed.Span[y]; + PixelOperations.Instance.ToVector4(configuration, sourceRow, tempRowSpan, conversionModifiers); - if (this.Compand) - { - SRgbCompanding.Expand(tempRowSpan); - } + ref Vector4 firstPassBaseRef = ref firstPassPixelsTransposed.Span[y]; - for (int x = minX; x < maxX; x++) - { - ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - startX); - Unsafe.Add(ref firstPassBaseRef, x * sourceHeight) = - kernel.Convolve(tempRowSpan); - } + for (int x = minX; x < maxX; x++) + { + ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - startX); + Unsafe.Add(ref firstPassBaseRef, x * sourceHeight) = kernel.Convolve(tempRowSpan); } - }); + } + }); var processRowsRect = Rectangle.FromLTRB(0, minY, width, maxY); @@ -283,35 +281,29 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms processRowsRect, configuration, (rows, tempRowBuffer) => - { - Span tempRowSpan = tempRowBuffer.Span; - - for (int y = rows.Min; y < rows.Max; y++) - { - // Ensure offsets are normalized for cropping and padding. - ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); + { + Span tempRowSpan = tempRowBuffer.Span; - ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempRowSpan); + for (int y = rows.Min; y < rows.Max; y++) + { + // Ensure offsets are normalized for cropping and padding. + ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); - for (int x = 0; x < width; x++) - { - Span firstPassColumn = firstPassPixelsTransposed.GetRowSpan(x).Slice(sourceY); + ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempRowSpan); - // Destination color components - Unsafe.Add(ref tempRowBase, x) = kernel.Convolve(firstPassColumn); - } + for (int x = 0; x < width; x++) + { + Span firstPassColumn = firstPassPixelsTransposed.GetRowSpan(x).Slice(sourceY); - Vector4Utils.UnPremultiply(tempRowSpan); + // Destination color components + Unsafe.Add(ref tempRowBase, x) = kernel.Convolve(firstPassColumn); + } - if (this.Compand) - { - SRgbCompanding.Compress(tempRowSpan); - } + Span targetRowSpan = destination.GetPixelRowSpan(y); - Span targetRowSpan = destination.GetPixelRowSpan(y); - PixelOperations.Instance.FromVector4(configuration, tempRowSpan, targetRowSpan); - } - }); + PixelOperations.Instance.FromVector4(configuration, tempRowSpan, targetRowSpan, conversionModifiers); + } + }); } } diff --git a/tests/Images/External b/tests/Images/External index c4098e463..4387e56e8 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit c4098e463ab0e7128ae196b7f963369271df8fd3 +Subproject commit 4387e56e8590ee00607efe29a9babfda041621cb From 575a484e61b054ec883c5106637d02106a5c39ca Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 1 Apr 2019 02:06:44 +0200 Subject: [PATCH 042/223] update benchmark results --- .../ImageSharp.Benchmarks/Samplers/Resize.cs | 124 +++++++++++------- 1 file changed, 79 insertions(+), 45 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs index 239e2fc6f..51f3a5653 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs @@ -95,27 +95,25 @@ namespace SixLabors.ImageSharp.Benchmarks ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); } - // RESULTS (2018 October): + // RESULTS (2019 April): // - // BenchmarkDotNet=v0.10.14, OS=Windows 10.0.17134 + // BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17134.648 (1803/April2018Update/Redstone4) // Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores - // Frequency=2742191 Hz, Resolution=364.6719 ns, Timer=TSC - // .NET Core SDK=2.1.403 - // [Host] : .NET Core 2.1.5 (CoreCLR 4.6.26919.02, CoreFX 4.6.26919.02), 64bit RyuJIT - // Job-IGUFBA : .NET Framework 4.7.1 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3190.0 - // Job-DZFERG : .NET Core 2.1.5 (CoreCLR 4.6.26919.02, CoreFX 4.6.26919.02), 64bit RyuJIT - // - // Method | Runtime | SourceSize | DestSize | Mean | Error | StdDev | Scaled | ScaledSD | Allocated | - // ----------------------------------------- |-------- |----------- |--------- |----------:|----------:|----------:|-------:|---------:|----------:| - // SystemDrawing | Clr | 3032 | 400 | 101.13 ms | 18.659 ms | 1.0542 ms | 1.00 | 0.00 | 0 B | - // 'ImageSharp, MaxDegreeOfParallelism = 1' | Clr | 3032 | 400 | 122.05 ms | 19.622 ms | 1.1087 ms | 1.21 | 0.01 | 21856 B | - // 'ImageSharp, MaxDegreeOfParallelism = 4' | Clr | 3032 | 400 | 41.34 ms | 54.841 ms | 3.0986 ms | 0.41 | 0.03 | 28000 B | - // 'ImageSharp, MaxDegreeOfParallelism = 8' | Clr | 3032 | 400 | 31.68 ms | 12.782 ms | 0.7222 ms | 0.31 | 0.01 | 28256 B | - // | | | | | | | | | | - // SystemDrawing | Core | 3032 | 400 | 100.37 ms | 18.479 ms | 1.0441 ms | 1.00 | 0.00 | 0 B | - // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | 3032 | 400 | 73.03 ms | 10.540 ms | 0.5955 ms | 0.73 | 0.01 | 21368 B | - // 'ImageSharp, MaxDegreeOfParallelism = 4' | Core | 3032 | 400 | 22.59 ms | 4.863 ms | 0.2748 ms | 0.23 | 0.00 | 25220 B | - // 'ImageSharp, MaxDegreeOfParallelism = 8' | Core | 3032 | 400 | 21.10 ms | 23.362 ms | 1.3200 ms | 0.21 | 0.01 | 25539 B | + // Frequency=2742192 Hz, Resolution=364.6718 ns, Timer=TSC + // .NET Core SDK=2.1.602 + // [Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3362.0 + // Core : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // + // IterationCount=3 LaunchCount=1 WarmupCount=3 + // + // Method | Job | Runtime | SourceSize | DestSize | Mean | Error | StdDev | Ratio | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | + // ----------------------------------------- |----- |-------- |----------- |--------- |----------:|----------:|----------:|------:|------------:|------------:|------------:|--------------------:| + // SystemDrawing | Clr | Clr | 3032 | 400 | 118.71 ms | 4.884 ms | 0.2677 ms | 1.00 | - | - | - | 2048 B | + // 'ImageSharp, MaxDegreeOfParallelism = 1' | Clr | Clr | 3032 | 400 | 94.55 ms | 16.160 ms | 0.8858 ms | 0.80 | - | - | - | 16384 B | + // | | | | | | | | | | | | | + // SystemDrawing | Core | Core | 3032 | 400 | 118.38 ms | 2.814 ms | 0.1542 ms | 1.00 | - | - | - | 96 B | + // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032 | 400 | 90.28 ms | 4.679 ms | 0.2565 ms | 0.76 | - | - | - | 15712 B | } @@ -125,44 +123,80 @@ namespace SixLabors.ImageSharp.Benchmarks { ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); } + + // RESULTS (2019 April): + // + // BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17134.648 (1803/April2018Update/Redstone4) + // Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores + // Frequency=2742192 Hz, Resolution=364.6718 ns, Timer=TSC + // .NET Core SDK=2.1.602 + // [Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3362.0 + // Core : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // + // IterationCount=3 LaunchCount=1 WarmupCount=3 + // + // Method | Job | Runtime | SourceSize | DestSize | Mean | Error | StdDev | Ratio | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | + // ----------------------------------------- |----- |-------- |----------- |--------- |----------:|----------:|----------:|------:|------------:|------------:|------------:|--------------------:| + // SystemDrawing | Clr | Clr | 3032 | 400 | 119.01 ms | 18.513 ms | 1.0147 ms | 1.00 | - | - | - | 1638 B | + // 'ImageSharp, MaxDegreeOfParallelism = 1' | Clr | Clr | 3032 | 400 | 104.71 ms | 16.078 ms | 0.8813 ms | 0.88 | - | - | - | 45056 B | + // | | | | | | | | | | | | | + // SystemDrawing | Core | Core | 3032 | 400 | 121.58 ms | 50.084 ms | 2.7453 ms | 1.00 | - | - | - | 96 B | + // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032 | 400 | 96.96 ms | 7.899 ms | 0.4329 ms | 0.80 | - | - | - | 44512 B | } - public class Resize_BicubicCompand_Rgba32 : ResizeBenchmarkBase + public class Resize_Bicubic_Rgb24 : ResizeBenchmarkBase { - protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { - ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic, true); + ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); } - // RESULTS (2018 October): + // RESULTS (2019 April): // - // BenchmarkDotNet=v0.10.14, OS=Windows 10.0.17134 + // BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17134.648 (1803/April2018Update/Redstone4) // Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores - // Frequency=2742191 Hz, Resolution=364.6719 ns, Timer=TSC - // .NET Core SDK=2.1.403 - // [Host] : .NET Core 2.1.5 (CoreCLR 4.6.26919.02, CoreFX 4.6.26919.02), 64bit RyuJIT - // Job-IGUFBA : .NET Framework 4.7.1 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3190.0 - // Job-DZFERG : .NET Core 2.1.5 (CoreCLR 4.6.26919.02, CoreFX 4.6.26919.02), 64bit RyuJIT - // - // Method | Runtime | SourceSize | DestSize | Mean | Error | StdDev | Scaled | ScaledSD | Allocated | - // ----------------------------------------- |-------- |----------- |--------- |----------:|----------:|----------:|-------:|---------:|----------:| - // SystemDrawing | Clr | 3032 | 400 | 100.63 ms | 13.864 ms | 0.7833 ms | 1.00 | 0.00 | 0 B | - // 'ImageSharp, MaxDegreeOfParallelism = 1' | Clr | 3032 | 400 | 156.83 ms | 28.631 ms | 1.6177 ms | 1.56 | 0.02 | 21856 B | - // 'ImageSharp, MaxDegreeOfParallelism = 4' | Clr | 3032 | 400 | 53.43 ms | 38.493 ms | 2.1749 ms | 0.53 | 0.02 | 28512 B | - // 'ImageSharp, MaxDegreeOfParallelism = 8' | Clr | 3032 | 400 | 38.47 ms | 11.969 ms | 0.6763 ms | 0.38 | 0.01 | 28000 B | - // | | | | | | | | | | - // SystemDrawing | Core | 3032 | 400 | 99.87 ms | 23.459 ms | 1.3255 ms | 1.00 | 0.00 | 0 B | - // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | 3032 | 400 | 108.19 ms | 38.562 ms | 2.1788 ms | 1.08 | 0.02 | 21368 B | - // 'ImageSharp, MaxDegreeOfParallelism = 4' | Core | 3032 | 400 | 36.21 ms | 53.802 ms | 3.0399 ms | 0.36 | 0.03 | 25300 B | - // 'ImageSharp, MaxDegreeOfParallelism = 8' | Core | 3032 | 400 | 26.52 ms | 2.173 ms | 0.1228 ms | 0.27 | 0.00 | 25589 B | + // Frequency=2742192 Hz, Resolution=364.6718 ns, Timer=TSC + // .NET Core SDK=2.1.602 + // [Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3362.0 + // Core : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // + // Method | Job | Runtime | SourceSize | DestSize | Mean | Error | StdDev | Ratio | RatioSD | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | + // ----------------------------------------- |----- |-------- |----------- |--------- |----------:|----------:|----------:|------:|--------:|------------:|------------:|------------:|--------------------:| + // SystemDrawing | Clr | Clr | 3032 | 400 | 121.37 ms | 48.580 ms | 2.6628 ms | 1.00 | 0.00 | - | - | - | 2048 B | + // 'ImageSharp, MaxDegreeOfParallelism = 1' | Clr | Clr | 3032 | 400 | 99.36 ms | 11.356 ms | 0.6224 ms | 0.82 | 0.02 | - | - | - | 45056 B | + // | | | | | | | | | | | | | | + // SystemDrawing | Core | Core | 3032 | 400 | 118.06 ms | 15.667 ms | 0.8587 ms | 1.00 | 0.00 | - | - | - | 96 B | + // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032 | 400 | 92.47 ms | 5.683 ms | 0.3115 ms | 0.78 | 0.01 | - | - | - | 44512 B | } - public class Resize_Bicubic_Rgb24 : ResizeBenchmarkBase + + public class Resize_BicubicCompand_Rgba32 : ResizeBenchmarkBase { - protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { - ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); + ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic, true); } - } + // RESULTS (2019 April): + // + // BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17134.648 (1803/April2018Update/Redstone4) + // Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores + // Frequency=2742192 Hz, Resolution=364.6718 ns, Timer=TSC + // .NET Core SDK=2.1.602 + // [Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3362.0 + // Core : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // + // IterationCount=3 LaunchCount=1 WarmupCount=3 + // + // Method | Job | Runtime | SourceSize | DestSize | Mean | Error | StdDev | Ratio | RatioSD | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | + // ----------------------------------------- |----- |-------- |----------- |--------- |---------:|----------:|----------:|------:|--------:|------------:|------------:|------------:|--------------------:| + // SystemDrawing | Clr | Clr | 3032 | 400 | 120.7 ms | 68.985 ms | 3.7813 ms | 1.00 | 0.00 | - | - | - | 1638 B | + // 'ImageSharp, MaxDegreeOfParallelism = 1' | Clr | Clr | 3032 | 400 | 132.2 ms | 15.976 ms | 0.8757 ms | 1.10 | 0.04 | - | - | - | 16384 B | + // | | | | | | | | | | | | | | + // SystemDrawing | Core | Core | 3032 | 400 | 118.3 ms | 6.899 ms | 0.3781 ms | 1.00 | 0.00 | - | - | - | 96 B | + // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032 | 400 | 122.4 ms | 15.069 ms | 0.8260 ms | 1.03 | 0.01 | - | - | - | 15712 B | + } } \ No newline at end of file From 4a0b10080d00c01833d344b0dab709a4f82de39e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 1 Apr 2019 02:14:16 +0200 Subject: [PATCH 043/223] rename FromVector4(...) to FromVector4Destructive(...) --- .../Decoder/JpegImagePostProcessor.cs | 2 +- .../PixelFormats/PixelBlender{TPixel}.cs | 4 ++-- .../PixelFormats/PixelConversionModifiers.cs | 4 ++-- .../Argb32.PixelOperations.Generated.cs | 2 +- .../Bgr24.PixelOperations.Generated.cs | 2 +- .../Bgra32.PixelOperations.Generated.cs | 2 +- .../Rgb24.PixelOperations.Generated.cs | 2 +- .../Rgba32.PixelOperations.cs | 2 +- .../RgbaVector.PixelOperations.cs | 2 +- .../PixelFormats/PixelOperations{TPixel}.cs | 18 +++++++++++++----- .../Utils/Vector4Converters.RgbaCompatible.cs | 2 +- .../Convolution/Convolution2DProcessor.cs | 2 +- .../Convolution/Convolution2PassProcessor.cs | 2 +- .../Convolution/ConvolutionProcessor.cs | 2 +- .../Processors/Filters/FilterProcessor.cs | 2 +- .../Transforms/AffineTransformProcessor.cs | 2 +- .../Transforms/ProjectiveTransformProcessor.cs | 2 +- .../Transforms/Resize/ResizeProcessor.cs | 2 +- .../Color/Bulk/FromVector4.cs | 4 ++-- .../PixelBlenders/PorterDuffBulkVsPixel.cs | 2 +- .../PixelOperations/PixelOperationsTests.cs | 12 ++++++------ .../TestUtilities/TestImageExtensions.cs | 2 +- 22 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs index 438749abf..2c8190884 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs @@ -173,7 +173,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder Span destRow = destination.GetPixelRowSpan(yy); // TODO: Investigate if slicing is actually necessary - PixelOperations.Instance.FromVector4(this.configuration, this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow); + PixelOperations.Instance.FromVector4Destructive(this.configuration, this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow); } } } diff --git a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs index e81498463..d2a6fbf50 100644 --- a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs @@ -120,7 +120,7 @@ namespace SixLabors.ImageSharp.PixelFormats this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); Span sourceVectors = destinationSpan.Slice(0, background.Length); - PixelOperations.Instance.FromVector4(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); + PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); } } @@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount); Span sourceVectors = destinationSpan.Slice(0, background.Length); - PixelOperations.Instance.FromVector4(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); + PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale); } } } diff --git a/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs b/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs index d66dbb57a..5df5dc62b 100644 --- a/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs +++ b/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Flags responsible to select additional operations which could be effitiently applied in /// /// or - /// + /// /// knowing the pixel type. /// [Flags] @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.PixelFormats None = 0, /// - /// Select instead the standard (non scaled) variants. + /// Select and instead the standard (non scaled) variants. /// Scale = 1 << 0, diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs index c49f3f834..4cff1f8c1 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) + internal override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs index 92925898b..225e4b5e0 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) + internal override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply)); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs index 73eddc235..ce049115e 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) + internal override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index 6de8c92bc..02a8869ec 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) + internal override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply)); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs index aa9b82be7..3da5d1855 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs @@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - internal override void FromVector4( + internal override void FromVector4Destructive( Configuration configuration, Span sourceVectors, Span destPixels, diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs index 2d52f98cb..3112126e7 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.PixelFormats internal class PixelOperations : PixelOperations { /// - internal override void FromVector4( + internal override void FromVector4Destructive( Configuration configuration, Span sourceVectors, Span destinationColors, diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 6dae22c5a..d009822e8 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -24,13 +24,17 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'. - /// TODO: Rename to DestructiveFromVector4() + add explain behavior + /// The method is DESTRUCTIVE altering the contents of . /// + /// + /// The destructive behavior is a design choice for performance reasons. + /// In a typical use case the contents of are abandoned after the conversion. + /// /// A to configure internal operations /// The to the source vectors. /// The to the destination colors. /// The to apply during the conversion - internal virtual void FromVector4( + internal virtual void FromVector4Destructive( Configuration configuration, Span sourceVectors, Span destPixels, @@ -43,13 +47,17 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'. - /// TODO: Rename to DestructiveFromVector4() + add explain behavior + /// The method is DESTRUCTIVE altering the contents of . /// + /// + /// The destructive behavior is a design choice for performance reasons. + /// In a typical use case the contents of are abandoned after the conversion. + /// /// A to configure internal operations /// The to the source vectors. /// The to the destination colors. - internal void FromVector4(Configuration configuration, Span sourceVectors, Span destPixels) => - this.FromVector4(configuration, sourceVectors, destPixels, PixelConversionModifiers.None); + internal void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destPixels) => + this.FromVector4Destructive(configuration, sourceVectors, destPixels, PixelConversionModifiers.None); /// /// Bulk version of converting 'sourceColors.Length' pixels into 'destinationVectors'. diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs index 5188a89a3..fe8d7dec3 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } /// - /// Provides an efficient default implementation for + /// Provides an efficient default implementation for /// The method is works by internally converting to a therefore it's not applicable for that type! /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs index bd1419e4b..341a26ae8 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs @@ -82,7 +82,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution DenseMatrixUtils.Convolve2D(in matrixY, in matrixX, source.PixelBuffer, vectorSpan, y, x, maxY, maxX, startX); } - PixelOperations.Instance.FromVector4(configuration, vectorSpan.Slice(0, length), targetRowSpan); + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan.Slice(0, length), targetRowSpan); } }); diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs index 05007c370..9de467328 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs @@ -100,7 +100,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution DenseMatrixUtils.Convolve(in matrix, sourcePixels, vectorSpan, y, x, maxY, maxX, startX); } - PixelOperations.Instance.FromVector4(configuration, vectorSpan.Slice(0, length), targetRowSpan); + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan.Slice(0, length), targetRowSpan); } }); } diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs index 8ef64bdac..7e003cb03 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs @@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution DenseMatrixUtils.Convolve(in matrix, source.PixelBuffer, vectorSpan, y, x, maxY, maxX, startX); } - PixelOperations.Instance.FromVector4(configuration, vectorSpan.Slice(0, length), targetRowSpan); + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan.Slice(0, length), targetRowSpan); } }); diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs index d6a32d889..dbd843341 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs @@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters Vector4Utils.Transform(vectorSpan, ref matrix); - PixelOperations.Instance.FromVector4(configuration, vectorSpan, rowSpan); + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, rowSpan); } }); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs index 5a3b5943b..0f71c732d 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs @@ -129,7 +129,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms kernel.Convolve(point, x, ref ySpanRef, ref xSpanRef, source.PixelBuffer, vectorSpan); } - PixelOperations.Instance.FromVector4(configuration, vectorSpan, targetRowSpan); + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); } }); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs index 0b5627e19..8a5d7563f 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs @@ -128,7 +128,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms kernel.Convolve(point, x, ref ySpanRef, ref xSpanRef, source.PixelBuffer, vectorSpan); } - PixelOperations.Instance.FromVector4(configuration, vectorSpan, targetRowSpan); + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); } }); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 6904122cc..2c186a276 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -301,7 +301,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Span targetRowSpan = destination.GetPixelRowSpan(y); - PixelOperations.Instance.FromVector4(configuration, tempRowSpan, targetRowSpan, conversionModifiers); + PixelOperations.Instance.FromVector4Destructive(configuration, tempRowSpan, targetRowSpan, conversionModifiers); } }); } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs index 2b9573ed7..8b2d08e66 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs @@ -61,13 +61,13 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk [Benchmark] public void PixelOperations_Base() { - new PixelOperations().FromVector4(this.Configuration, this.source.GetSpan(), this.destination.GetSpan()); + new PixelOperations().FromVector4Destructive(this.Configuration, this.source.GetSpan(), this.destination.GetSpan()); } [Benchmark] public void PixelOperations_Specialized() { - PixelOperations.Instance.FromVector4(this.Configuration, this.source.GetSpan(), this.destination.GetSpan()); + PixelOperations.Instance.FromVector4Destructive(this.Configuration, this.source.GetSpan(), this.destination.GetSpan()); } } diff --git a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs index cdd56fa07..ce4e16c44 100644 --- a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs +++ b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Benchmarks destinationSpan[i] = PorterDuffFunctions.NormalSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } - PixelOperations.Instance.FromVector4(this.Configuration, destinationSpan, destination); + PixelOperations.Instance.FromVector4Destructive(this.Configuration, destinationSpan, destination); } } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index 659da47a7..d9ae9131f 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4(this.Configuration, s, d.GetSpan()) + (s, d) => Operations.FromVector4Destructive(this.Configuration, s, d.GetSpan()) ); } @@ -129,7 +129,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations (s, d) => { Span destPixels = d.GetSpan(); - Operations.FromVector4(this.Configuration, (Span)s, destPixels, PixelConversionModifiers.Scale); + Operations.FromVector4Destructive(this.Configuration, (Span)s, destPixels, PixelConversionModifiers.Scale); }); } @@ -153,7 +153,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4( + (s, d) => Operations.FromVector4Destructive( this.Configuration, s, d.GetSpan(), @@ -187,7 +187,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4(this.Configuration, s, d.GetSpan(), PixelConversionModifiers.Premultiply) + (s, d) => Operations.FromVector4Destructive(this.Configuration, s, d.GetSpan(), PixelConversionModifiers.Premultiply) ); } @@ -217,7 +217,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4( + (s, d) => Operations.FromVector4Destructive( this.Configuration, s, d.GetSpan(), @@ -255,7 +255,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4( + (s, d) => Operations.FromVector4Destructive( this.Configuration, s, d.GetSpan(), diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index ad31319bb..6ca3ed6f9 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Tests v.W = 1F; } - PixelOperations.Instance.FromVector4(configuration, tempSpan, pixelSpan, PixelConversionModifiers.Scale); + PixelOperations.Instance.FromVector4Destructive(configuration, tempSpan, pixelSpan, PixelConversionModifiers.Scale); } } }); From 408e19645ff80dfbfbb8200377771b419c7e1ba6 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 1 Apr 2019 02:20:38 +0200 Subject: [PATCH 044/223] pull back the submodule reference with a few revisions --- tests/Images/External | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Images/External b/tests/Images/External index 4387e56e8..9d7198554 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 4387e56e8590ee00607efe29a9babfda041621cb +Subproject commit 9d71985545bb827270ca34af3f78e4c220560ef1 From a86cddb54ffac07060e3908c4ad7f0a9ba247582 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 1 Apr 2019 23:16:04 -0500 Subject: [PATCH 045/223] Nits (#870) * Format conversion models * Format color spaces * Add missing periods * Replace Endianness enum with isBigEndian * Seal DoubleBufferedStreamReader * Remove unused namespaces * Simplify variable names * Remove unused namespace * Format Block8x8F * Use MathF * Simplify exception when an encoder is not found * Format ICC models * Simplify excption messages in ExifValue (reduces IL size) * Add missing periods to documentation. * Format ImageProperty * Format BmpImageFormatDetector * Seal LocalFileSystem * Seal JpegColorConverter implementations * Add missing periods to jpeg documentation * Format ValueSize * Fix stylecop violation * Revert "Simplify excption messages in ExifValue (reduces IL size)" This reverts commit d22f2a679f4d9b1d5c3e41a56d1a7ea8e895f6c7. --- .../Advanced/AdvancedImageExtensions.cs | 6 +- src/ImageSharp/Advanced/IPixelSource.cs | 1 - src/ImageSharp/ColorSpaces/CieLch.cs | 6 +- src/ImageSharp/ColorSpaces/CieXyz.cs | 2 +- src/ImageSharp/ColorSpaces/Cmyk.cs | 2 +- .../ColorSpaces/Companding/SRgbCompanding.cs | 2 +- .../Conversion/ColorSpaceConverter.CieLab.cs | 47 +++++----- .../Conversion/ColorSpaceConverter.CieLch.cs | 48 +++++----- .../ColorSpaceConverter.CieLchuv.cs | 50 +++++----- .../Conversion/ColorSpaceConverter.CieLuv.cs | 54 +++++------ .../Conversion/ColorSpaceConverter.CieXyz.cs | 57 +++++------- .../Conversion/ColorSpaceConverter.Cmyk.cs | 42 ++++----- .../Conversion/ColorSpaceConverter.Hsl.cs | 36 ++++---- .../Conversion/ColorSpaceConverter.Hsv.cs | 2 +- .../ColorSpaceConverter.HunterLab.cs | 68 +++++++------- .../ColorSpaceConverter.LinearRgb.cs | 92 +++++++++---------- .../Conversion/ColorSpaceConverter.YCbCr.cs | 54 +++++------ .../Conversion/VonKriesChromaticAdaptation.cs | 4 +- src/ImageSharp/ColorSpaces/HunterLab.cs | 9 +- src/ImageSharp/ColorSpaces/Illuminants.cs | 6 +- src/ImageSharp/ColorSpaces/Rgb.cs | 8 +- .../ColorSpaces/RgbWorkingSpaces.cs | 3 +- .../Common/Extensions/EnumerableExtensions.cs | 4 +- src/ImageSharp/Common/Tuples/Octet.cs | 2 +- .../Formats/Bmp/BmpImageFormatDetector.cs | 8 +- .../Formats/Gif/IGifDecoderOptions.cs | 2 +- .../Jpeg/Components/Block8x8F.Generated.cs | 4 +- .../Jpeg/Components/Block8x8F.Generated.tt | 4 +- .../Formats/Jpeg/Components/Block8x8F.cs | 24 ++--- .../Jpeg/Components/Decoder/AdobeMarker.cs | 4 +- .../JpegColorConverter.FromCmyk.cs | 2 +- .../JpegColorConverter.FromGrayScale.cs | 2 +- .../JpegColorConverter.FromRgb.cs | 2 +- .../JpegColorConverter.FromYCbCrBasic.cs | 2 +- .../JpegColorConverter.FromYCbCrSimd.cs | 2 +- .../JpegColorConverter.FromYCbCrSimdAvx2.cs | 2 +- .../JpegColorConverter.FromYccK.cs | 2 +- .../ColorConverters/JpegColorConverter.cs | 4 +- .../Jpeg/Components/Decoder/FastACTable.cs | 2 +- .../Jpeg/Components/Decoder/HuffmanTable.cs | 8 +- .../Jpeg/Components/Decoder/JFifMarker.cs | 18 ++-- .../Decoder/JpegBlockPostProcessor.cs | 14 +-- .../Jpeg/Components/Decoder/JpegColorSpace.cs | 2 +- .../Jpeg/Components/Decoder/JpegComponent.cs | 2 +- .../Decoder/JpegComponentPostProcessor.cs | 2 +- .../Jpeg/Components/Decoder/JpegFrame.cs | 28 +++--- .../Components/Decoder/ProfileResolver.cs | 14 +-- src/ImageSharp/IImageInfo.cs | 2 +- .../IO/DoubleBufferedStreamReader.cs | 8 +- src/ImageSharp/IO/Endianness.cs | 21 ----- src/ImageSharp/IO/LocalFileSystem.cs | 2 +- src/ImageSharp/Image.FromBytes.cs | 15 ++- src/ImageSharp/Image.WrapMemory.cs | 47 +++++----- src/ImageSharp/ImageExtensions.Internal.cs | 1 - src/ImageSharp/ImageExtensions.cs | 8 +- src/ImageSharp/Memory/RowInterval.cs | 11 +-- src/ImageSharp/MetaData/ImageProperty.cs | 5 +- .../MetaData/Profiles/Exif/ExifReader.cs | 32 +++---- .../ICC/Various/IccColorantTableEntry.cs | 13 +-- .../ICC/Various/IccLocalizedString.cs | 5 +- .../Profiles/ICC/Various/IccProfileId.cs | 25 ++--- .../ICC/Various/IccScreeningChannel.cs | 9 +- .../Profiles/ICC/Various/IccTagTableEntry.cs | 21 ++--- .../PixelImplementations/NormalizedByte4.cs | 8 +- src/ImageSharp/Primitives/LongRational.cs | 2 +- src/ImageSharp/Primitives/ValueSize.cs | 22 ++--- 66 files changed, 465 insertions(+), 551 deletions(-) delete mode 100644 src/ImageSharp/IO/Endianness.cs diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs index 63ccea4e6..bdcb4c10f 100644 --- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs +++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Advanced /// Gets the configuration for the image. /// /// The Pixel format. - /// The source image + /// The source image. /// Returns the configuration. public static Configuration GetConfiguration(this Image source) where TPixel : struct, IPixel @@ -150,7 +150,7 @@ namespace SixLabors.ImageSharp.Advanced /// /// Gets the assigned to 'source'. /// - /// The source image + /// The source image. /// Returns the configuration. internal static MemoryAllocator GetMemoryAllocator(this IConfigurable source) => GetConfiguration(source).MemoryAllocator; @@ -185,7 +185,7 @@ namespace SixLabors.ImageSharp.Advanced /// The source. /// The row. /// - /// The span returned from Pixel source + /// The span returned from Pixel source. /// private static Span GetSpan(Buffer2D source, int row) where TPixel : struct, IPixel diff --git a/src/ImageSharp/Advanced/IPixelSource.cs b/src/ImageSharp/Advanced/IPixelSource.cs index 19616d742..a321e877b 100644 --- a/src/ImageSharp/Advanced/IPixelSource.cs +++ b/src/ImageSharp/Advanced/IPixelSource.cs @@ -3,7 +3,6 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; namespace SixLabors.ImageSharp.Advanced { diff --git a/src/ImageSharp/ColorSpaces/CieLch.cs b/src/ImageSharp/ColorSpaces/CieLch.cs index 074bc1516..99d4c09e9 100644 --- a/src/ImageSharp/ColorSpaces/CieLch.cs +++ b/src/ImageSharp/ColorSpaces/CieLch.cs @@ -13,15 +13,15 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public readonly struct CieLch : IEquatable { - private static readonly Vector3 Min = new Vector3(0, -200, 0); - private static readonly Vector3 Max = new Vector3(100, 200, 360); - /// /// D50 standard illuminant. /// Used when reference white is not specified explicitly. /// public static readonly CieXyz DefaultWhitePoint = Illuminants.D50; + private static readonly Vector3 Min = new Vector3(0, -200, 0); + private static readonly Vector3 Max = new Vector3(100, 200, 360); + /// /// Gets the lightness dimension. /// A value ranging between 0 (black), 100 (diffuse white) or higher (specular white). diff --git a/src/ImageSharp/ColorSpaces/CieXyz.cs b/src/ImageSharp/ColorSpaces/CieXyz.cs index 30521476e..6c5adcb21 100644 --- a/src/ImageSharp/ColorSpaces/CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/CieXyz.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public readonly float Y; /// - /// Gets the Z component. Quasi-equal to blue stimulation, or the S cone response + /// Gets the Z component. Quasi-equal to blue stimulation, or the S cone response. /// A value usually ranging between 0 and 1. /// public readonly float Z; diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs index 04901126c..c2331c379 100644 --- a/src/ImageSharp/ColorSpaces/Cmyk.cs +++ b/src/ImageSharp/ColorSpaces/Cmyk.cs @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public static bool operator ==(Cmyk left, Cmyk right) => left.Equals(right); /// - /// Compares two objects for inequality + /// Compares two objects for inequality. /// /// The on the left side of the operand. /// The on the right side of the operand. diff --git a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs index bbd454fbe..cc30c3632 100644 --- a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.ColorSpaces.Companding { /// - /// Implements sRGB companding + /// Implements sRGB companding. /// /// /// For more info see: diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs index 3c197673d..bfabbb21d 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion private static readonly CieLchToCieLabConverter CieLchToCieLabConverter = new CieLchToCieLabConverter(); /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -28,12 +28,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion // Conversion (perserving white point) CieLab unadapted = CieLchToCieLabConverter.Convert(color); - // Adaptation return this.Adapt(unadapted); } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -54,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -66,7 +65,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -87,7 +86,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -99,7 +98,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -120,7 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -132,7 +131,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -159,10 +158,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLab ToCieLab(in CieXyz color) { - // Adaptation CieXyz adapted = this.Adapt(color, this.whitePoint, this.targetLabWhitePoint); - // Conversion return this.cieXyzToCieLabConverter.Convert(adapted); } @@ -199,7 +196,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -220,7 +217,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -232,7 +229,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -253,7 +250,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -264,7 +261,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -285,7 +282,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -297,7 +294,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -318,7 +315,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -330,7 +327,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -351,7 +348,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -363,7 +360,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -384,7 +381,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -396,7 +393,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -429,7 +426,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs index 0a8607e3b..381073619 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -100,7 +100,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -166,7 +166,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -187,7 +187,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -198,7 +198,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -231,7 +231,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -252,7 +252,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -264,7 +264,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -285,7 +285,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -297,7 +297,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -318,7 +318,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -330,7 +330,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -351,7 +351,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -363,7 +363,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -384,7 +384,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -396,7 +396,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -417,7 +417,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -429,7 +429,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs index 3a779ee72..6ca40af03 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -86,21 +86,19 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The public CieLchuv ToCieLchuv(in CieLuv color) { - // Adaptation CieLuv adapted = this.Adapt(color); - // Conversion return CieLuvToCieLchuvConverter.Convert(adapted); } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -121,7 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -133,7 +131,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -154,7 +152,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -166,7 +164,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -187,7 +185,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -199,7 +197,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -220,7 +218,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -253,7 +251,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -265,7 +263,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -286,7 +284,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -298,7 +296,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -319,7 +317,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -331,7 +329,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -352,7 +350,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -364,7 +362,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -385,7 +383,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -397,7 +395,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -418,7 +416,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -429,7 +427,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs index 90eb8e34d..316b35f37 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion private static readonly CieLchuvToCieLuvConverter CieLchuvToCieLuvConverter = new CieLchuvToCieLuvConverter(); /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -148,7 +148,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -162,7 +162,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -183,7 +183,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -194,7 +194,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -226,7 +226,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -247,7 +247,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -258,7 +258,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -279,7 +279,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -290,7 +290,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -311,7 +311,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -322,7 +322,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -343,7 +343,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -354,7 +354,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -375,7 +375,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -386,7 +386,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -407,7 +407,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -418,10 +418,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs index fada6d9c5..2cc8437bb 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion private LinearRgbToCieXyzConverter linearRgbToCieXyzConverter; /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -164,7 +164,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -175,7 +175,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -196,20 +196,19 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The public CieXyz ToCieXyz(in Cmyk color) { - // Conversion var rgb = this.ToRgb(color); return this.ToCieXyz(rgb); } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -230,23 +229,22 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The public CieXyz ToCieXyz(in Hsl color) { - // Conversion var rgb = this.ToRgb(color); return this.ToCieXyz(rgb); } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -264,7 +262,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -277,7 +275,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -298,21 +296,19 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The public CieXyz ToCieXyz(in HunterLab color) { - // Conversion CieXyz unadapted = HunterLabToCieXyzConverter.Convert(color); - // Adaptation return this.Adapt(unadapted, color.WhitePoint); } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -333,7 +329,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -343,15 +339,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion LinearRgbToCieXyzConverter converter = this.GetLinearRgbToCieXyzConverter(color.WorkingSpace); CieXyz unadapted = converter.Convert(color); - // Adaptation return this.Adapt(unadapted, color.WorkingSpace.WhitePoint); } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -369,18 +364,17 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The public CieXyz ToCieXyz(in Lms color) { - // Conversion return this.cieXyzAndLmsConverter.Convert(color); } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -440,7 +434,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieXyz ToCieXyz(in YCbCr color) { - // Conversion var rgb = this.ToRgb(color); return this.ToCieXyz(rgb); diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs index b79851635..00e20e25b 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion private static readonly CmykAndRgbConverter CmykAndRgbConverter = new CmykAndRgbConverter(); /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -149,7 +149,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -161,7 +161,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -182,7 +182,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -215,7 +215,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -227,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -248,7 +248,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -260,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -281,7 +281,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -293,7 +293,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -314,7 +314,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -326,7 +326,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -347,7 +347,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -359,9 +359,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors + /// The span to the source colors, /// The span to the destination colors public void Convert(ReadOnlySpan source, Span destination) { @@ -380,7 +380,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -408,7 +408,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -420,7 +420,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs index a7080b974..76175f1cb 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion private static readonly HslAndRgbConverter HslAndRgbConverter = new HslAndRgbConverter(); /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -128,7 +128,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -149,7 +149,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -281,7 +281,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -293,7 +293,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -314,7 +314,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -326,7 +326,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -347,7 +347,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -359,7 +359,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -387,7 +387,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public Hsl ToHsl(in Rgb color) => HslAndRgbConverter.Convert(color); /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -408,7 +408,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -420,7 +420,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs index a2121203c..e64beb3e4 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs @@ -263,7 +263,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// Performs the bulk conversion from into /// /// The span to the source colors - /// The span to the destination colors + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs index e5996c238..91e5549ac 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs @@ -13,10 +13,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public partial class ColorSpaceConverter { /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -34,10 +34,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -97,10 +97,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -118,10 +118,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -139,7 +139,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -160,10 +160,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors - /// The span to the destination colors + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -181,7 +181,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -223,7 +223,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -244,7 +244,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -265,7 +265,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -286,7 +286,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -297,7 +297,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -308,7 +308,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -319,7 +319,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -330,7 +330,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -341,21 +341,19 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The public HunterLab ToHunterLab(in CieXyz color) { - // Adaptation CieXyz adapted = this.Adapt(color, this.whitePoint, this.targetHunterLabWhitePoint); - // Conversion return this.cieXyzToHunterLabConverter.Convert(adapted); } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -366,7 +364,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -377,7 +375,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -388,7 +386,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -399,7 +397,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -421,7 +419,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs index eef626be2..4be3f0079 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs @@ -17,10 +17,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion private static readonly RgbToLinearRgbConverter RgbToLinearRgbConverter = new RgbToLinearRgbConverter(); /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -38,10 +38,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -59,10 +59,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -80,10 +80,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -101,10 +101,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -122,10 +122,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -143,10 +143,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -164,10 +164,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -185,10 +185,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -206,10 +206,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -227,10 +227,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -248,7 +248,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -269,7 +269,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -290,7 +290,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -301,7 +301,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -312,7 +312,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -323,7 +323,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -345,7 +345,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -359,7 +359,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -370,7 +370,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -381,7 +381,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -392,7 +392,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -403,7 +403,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -425,7 +425,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs index 5780f4f54..68cd34bf2 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs @@ -17,10 +17,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion private static readonly YCbCrAndRgbConverter YCbCrAndRgbConverter = new YCbCrAndRgbConverter(); /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -38,10 +38,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// - /// The span to the source colors - /// The span to the destination colors + /// The span to the source colors. + /// The span to the destination colors. public void Convert(ReadOnlySpan source, Span destination) { Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination)); @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -164,7 +164,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -185,7 +185,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -206,7 +206,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -227,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -248,7 +248,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Performs the bulk conversion from into + /// Performs the bulk conversion from into . /// /// The span to the source colors /// The span to the destination colors @@ -269,7 +269,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -281,7 +281,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -293,7 +293,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -305,7 +305,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -317,7 +317,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -329,7 +329,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -341,7 +341,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -353,7 +353,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -365,7 +365,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -377,7 +377,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -389,7 +389,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The @@ -401,7 +401,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Converts a into a + /// Converts a into a . /// /// The color to convert. /// The diff --git a/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs b/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs index 85a36331b..a4d96d19e 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs @@ -10,13 +10,13 @@ using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation; namespace SixLabors.ImageSharp.ColorSpaces.Conversion { /// - /// Basic implementation of the von Kries chromatic adaptation model + /// Implementation of the von Kries chromatic adaptation model. /// /// /// Transformation described here: /// http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html /// - public class VonKriesChromaticAdaptation : IChromaticAdaptation + public sealed class VonKriesChromaticAdaptation : IChromaticAdaptation { private readonly CieXyzAndLmsConverter converter; diff --git a/src/ImageSharp/ColorSpaces/HunterLab.cs b/src/ImageSharp/ColorSpaces/HunterLab.cs index dcae65e42..402761d8c 100644 --- a/src/ImageSharp/ColorSpaces/HunterLab.cs +++ b/src/ImageSharp/ColorSpaces/HunterLab.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces { /// /// Represents an Hunter LAB color. - /// + /// . /// public readonly struct HunterLab : IEquatable { @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public readonly float B; /// - /// Gets the reference white point of this color + /// Gets the reference white point of this color. /// public readonly CieXyz WhitePoint; @@ -117,10 +117,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() - { - return HashCode.Combine(this.L, this.A, this.B, this.WhitePoint); - } + public override int GetHashCode() => HashCode.Combine(this.L, this.A, this.B, this.WhitePoint); /// public override string ToString() => FormattableString.Invariant($"HunterLab({this.L:#0.##}, {this.A:#0.##}, {this.B:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/Illuminants.cs b/src/ImageSharp/ColorSpaces/Illuminants.cs index ed385e02c..d5c1b3eed 100644 --- a/src/ImageSharp/ColorSpaces/Illuminants.cs +++ b/src/ImageSharp/ColorSpaces/Illuminants.cs @@ -8,11 +8,9 @@ namespace SixLabors.ImageSharp.ColorSpaces /// Standard illuminants provide a basis for comparing images or colors recorded under different lighting /// /// - /// Coefficients taken from: - /// http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html + /// Coefficients taken from: http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html ///
- /// Descriptions taken from: - /// http://en.wikipedia.org/wiki/Standard_illuminant + /// Descriptions taken from: http://en.wikipedia.org/wiki/Standard_illuminant ///
public static class Illuminants { diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs index cdc9e90ad..5cb89a293 100644 --- a/src/ImageSharp/ColorSpaces/Rgb.cs +++ b/src/ImageSharp/ColorSpaces/Rgb.cs @@ -14,14 +14,14 @@ namespace SixLabors.ImageSharp.ColorSpaces ///
public readonly struct Rgb : IEquatable { - private static readonly Vector3 Min = Vector3.Zero; - private static readonly Vector3 Max = Vector3.One; - /// - /// The default rgb working space + /// The default rgb working space. /// public static readonly RgbWorkingSpaceBase DefaultWorkingSpace = RgbWorkingSpaces.SRgb; + private static readonly Vector3 Min = Vector3.Zero; + private static readonly Vector3 Max = Vector3.One; + /// /// Gets the red component. /// A value usually ranging between 0 and 1. diff --git a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs index ee3822c15..7ddcae7ce 100644 --- a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs +++ b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs @@ -8,8 +8,7 @@ using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation; namespace SixLabors.ImageSharp.ColorSpaces { /// - /// Chromaticity coordinates taken from: - /// + /// Chromaticity coordinates based on: /// public static class RgbWorkingSpaces { diff --git a/src/ImageSharp/Common/Extensions/EnumerableExtensions.cs b/src/ImageSharp/Common/Extensions/EnumerableExtensions.cs index e97a2eaed..e28db7cff 100644 --- a/src/ImageSharp/Common/Extensions/EnumerableExtensions.cs +++ b/src/ImageSharp/Common/Extensions/EnumerableExtensions.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Common /// The start index, inclusive. /// /// - /// A method that has one parameter and returns a calculating the end index + /// A method that has one parameter and returns a calculating the end index. /// /// /// The incremental step. @@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Common /// The start index, inclusive. /// /// - /// A method that has one parameter and returns a calculating the end index + /// A method that has one parameter and returns a calculating the end index. /// /// /// The incremental step. diff --git a/src/ImageSharp/Common/Tuples/Octet.cs b/src/ImageSharp/Common/Tuples/Octet.cs index 23faf08ae..7ece2ed56 100644 --- a/src/ImageSharp/Common/Tuples/Octet.cs +++ b/src/ImageSharp/Common/Tuples/Octet.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Tuples internal static class Octet { /// - /// Value tuple of -s + /// Value tuple of -s. /// [StructLayout(LayoutKind.Explicit, Size = 8 * sizeof(uint))] public struct OfUInt32 diff --git a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs index 6a740d47d..c0814b1df 100644 --- a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs @@ -6,7 +6,7 @@ using System; namespace SixLabors.ImageSharp.Formats.Bmp { /// - /// Detects bmp file headers + /// Detects bmp file headers. /// public sealed class BmpImageFormatDetector : IImageFormatDetector { @@ -22,9 +22,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp private bool IsSupportedFileFormat(ReadOnlySpan header) { // TODO: This should be in constants - return header.Length >= this.HeaderSize && - header[0] == 0x42 && // B - header[1] == 0x4D; // M + return header.Length >= this.HeaderSize + && header[0] == 0x42 // B + && header[1] == 0x4D; // M } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs index 42c202a3d..0c59163cc 100644 --- a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs +++ b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Gif Encoding TextEncoding { get; } /// - /// Gets the decoding mode for multi-frame images + /// Gets the decoding mode for multi-frame images. /// FrameDecodingMode DecodingMode { get; } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs index 1f47de594..a9e9903a9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs @@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { Vector4 CMin4 = new Vector4(0F); Vector4 CMax4 = new Vector4(maximum); - Vector4 COff4 = new Vector4((float)Math.Ceiling(maximum/2)); + Vector4 COff4 = new Vector4(MathF.Ceiling(maximum / 2)); this.V0L = Vector4.Clamp(this.V0L + COff4, CMin4, CMax4); this.V0R = Vector4.Clamp(this.V0R + COff4, CMin4, CMax4); @@ -123,7 +123,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public void NormalizeColorsAndRoundInplaceAvx2(float maximum) { - Vector off = new Vector((float)Math.Ceiling(maximum/2)); + Vector off = new Vector(MathF.Ceiling(maximum / 2)); Vector max = new Vector(maximum); ref Vector row0 = ref Unsafe.As>(ref this.V0L); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt index ec4e06e42..d6c42a802 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { Vector4 CMin4 = new Vector4(0F); Vector4 CMax4 = new Vector4(maximum); - Vector4 COff4 = new Vector4((float)Math.Ceiling(maximum/2)); + Vector4 COff4 = new Vector4(MathF.Ceiling(maximum / 2)); <# @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public void NormalizeColorsAndRoundInplaceAvx2(float maximum) { - Vector off = new Vector((float)Math.Ceiling(maximum/2)); + Vector off = new Vector(MathF.Ceiling(maximum / 2)); Vector max = new Vector(maximum); <# diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index c0de45069..c85bd725c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// Fill the block with defaults (zeroes) + /// Fill the block with defaults (zeroes). /// [MethodImpl(InliningOptions.ShortMethod)] public void Clear() @@ -157,7 +157,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// Load raw 32bit floating point data from source + /// Load raw 32bit floating point data from source. /// /// Source [MethodImpl(InliningOptions.ShortMethod)] @@ -170,7 +170,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// Load raw 32bit floating point data from source + /// Load raw 32bit floating point data from source. /// /// Block pointer /// Source @@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// Copy raw 32bit floating point data to dest + /// Copy raw 32bit floating point data to dest, /// /// Destination [MethodImpl(InliningOptions.ShortMethod)] @@ -210,7 +210,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// Convert salars to byte-s and copy to dest + /// Convert salars to byte-s and copy to dest, /// /// Pointer to block /// Destination @@ -226,10 +226,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// Copy raw 32bit floating point data to dest + /// Copy raw 32bit floating point data to dest. /// - /// Block pointer - /// Destination + /// The block pointer. + /// The destination. [MethodImpl(InliningOptions.ShortMethod)] public static unsafe void CopyTo(Block8x8F* blockPtr, Span dest) { @@ -275,7 +275,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Multiply all elements of the block. /// - /// The value to multiply by + /// The value to multiply by. [MethodImpl(InliningOptions.ShortMethod)] public void MultiplyInplace(float value) { @@ -298,7 +298,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// Multiply all elements of the block by the corresponding elements of 'other' + /// Multiply all elements of the block by the corresponding elements of 'other'. /// [MethodImpl(InliningOptions.ShortMethod)] public void MultiplyInplace(ref Block8x8F other) @@ -349,8 +349,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Quantize the block. /// - /// Block pointer - /// Qt pointer + /// The block pointer. + /// The qt pointer. /// Unzig pointer // [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe void DequantizeBlock(Block8x8F* blockPtr, Block8x8F* qtPtr, byte* unzigPtr) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs index 43de39ac7..e34af9825 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// /// Gets the horizontal downsampling hint used for DCT encoding /// 0x0 : (none - Chop) - /// Bit 15 : Encoded with Blend=1 downsampling + /// Bit 15 : Encoded with Blend=1 downsampling. /// public short APP14Flags0 { get; } @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// Converts the specified byte array representation of an Adobe marker to its equivalent and /// returns a value that indicates whether the conversion succeeded. /// - /// The byte array containing metadata to parse + /// The byte array containing metadata to parse. /// The marker to return. public static bool TryParse(byte[] bytes, out AdobeMarker marker) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs index d4dc31fe0..a57535b71 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal class FromCmyk : JpegColorConverter + internal sealed class FromCmyk : JpegColorConverter { public FromCmyk(int precision) : base(JpegColorSpace.Cmyk, precision) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs index 4a5dfa632..15bb2cf4b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal class FromGrayscale : JpegColorConverter + internal sealed class FromGrayscale : JpegColorConverter { public FromGrayscale(int precision) : base(JpegColorSpace.Grayscale, precision) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs index 516dfb39f..2f68e312d 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal class FromRgb : JpegColorConverter + internal sealed class FromRgb : JpegColorConverter { public FromRgb(int precision) : base(JpegColorSpace.RGB, precision) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs index 124aac122..a646cd6cf 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal class FromYCbCrBasic : JpegColorConverter + internal sealed class FromYCbCrBasic : JpegColorConverter { public FromYCbCrBasic(int precision) : base(JpegColorSpace.YCbCr, precision) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs index 10ef02a93..1706b4c1b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal class FromYCbCrSimd : JpegColorConverter + internal sealed class FromYCbCrSimd : JpegColorConverter { public FromYCbCrSimd(int precision) : base(JpegColorSpace.YCbCr, precision) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs index 9953f78c1..093ea2f9a 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal class FromYCbCrSimdAvx2 : JpegColorConverter + internal sealed class FromYCbCrSimdAvx2 : JpegColorConverter { public FromYCbCrSimdAvx2(int precision) : base(JpegColorSpace.YCbCr, precision) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs index 94be11e23..cd8a3bb06 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal class FromYccK : JpegColorConverter + internal sealed class FromYccK : JpegColorConverter { public FromYccK(int precision) : base(JpegColorSpace.Ycck, precision) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index c2e390c59..61e359869 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -42,8 +42,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { this.ColorSpace = colorSpace; this.Precision = precision; - this.MaximumValue = (float)Math.Pow(2, precision) - 1; - this.HalfValue = (float)Math.Ceiling(this.MaximumValue / 2); + this.MaximumValue = MathF.Pow(2, precision) - 1; + this.HalfValue = MathF.Ceiling(this.MaximumValue / 2); } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs index 57d2221ba..dc78a89dd 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder internal unsafe struct FastACTable { /// - /// Gets the lookahead array + /// Gets the lookahead array. /// public fixed short Lookahead[512]; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs index a2c9bade1..7e025e271 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs @@ -26,22 +26,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder #pragma warning restore IDE0044 // Add readonly modifier /// - /// Gets the max code array + /// Gets the max code array. /// public fixed uint MaxCode[18]; /// - /// Gets the value offset array + /// Gets the value offset array. /// public fixed int ValOffset[18]; /// - /// Gets the huffman value array + /// Gets the huffman value array. /// public fixed byte Values[256]; /// - /// Gets the lookahead array + /// Gets the lookahead array. /// public fixed byte Lookahead[512]; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs index 76f0e2cb5..5bd5920db 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs @@ -7,7 +7,7 @@ using SixLabors.ImageSharp.MetaData; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { /// - /// Provides information about the JFIF marker segment + /// Provides information about the JFIF marker segment. /// TODO: Thumbnail? /// internal readonly struct JFifMarker : IEquatable @@ -20,11 +20,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// /// Initializes a new instance of the struct. /// - /// The major version - /// The minor version - /// The units for the density values - /// The horizontal pixel density - /// The vertical pixel density + /// The major version. + /// The minor version. + /// The units for the density values. + /// The horizontal pixel density. + /// The vertical pixel density. private JFifMarker(byte majorVersion, byte minorVersion, byte densityUnits, short xDensity, short yDensity) { if (xDensity <= 0) @@ -47,12 +47,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } /// - /// Gets the major version + /// Gets the major version. /// public byte MajorVersion { get; } /// - /// Gets the minor version + /// Gets the minor version. /// public byte MinorVersion { get; } @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// Converts the specified byte array representation of an JFIF marker to its equivalent and /// returns a value that indicates whether the conversion succeeded. /// - /// The byte array containing metadata to parse + /// The byte array containing metadata to parse. /// The marker to return. public static bool TryParse(byte[] bytes, out JFifMarker marker) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs index fe39f4188..c5efb812e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs @@ -20,17 +20,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder public Block8x8F SourceBlock; /// - /// Temporal block 1 to store intermediate and/or final computation results + /// Temporal block 1 to store intermediate and/or final computation results. /// public Block8x8F WorkspaceBlock1; /// - /// Temporal block 2 to store intermediate and/or final computation results + /// Temporal block 2 to store intermediate and/or final computation results. /// public Block8x8F WorkspaceBlock2; /// - /// The quantization table as + /// The quantization table as . /// public Block8x8F DequantiazationTable; @@ -40,9 +40,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder private Size subSamplingDivisors; /// - /// Defines the maximum value derived from the bitdepth + /// Defines the maximum value derived from the bitdepth. /// - private int maximumValue; + private readonly int maximumValue; /// /// Initializes a new instance of the struct. @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder int qtIndex = component.QuantizationTableIndex; this.DequantiazationTable = ZigZag.CreateDequantizationTable(ref decoder.QuantizationTables[qtIndex]); this.subSamplingDivisors = component.SubSamplingDivisors; - this.maximumValue = (int)Math.Pow(2, decoder.Precision) - 1; + this.maximumValue = (int)MathF.Pow(2, decoder.Precision) - 1; this.SourceBlock = default; this.WorkspaceBlock1 = default; @@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// - Dequantize /// - Applying IDCT /// - Level shift by +maximumValue/2, clip to [0, maximumValue] - /// - Copy the resulting color values into 'destArea' scaling up the block by amount defined in + /// - Copy the resulting color values into 'destArea' scaling up the block by amount defined in . /// /// The source block. /// The destination buffer area. diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegColorSpace.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegColorSpace.cs index 2861a2c2e..aa33744ad 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegColorSpace.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegColorSpace.cs @@ -4,7 +4,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { /// - /// Identifies the colorspace of a Jpeg image + /// Identifies the colorspace of a Jpeg image. /// internal enum JpegColorSpace { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs index ac24f4ca5..535330394 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } /// - /// Gets the component Id. + /// Gets the component id. /// public byte Id { get; } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs index e7f3e4fda..e1a9380a0 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder public void CopyBlocksToColorBuffer() { var blockPp = new JpegBlockPostProcessor(this.ImagePostProcessor.RawJpeg, this.Component); - float maximumValue = (float)Math.Pow(2, this.ImagePostProcessor.RawJpeg.Precision) - 1; + float maximumValue = MathF.Pow(2, this.ImagePostProcessor.RawJpeg.Precision) - 1; for (int y = 0; y < this.BlockRowsPerStep; y++) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs index 33a7c68ba..f426eb1b1 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs @@ -11,68 +11,68 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder internal sealed class JpegFrame : IDisposable { /// - /// Gets or sets a value indicating whether the frame uses the extended specification + /// Gets or sets a value indicating whether the frame uses the extended specification. /// public bool Extended { get; set; } /// - /// Gets or sets a value indicating whether the frame uses the progressive specification + /// Gets or sets a value indicating whether the frame uses the progressive specification. /// public bool Progressive { get; set; } /// - /// Gets or sets the precision + /// Gets or sets the precision. /// public byte Precision { get; set; } /// - /// Gets or sets the number of scanlines within the frame + /// Gets or sets the number of scanlines within the frame. /// public short Scanlines { get; set; } /// - /// Gets or sets the number of samples per scanline + /// Gets or sets the number of samples per scanline. /// public short SamplesPerLine { get; set; } /// - /// Gets or sets the number of components within a frame. In progressive frames this value can range from only 1 to 4 + /// Gets or sets the number of components within a frame. In progressive frames this value can range from only 1 to 4. /// public byte ComponentCount { get; set; } /// - /// Gets or sets the component id collection + /// Gets or sets the component id collection. /// public byte[] ComponentIds { get; set; } /// - /// Gets or sets the order in which to process the components + /// Gets or sets the order in which to process the components. /// in interleaved mode. /// public byte[] ComponentOrder { get; set; } /// - /// Gets or sets the frame component collection + /// Gets or sets the frame component collection. /// public JpegComponent[] Components { get; set; } /// - /// Gets or sets the maximum horizontal sampling factor + /// Gets or sets the maximum horizontal sampling factor. /// public int MaxHorizontalFactor { get; set; } /// - /// Gets or sets the maximum vertical sampling factor + /// Gets or sets the maximum vertical sampling factor. /// public int MaxVerticalFactor { get; set; } /// - /// Gets or sets the number of MCU's per line + /// Gets or sets the number of MCU's per line. /// public int McusPerLine { get; set; } /// - /// Gets or sets the number of MCU's per column + /// Gets or sets the number of MCU's per column. /// public int McusPerColumn { get; set; } @@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } /// - /// Allocates the frame component blocks + /// Allocates the frame component blocks. /// public void InitComponents() { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs index 3e7108b15..abfd6f556 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs @@ -12,30 +12,30 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder internal static class ProfileResolver { /// - /// Describes the EXIF specific markers + /// Describes the EXIF specific markers. /// public static readonly byte[] JFifMarker = Encoding.ASCII.GetBytes("JFIF\0"); /// - /// Describes the EXIF specific markers + /// Describes the EXIF specific markers. /// public static readonly byte[] IccMarker = Encoding.ASCII.GetBytes("ICC_PROFILE\0"); /// - /// Describes the ICC specific markers + /// Describes the ICC specific markers. /// public static readonly byte[] ExifMarker = Encoding.ASCII.GetBytes("Exif\0\0"); /// - /// Describes Adobe specific markers + /// Describes Adobe specific markers . /// public static readonly byte[] AdobeMarker = Encoding.ASCII.GetBytes("Adobe"); /// - /// Returns a value indicating whether the passed bytes are a match to the profile identifier + /// Returns a value indicating whether the passed bytes are a match to the profile identifier. /// - /// The bytes to check - /// The profile identifier + /// The bytes to check. + /// The profile identifier. /// The public static bool IsProfile(ReadOnlySpan bytesToCheck, ReadOnlySpan profileIdentifier) { diff --git a/src/ImageSharp/IImageInfo.cs b/src/ImageSharp/IImageInfo.cs index 6e64aa679..b1b1afc66 100644 --- a/src/ImageSharp/IImageInfo.cs +++ b/src/ImageSharp/IImageInfo.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp { /// /// Encapsulates properties that describe basic image information including dimensions, pixel type information - /// and additional metadata + /// and additional metadata. /// public interface IImageInfo { diff --git a/src/ImageSharp/IO/DoubleBufferedStreamReader.cs b/src/ImageSharp/IO/DoubleBufferedStreamReader.cs index 8530ecec5..6d5673d5a 100644 --- a/src/ImageSharp/IO/DoubleBufferedStreamReader.cs +++ b/src/ImageSharp/IO/DoubleBufferedStreamReader.cs @@ -13,10 +13,10 @@ namespace SixLabors.ImageSharp.IO /// A stream reader that add a secondary level buffer in addition to native stream buffered reading /// to reduce the overhead of small incremental reads. ///
- internal class DoubleBufferedStreamReader : IDisposable + internal sealed class DoubleBufferedStreamReader : IDisposable { /// - /// The length, in bytes, of the buffering chunk + /// The length, in bytes, of the buffering chunk. /// public const int ChunkLength = 4096; @@ -49,12 +49,12 @@ namespace SixLabors.ImageSharp.IO } /// - /// Gets the length, in bytes, of the stream + /// Gets the length, in bytes, of the stream. /// public long Length => this.length; /// - /// Gets or sets the current position within the stream + /// Gets or sets the current position within the stream. /// public long Position { diff --git a/src/ImageSharp/IO/Endianness.cs b/src/ImageSharp/IO/Endianness.cs deleted file mode 100644 index 59b2ae77c..000000000 --- a/src/ImageSharp/IO/Endianness.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.IO -{ - /// - /// Endianness of a converter - /// - internal enum Endianness - { - /// - /// Little endian - least significant byte first - /// - LittleEndian, - - /// - /// Big endian - most significant byte first - /// - BigEndian - } -} diff --git a/src/ImageSharp/IO/LocalFileSystem.cs b/src/ImageSharp/IO/LocalFileSystem.cs index dc5901ff9..11f3d7972 100644 --- a/src/ImageSharp/IO/LocalFileSystem.cs +++ b/src/ImageSharp/IO/LocalFileSystem.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.IO /// /// A wrapper around the local File apis. /// - internal class LocalFileSystem : IFileSystem + internal sealed class LocalFileSystem : IFileSystem { /// public Stream OpenRead(string path) => File.OpenRead(path); diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs index 34927e6e2..7ceeea949 100644 --- a/src/ImageSharp/Image.FromBytes.cs +++ b/src/ImageSharp/Image.FromBytes.cs @@ -3,7 +3,6 @@ using System; using System.IO; -using System.Linq; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.PixelFormats; @@ -32,7 +31,7 @@ namespace SixLabors.ImageSharp /// The mime type or null if none found. public static IImageFormat DetectFormat(Configuration config, byte[] data) { - using (Stream stream = new MemoryStream(data)) + using (var stream = new MemoryStream(data)) { return DetectFormat(config, stream); } @@ -118,9 +117,9 @@ namespace SixLabors.ImageSharp public static Image Load(Configuration config, byte[] data) where TPixel : struct, IPixel { - using (var memoryStream = new MemoryStream(data)) + using (var steram = new MemoryStream(data)) { - return Load(config, memoryStream); + return Load(config, steram); } } @@ -135,9 +134,9 @@ namespace SixLabors.ImageSharp public static Image Load(Configuration config, byte[] data, out IImageFormat format) where TPixel : struct, IPixel { - using (var memoryStream = new MemoryStream(data)) + using (var stream = new MemoryStream(data)) { - return Load(config, memoryStream, out format); + return Load(config, stream, out format); } } @@ -151,9 +150,9 @@ namespace SixLabors.ImageSharp public static Image Load(byte[] data, IImageDecoder decoder) where TPixel : struct, IPixel { - using (var memoryStream = new MemoryStream(data)) + using (var stream = new MemoryStream(data)) { - return Load(memoryStream, decoder); + return Load(stream, decoder); } } diff --git a/src/ImageSharp/Image.WrapMemory.cs b/src/ImageSharp/Image.WrapMemory.cs index c2935bed9..4bb24a126 100644 --- a/src/ImageSharp/Image.WrapMemory.cs +++ b/src/ImageSharp/Image.WrapMemory.cs @@ -7,7 +7,6 @@ using System.Buffers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.MetaData; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; namespace SixLabors.ImageSharp { @@ -22,10 +21,10 @@ namespace SixLabors.ImageSharp ///
/// The pixel type /// The - /// The pixel memory - /// The width of the memory image - /// The height of the memory image - /// The + /// The pixel memory. + /// The width of the memory image. + /// The height of the memory image. + /// The . /// An instance public static Image WrapMemory( Configuration config, @@ -45,10 +44,10 @@ namespace SixLabors.ImageSharp ///
/// The pixel type /// The - /// The pixel memory - /// The width of the memory image - /// The height of the memory image - /// An instance + /// The pixel memory. + /// The width of the memory image. + /// The height of the memory image. + /// An instance. public static Image WrapMemory( Configuration config, Memory pixelMemory, @@ -64,11 +63,11 @@ namespace SixLabors.ImageSharp /// allowing to view/manipulate it as an ImageSharp instance. /// The memory is being observed, the caller remains responsible for managing it's lifecycle. ///
- /// The pixel type - /// The pixel memory - /// The width of the memory image - /// The height of the memory image - /// An instance + /// The pixel type. + /// The pixel memory. + /// The width of the memory image. + /// The height of the memory image. + /// An instance. public static Image WrapMemory( Memory pixelMemory, int width, @@ -88,8 +87,8 @@ namespace SixLabors.ImageSharp /// The pixel type /// The /// The that is being transferred to the image - /// The width of the memory image - /// The height of the memory image + /// The width of the memory image. + /// The height of the memory image. /// The /// An instance public static Image WrapMemory( @@ -111,11 +110,11 @@ namespace SixLabors.ImageSharp /// meaning that the caller is not allowed to dispose . /// It will be disposed together with the result image. ///
- /// The pixel type + /// The pixel type. /// The - /// The that is being transferred to the image - /// The width of the memory image - /// The height of the memory image + /// The that is being transferred to the image. + /// The width of the memory image. + /// The height of the memory image. /// An instance public static Image WrapMemory( Configuration config, @@ -135,10 +134,10 @@ namespace SixLabors.ImageSharp /// It will be disposed together with the result image. ///
/// The pixel type - /// The that is being transferred to the image - /// The width of the memory image - /// The height of the memory image - /// An instance + /// The that is being transferred to the image. + /// The width of the memory image. + /// The height of the memory image. + /// An instance. public static Image WrapMemory( IMemoryOwner pixelMemoryOwner, int width, diff --git a/src/ImageSharp/ImageExtensions.Internal.cs b/src/ImageSharp/ImageExtensions.Internal.cs index dfdbbd89b..5b5e56665 100644 --- a/src/ImageSharp/ImageExtensions.Internal.cs +++ b/src/ImageSharp/ImageExtensions.Internal.cs @@ -3,7 +3,6 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; namespace SixLabors.ImageSharp { diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs index cbf93275c..5010451b8 100644 --- a/src/ImageSharp/ImageExtensions.cs +++ b/src/ImageSharp/ImageExtensions.cs @@ -12,7 +12,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { /// - /// Extension methods over Image{TPixel} + /// Extension methods over Image{TPixel}. /// public static partial class ImageExtensions { @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp if (format is null) { var sb = new StringBuilder(); - sb.AppendLine($"Can't find a format that is associated with the file extension '{ext}'. Registered formats with there extensions include:"); + sb.AppendLine($"No encoder was found for extension '{ext}'. Registered encoders include:"); foreach (IImageFormat fmt in source.GetConfiguration().ImageFormats) { sb.AppendLine($" - {fmt.Name} : {string.Join(", ", fmt.FileExtensions)}"); @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp if (encoder is null) { var sb = new StringBuilder(); - sb.AppendLine($"Can't find encoder for file extension '{ext}' using image format '{format.Name}'. Registered encoders include:"); + sb.AppendLine($"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:"); foreach (KeyValuePair enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders) { sb.AppendLine($" - {enc.Key} : {enc.Value.GetType().Name}"); @@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp if (encoder is null) { var sb = new StringBuilder(); - sb.AppendLine("Can't find encoder for provided mime type. Available encoded:"); + sb.AppendLine("No encoder was found for the provided mime type. Registered encoders include:"); foreach (KeyValuePair val in source.GetConfiguration().ImageFormatsManager.ImageEncoders) { diff --git a/src/ImageSharp/Memory/RowInterval.cs b/src/ImageSharp/Memory/RowInterval.cs index 501ed5e69..835e880e9 100644 --- a/src/ImageSharp/Memory/RowInterval.cs +++ b/src/ImageSharp/Memory/RowInterval.cs @@ -22,24 +22,21 @@ namespace SixLabors.ImageSharp.Memory } /// - /// Gets the INCLUSIVE minimum + /// Gets the INCLUSIVE minimum. /// public int Min { get; } /// - /// Gets the EXCLUSIVE maximum + /// Gets the EXCLUSIVE maximum. /// public int Max { get; } /// - /// Gets the difference ( - ) + /// Gets the difference ( - ). /// public int Height => this.Max - this.Min; /// - public override string ToString() - { - return $"RowInterval [{this.Min}->{this.Max}["; - } + public override string ToString() => $"RowInterval [{this.Min}->{this.Max}]"; } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/ImageProperty.cs b/src/ImageSharp/MetaData/ImageProperty.cs index 24a3686de..6d38b6bf1 100644 --- a/src/ImageSharp/MetaData/ImageProperty.cs +++ b/src/ImageSharp/MetaData/ImageProperty.cs @@ -107,10 +107,7 @@ namespace SixLabors.ImageSharp.MetaData /// /// A containing a fully qualified type name. /// - public override string ToString() - { - return $"ImageProperty [ Name={this.Name}, Value={this.Value} ]"; - } + public override string ToString() => $"ImageProperty [ Name={this.Name}, Value={this.Value} ]"; /// /// Indicates whether the current object is equal to another object of the same type. diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs index 8ec9eea27..cf95affb0 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs @@ -8,20 +8,19 @@ using System.Collections.ObjectModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; -using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Primitives; namespace SixLabors.ImageSharp.MetaData.Profiles.Exif { /// - /// Reads and parses EXIF data from a byte array + /// Reads and parses EXIF data from a byte array. /// internal sealed class ExifReader { private List invalidTags; private readonly byte[] exifData; private int position; - private Endianness endianness = Endianness.BigEndian; + private bool isBigEndian; private uint exifOffset; private uint gpsOffset; @@ -38,12 +37,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif public IReadOnlyList InvalidTags => this.invalidTags ?? (IReadOnlyList)Array.Empty(); /// - /// Gets the thumbnail length in the byte stream + /// Gets the thumbnail length in the byte stream. /// public uint ThumbnailLength { get; private set; } /// - /// Gets the thumbnail offset position in the byte stream + /// Gets the thumbnail offset position in the byte stream. /// public uint ThumbnailOffset { get; private set; } @@ -74,10 +73,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif var values = new List(); // II == 0x4949 - if (this.ReadUInt16() == 0x4949) - { - this.endianness = Endianness.LittleEndian; - } + this.isBigEndian = !(this.ReadUInt16() == 0x4949); if (this.ReadUInt16() != 0x002A) { @@ -382,7 +378,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif [MethodImpl(InliningOptions.ShortMethod)] private TEnum ToEnum(int value, TEnum defaultValue) - where TEnum : struct + where TEnum : struct, Enum { if (EnumHelper.IsDefined(value)) { @@ -458,7 +454,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif return default; } - long intValue = this.endianness == Endianness.BigEndian + long intValue = this.isBigEndian ? BinaryPrimitives.ReadInt64BigEndian(buffer) : BinaryPrimitives.ReadInt64LittleEndian(buffer); @@ -473,7 +469,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif return default; } - return this.endianness == Endianness.BigEndian + return this.isBigEndian ? BinaryPrimitives.ReadUInt32BigEndian(buffer) : BinaryPrimitives.ReadUInt32LittleEndian(buffer); } @@ -485,7 +481,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif return default; } - return this.endianness == Endianness.BigEndian + return this.isBigEndian ? BinaryPrimitives.ReadUInt16BigEndian(buffer) : BinaryPrimitives.ReadUInt16LittleEndian(buffer); } @@ -497,7 +493,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif return default; } - int intValue = this.endianness == Endianness.BigEndian + int intValue = this.isBigEndian ? BinaryPrimitives.ReadInt32BigEndian(buffer) : BinaryPrimitives.ReadInt32LittleEndian(buffer); @@ -526,7 +522,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif return default; } - return this.endianness == Endianness.BigEndian + return this.isBigEndian ? BinaryPrimitives.ReadInt32BigEndian(buffer) : BinaryPrimitives.ReadInt32LittleEndian(buffer); } @@ -551,13 +547,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif return default; } - return this.endianness == Endianness.BigEndian + return this.isBigEndian ? BinaryPrimitives.ReadInt16BigEndian(buffer) : BinaryPrimitives.ReadInt16LittleEndian(buffer); } - private class EnumHelper - where TEnum : struct + private sealed class EnumHelper + where TEnum : struct, Enum { private static readonly int[] Values = Enum.GetValues(typeof(TEnum)).Cast() .Select(e => Convert.ToInt32(e)).OrderBy(e => e).ToArray(); diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs index 8f273dd60..4bcd1b686 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs @@ -35,22 +35,22 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - /// Gets the colorant name + /// Gets the colorant name. /// public string Name { get; } /// - /// Gets the first PCS value + /// Gets the first PCS value. /// public ushort Pcs1 { get; } /// - /// Gets the second PCS value + /// Gets the second PCS value. /// public ushort Pcs2 { get; } /// - /// Gets the third PCS value + /// Gets the third PCS value. /// public ushort Pcs3 { get; } @@ -110,9 +110,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override string ToString() - { - return $"{this.Name}: {this.Pcs1}; {this.Pcs2}; {this.Pcs3}"; - } + public override string ToString() => $"{this.Name}: {this.Pcs1}; {this.Pcs2}; {this.Pcs3}"; } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs index 00ededca4..1920e97fe 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs @@ -49,9 +49,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc this.Text == other.Text; /// - public override string ToString() - { - return $"{this.Culture.Name}: {this.Text}"; - } + public override string ToString() => $"{this.Culture.Name}: {this.Text}"; } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs index f64d5409a..710e6bb25 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs @@ -31,27 +31,27 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - /// Gets the first part of the ID + /// Gets the first part of the ID. /// public uint Part1 { get; } /// - /// Gets the second part of the ID + /// Gets the second part of the ID. /// public uint Part2 { get; } /// - /// Gets the third part of the ID + /// Gets the third part of the ID. /// public uint Part3 { get; } /// - /// Gets the fourth part of the ID + /// Gets the fourth part of the ID. /// public uint Part4 { get; } /// - /// Gets a value indicating whether the ID is set or just consists of zeros + /// Gets a value indicating whether the ID is set or just consists of zeros. /// public bool IsSet => !this.Equals(Zero); @@ -86,10 +86,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override bool Equals(object obj) - { - return obj is IccProfileId other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccProfileId other && this.Equals(other); /// public bool Equals(IccProfileId other) => @@ -109,14 +106,8 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override string ToString() - { - return $"{ToHex(this.Part1)}-{ToHex(this.Part2)}-{ToHex(this.Part3)}-{ToHex(this.Part4)}"; - } + public override string ToString() => $"{ToHex(this.Part1)}-{ToHex(this.Part2)}-{ToHex(this.Part3)}-{ToHex(this.Part4)}"; - private static string ToHex(uint value) - { - return value.ToString("X").PadLeft(8, '0'); - } + private static string ToHex(uint value) => value.ToString("X").PadLeft(8, '0'); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs index e8885a66b..7e2072d5b 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs @@ -26,12 +26,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - /// Gets the screen frequency + /// Gets the screen frequency. /// public float Frequency { get; } /// - /// Gets the angle in degrees + /// Gets the angle in degrees. /// public float Angle { get; } @@ -89,9 +89,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override string ToString() - { - return $"{this.Frequency}Hz; {this.Angle}°; {this.SpotShape}"; - } + public override string ToString() => $"{this.Frequency}Hz; {this.Angle}°; {this.SpotShape}"; } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs index d93e068c5..7713c4faa 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs @@ -24,17 +24,17 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - /// Gets the signature of the tag + /// Gets the signature of the tag. /// public IccProfileTag Signature { get; } /// - /// Gets the offset of entry in bytes + /// Gets the offset of entry in bytes. /// public uint Offset { get; } /// - /// Gets the size of entry in bytes + /// Gets the size of entry in bytes. /// public uint DataSize { get; } @@ -69,10 +69,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override bool Equals(object obj) - { - return obj is IccTagTableEntry other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccTagTableEntry other && this.Equals(other); /// public bool Equals(IccTagTableEntry other) => @@ -81,15 +78,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc this.DataSize.Equals(other.DataSize); /// - public override int GetHashCode() - { - return HashCode.Combine(this.Signature, this.Offset, this.DataSize); - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Offset, this.DataSize); /// - public override string ToString() - { - return $"{this.Signature} (Offset: {this.Offset}; Size: {this.DataSize})"; - } + public override string ToString() => $"{this.Signature} (Offset: {this.Offset}; Size: {this.DataSize})"; } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs index 82698d508..8a9368463 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs @@ -164,10 +164,10 @@ namespace SixLabors.ImageSharp.PixelFormats { vector = Vector4.Clamp(vector, MinusOne, Vector4.One) * Half; - uint byte4 = ((uint)Math.Round(vector.X) & 0xFF) << 0; - uint byte3 = ((uint)Math.Round(vector.Y) & 0xFF) << 8; - uint byte2 = ((uint)Math.Round(vector.Z) & 0xFF) << 16; - uint byte1 = ((uint)Math.Round(vector.W) & 0xFF) << 24; + uint byte4 = ((uint)MathF.Round(vector.X) & 0xFF) << 0; + uint byte3 = ((uint)MathF.Round(vector.Y) & 0xFF) << 8; + uint byte2 = ((uint)MathF.Round(vector.Z) & 0xFF) << 16; + uint byte1 = ((uint)MathF.Round(vector.W) & 0xFF) << 24; return byte4 | byte3 | byte2 | byte1; } diff --git a/src/ImageSharp/Primitives/LongRational.cs b/src/ImageSharp/Primitives/LongRational.cs index d790b110d..b15aa4022 100644 --- a/src/ImageSharp/Primitives/LongRational.cs +++ b/src/ImageSharp/Primitives/LongRational.cs @@ -8,7 +8,7 @@ using System.Text; namespace SixLabors.ImageSharp.Primitives { /// - /// Represents a number that can be expressed as a fraction + /// Represents a number that can be expressed as a fraction. /// /// /// This is a very simplified implementation of a rational number designed for use with metadata only. diff --git a/src/ImageSharp/Primitives/ValueSize.cs b/src/ImageSharp/Primitives/ValueSize.cs index e5e086540..44bee5030 100644 --- a/src/ImageSharp/Primitives/ValueSize.cs +++ b/src/ImageSharp/Primitives/ValueSize.cs @@ -28,22 +28,22 @@ namespace SixLabors.ImageSharp.Primitives } /// - /// Enumerates the different value types + /// Enumerates the different value types. /// public enum ValueSizeType { /// - /// The value is the final return value + /// The value is the final return value. /// Absolute, /// - /// The value is a percentage of the image width + /// The value is a percentage of the image width. /// PercentageOfWidth, /// - /// The value is a percentage of the images height + /// The value is a percentage of the images height. /// PercentageOfHeight } @@ -59,11 +59,10 @@ namespace SixLabors.ImageSharp.Primitives public ValueSizeType Type { get; } /// - /// Implicitly converts a float into an absolute value + /// Implicitly converts a float into an absolute value. /// /// the value to use as the absolute figure. - public static implicit operator ValueSize(float f) - => Absolute(f); + public static implicit operator ValueSize(float f) => Absolute(f); /// /// Create a new ValueSize with as a PercentageOfWidth type with value set to percentage. @@ -89,7 +88,7 @@ namespace SixLabors.ImageSharp.Primitives /// Create a new ValueSize with as a Absolute type with value set to value. /// /// The value. - /// a Values size with type Absolute( + /// a Values size with type Absolute. public static ValueSize Absolute(float value) { return new ValueSize(value, ValueSizeType.Absolute); @@ -99,7 +98,7 @@ namespace SixLabors.ImageSharp.Primitives /// Calculates the specified size. /// /// The size. - /// The calculated value + /// The calculated value. public float Calculate(Size size) { switch (this.Type) @@ -115,10 +114,7 @@ namespace SixLabors.ImageSharp.Primitives } /// - public override string ToString() - { - return $"{this.Value} - {this.Type}"; - } + public override string ToString() => $"{this.Value} - {this.Type}"; /// public override bool Equals(object obj) From a7f9a8e9e16004174a500063aa22f0e83b1b19b4 Mon Sep 17 00:00:00 2001 From: Poyo Date: Wed, 3 Apr 2019 05:32:32 -0700 Subject: [PATCH 046/223] Fix incorrect gradient color-stop calculation (#864) * Fix incorrect gradient color-stop calculation * Update submodule * Add multi-stop gradient test * Add missing reference image --- .../Processing/GradientBrushBase{TPixel}.cs | 2 +- .../Drawing/FillLinearGradientBrushTests.cs | 47 +++++++++++++++++++ tests/Images/External | 2 +- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs index 00141a8d8..ca565c46c 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs @@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Processing { var fromAsVector = from.Color.ToVector4(); var toAsVector = to.Color.ToVector4(); - float onLocalGradient = (positionOnCompleteGradient - from.Ratio) / to.Ratio; + float onLocalGradient = (positionOnCompleteGradient - from.Ratio) / (to.Ratio - from.Ratio); // TODO: this should be changeble for different gradienting functions Vector4 result = PorterDuffFunctions.NormalSrcOver( diff --git a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs index 556ec9c9c..0bab2c079 100644 --- a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs @@ -350,5 +350,52 @@ namespace SixLabors.ImageSharp.Tests.Drawing false, false); } + + [Theory] + [WithBlankImages(200, 200, PixelTypes.Rgba32, 0, 0, 199, 199, new[] { 0f, .25f, .5f, .75f, 1f }, new[] { 0, 1, 2, 3, 4 })] + public void MultiplePointGradients( + TestImageProvider provider, + int startX, int startY, + int endX, int endY, + float[] stopPositions, + int[] stopColorCodes) + where TPixel : struct, IPixel + { + TPixel[] colors = + { + NamedColors.Black, NamedColors.Blue, NamedColors.Red, + NamedColors.White, NamedColors.Lime + }; + + var coloringVariant = new StringBuilder(); + var colorStops = new ColorStop[stopPositions.Length]; + + for (int i = 0; i < stopPositions.Length; i++) + { + TPixel color = colors[stopColorCodes[i % colors.Length]]; + float position = stopPositions[i]; + colorStops[i] = new ColorStop(position, color); + Rgba32 rgba = default; + color.ToRgba32(ref rgba); + coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position); + } + + FormattableString variant = $"({startX},{startY})_TO_({endX},{endY})__[{coloringVariant}]"; + + provider.VerifyOperation( + image => + { + var unicolorLinearGradientBrush = new LinearGradientBrush( + new SixLabors.Primitives.Point(startX, startY), + new SixLabors.Primitives.Point(endX, endY), + GradientRepetitionMode.None, + colorStops); + + image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); + }, + variant, + false, + false); + } } } \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index 9d7198554..bc2765fb9 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 9d71985545bb827270ca34af3f78e4c220560ef1 +Subproject commit bc2765fb949d5d4ddba289b29174022bb94646de From 0dfa2f9f98fb93cf1fc9d082df5d08affc4be5a8 Mon Sep 17 00:00:00 2001 From: Poyo Date: Wed, 3 Apr 2019 15:12:31 -0700 Subject: [PATCH 047/223] Change existing gradient brushes to accept PointF (#865) * Change existing gradient brushes to accept PointF * Change PositionOnGradient to accept float * Remove invalid assert. --- .../EllipticGradientBrush{TPixel}.cs | 18 +++++++-------- .../Processing/GradientBrushBase{TPixel}.cs | 12 +++++----- .../Processing/LinearGradientBrush{TPixel}.cs | 22 +++++++++---------- .../Processing/RadialGradientBrush{TPixel}.cs | 10 ++++----- .../Drawing/FillLinearGradientBrushTests.cs | 4 ---- tests/Images/External | 2 +- 6 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs index 8af01564c..64901c8e8 100644 --- a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs @@ -18,9 +18,9 @@ namespace SixLabors.ImageSharp.Processing public sealed class EllipticGradientBrush : GradientBrushBase where TPixel : struct, IPixel { - private readonly Point center; + private readonly PointF center; - private readonly Point referenceAxisEnd; + private readonly PointF referenceAxisEnd; private readonly float axisRatio; @@ -35,8 +35,8 @@ namespace SixLabors.ImageSharp.Processing /// Defines how the colors of the gradients are repeated. /// the color stops as defined in base class. public EllipticGradientBrush( - Point center, - Point referenceAxisEnd, + PointF center, + PointF referenceAxisEnd, float axisRatio, GradientRepetitionMode repetitionMode, params ColorStop[] colorStops) @@ -64,9 +64,9 @@ namespace SixLabors.ImageSharp.Processing /// private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase { - private readonly Point center; + private readonly PointF center; - private readonly Point referenceAxisEnd; + private readonly PointF referenceAxisEnd; private readonly float axisRatio; @@ -99,8 +99,8 @@ namespace SixLabors.ImageSharp.Processing public RadialGradientBrushApplicator( ImageFrame target, GraphicsOptions options, - Point center, - Point referenceAxisEnd, + PointF center, + PointF referenceAxisEnd, float axisRatio, ColorStop[] colorStops, GradientRepetitionMode repetitionMode) @@ -129,7 +129,7 @@ namespace SixLabors.ImageSharp.Processing } /// - protected override float PositionOnGradient(int xt, int yt) + protected override float PositionOnGradient(float xt, float yt) { float x0 = xt - this.center.X; float y0 = yt - this.center.Y; diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs index ca565c46c..2dfae9e8f 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing { get { - float positionOnCompleteGradient = this.PositionOnGradient(x, y); + float positionOnCompleteGradient = this.PositionOnGradient(x + 0.5f, y + 0.5f); switch (this.repetitionMode) { @@ -137,18 +137,18 @@ namespace SixLabors.ImageSharp.Processing } /// - /// calculates the position on the gradient for a given pixel. + /// calculates the position on the gradient for a given point. /// This method is abstract as it's content depends on the shape of the gradient. /// - /// The x coordinate of the pixel - /// The y coordinate of the pixel + /// The x coordinate of the point + /// The y coordinate of the point /// - /// The position the given pixel has on the gradient. + /// The position the given point has on the gradient. /// The position is not bound to the [0..1] interval. /// Values outside of that interval may be treated differently, /// e.g. for the enum. /// - protected abstract float PositionOnGradient(int x, int y); + protected abstract float PositionOnGradient(float x, float y); private (ColorStop from, ColorStop to) GetGradientSegment( float positionOnCompleteGradient) diff --git a/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs index 765bf5499..efdc852f2 100644 --- a/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs @@ -17,9 +17,9 @@ namespace SixLabors.ImageSharp.Processing public sealed class LinearGradientBrush : GradientBrushBase where TPixel : struct, IPixel { - private readonly Point p1; + private readonly PointF p1; - private readonly Point p2; + private readonly PointF p2; /// /// Initializes a new instance of the class. @@ -29,8 +29,8 @@ namespace SixLabors.ImageSharp.Processing /// defines how colors are repeated. /// public LinearGradientBrush( - Point p1, - Point p2, + PointF p1, + PointF p2, GradientRepetitionMode repetitionMode, params ColorStop[] colorStops) : base(repetitionMode, colorStops) @@ -48,9 +48,9 @@ namespace SixLabors.ImageSharp.Processing /// private sealed class LinearGradientBrushApplicator : GradientBrushApplicatorBase { - private readonly Point start; + private readonly PointF start; - private readonly Point end; + private readonly PointF end; /// /// the vector along the gradient, x component @@ -93,8 +93,8 @@ namespace SixLabors.ImageSharp.Processing /// the graphics options public LinearGradientBrushApplicator( ImageFrame source, - Point start, - Point end, + PointF start, + PointF end, ColorStop[] colorStops, GradientRepetitionMode repetitionMode, GraphicsOptions options) @@ -116,15 +116,15 @@ namespace SixLabors.ImageSharp.Processing this.length = (float)Math.Sqrt(this.alongsSquared); } - protected override float PositionOnGradient(int x, int y) + protected override float PositionOnGradient(float x, float y) { if (this.acrossX == 0) { - return (x - this.start.X) / (float)(this.end.X - this.start.X); + return (x - this.start.X) / (this.end.X - this.start.X); } else if (this.acrossY == 0) { - return (y - this.start.Y) / (float)(this.end.Y - this.start.Y); + return (y - this.start.Y) / (this.end.Y - this.start.Y); } else { diff --git a/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs index 16380fc34..d33d09993 100644 --- a/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.Processing public sealed class RadialGradientBrush : GradientBrushBase where TPixel : struct, IPixel { - private readonly Point center; + private readonly PointF center; private readonly float radius; @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing /// Defines how the colors in the gradient are repeated. /// the color stops as defined in base class. public RadialGradientBrush( - Point center, + PointF center, float radius, GradientRepetitionMode repetitionMode, params ColorStop[] colorStops) @@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing /// private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase { - private readonly Point center; + private readonly PointF center; private readonly float radius; @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing public RadialGradientBrushApplicator( ImageFrame target, GraphicsOptions options, - Point center, + PointF center, float radius, ColorStop[] colorStops, GradientRepetitionMode repetitionMode) @@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing /// The X coordinate of the target pixel. /// The Y coordinate of the target pixel. /// the position on the color gradient. - protected override float PositionOnGradient(int x, int y) + protected override float PositionOnGradient(float x, float y) { float distance = (float)Math.Sqrt(Math.Pow(this.center.X - x, 2) + Math.Pow(this.center.Y - y, 2)); return distance / this.radius; diff --git a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs index 0bab2c079..0f4a98a24 100644 --- a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs @@ -275,10 +275,6 @@ namespace SixLabors.ImageSharp.Tests.Drawing int verticalSign = startY == 0 ? 1 : -1; int horizontalSign = startX == 0 ? 1 : -1; - // check first and last pixel, these are known: - Assert.Equal(red, image[startX, startY]); - Assert.Equal(yellow, image[endX, endY]); - for (int i = 0; i < image.Height; i++) { // it's diagonal, so for any (a, a) on the gradient line, for all (a-x, b+x) - +/- depending on the diagonal direction - must be the same color) diff --git a/tests/Images/External b/tests/Images/External index bc2765fb9..94b5a8e11 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit bc2765fb949d5d4ddba289b29174022bb94646de +Subproject commit 94b5a8e11b33ba62c15d1d03f1b8b721468764f1 From f455dad3f1caf791c59bb8960dc399208956b1fd Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 7 Apr 2019 20:06:27 +0200 Subject: [PATCH 048/223] PixelConversionModifierExtensions.ApplyCompanding() + tests --- .../PixelConversionModifiersExtensions.cs | 18 +++++ .../Transforms/Resize/ResizeProcessor.cs | 7 +- ...PixelConversionModifiersExtensionsTests.cs | 65 +++++++++++++++++++ 3 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelConversionModifiersExtensionsTests.cs diff --git a/src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs b/src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs index bf77f8511..529041481 100644 --- a/src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs +++ b/src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs @@ -5,6 +5,9 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.PixelFormats { + /// + /// Extension and utility methods for . + /// internal static class PixelConversionModifiersExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -16,5 +19,20 @@ namespace SixLabors.ImageSharp.PixelFormats this PixelConversionModifiers modifiers, PixelConversionModifiers removeThis) => modifiers & ~removeThis; + + /// + /// Applies the union of and , + /// if is true, returns unmodified otherwise. + /// + /// + /// and + /// should be always used together! + /// + public static PixelConversionModifiers ApplyCompanding( + this PixelConversionModifiers originalModifiers, + bool compand) => + compand + ? originalModifiers | PixelConversionModifiers.Scale | PixelConversionModifiers.SRgbCompand + : originalModifiers; } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 2c186a276..198427d28 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -236,11 +236,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int sourceHeight = source.Height; - PixelConversionModifiers conversionModifiers = PixelConversionModifiers.Premultiply; - if (this.Compand) - { - conversionModifiers |= PixelConversionModifiers.Scale | PixelConversionModifiers.SRgbCompand; - } + PixelConversionModifiers conversionModifiers = + PixelConversionModifiers.Premultiply.ApplyCompanding(this.Compand); // Interpolate the image using the calculated weights. // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelConversionModifiersExtensionsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelConversionModifiersExtensionsTests.cs new file mode 100644 index 000000000..e98e14fc6 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelConversionModifiersExtensionsTests.cs @@ -0,0 +1,65 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public class PixelConversionModifiersExtensionsTests + { + [Theory] + [InlineData(PixelConversionModifiers.None, PixelConversionModifiers.None, true)] + [InlineData(PixelConversionModifiers.None, PixelConversionModifiers.Premultiply, false)] + [InlineData(PixelConversionModifiers.SRgbCompand, PixelConversionModifiers.Premultiply, false)] + [InlineData( + PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale, + PixelConversionModifiers.Premultiply, + true)] + [InlineData( + PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale, + PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale, + true)] + [InlineData( + PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale, + PixelConversionModifiers.Scale, + true)] + internal void IsDefined( + PixelConversionModifiers baselineModifiers, + PixelConversionModifiers checkModifiers, + bool expected) + { + Assert.Equal(expected, baselineModifiers.IsDefined(checkModifiers)); + } + + [Theory] + [InlineData(PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale | PixelConversionModifiers.SRgbCompand, + PixelConversionModifiers.Scale, PixelConversionModifiers.Premultiply | PixelConversionModifiers.SRgbCompand)] + [InlineData(PixelConversionModifiers.None, PixelConversionModifiers.Premultiply, PixelConversionModifiers.None)] + internal void Remove( + PixelConversionModifiers baselineModifiers, + PixelConversionModifiers toRemove, + PixelConversionModifiers expected) + { + PixelConversionModifiers result = baselineModifiers.Remove(toRemove); + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(PixelConversionModifiers.Premultiply, false, PixelConversionModifiers.Premultiply)] + [InlineData(PixelConversionModifiers.Premultiply, true, PixelConversionModifiers.Premultiply | PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Scale)] + internal void ApplyCompanding( + PixelConversionModifiers baselineModifiers, + bool compand, + PixelConversionModifiers expected) + { + PixelConversionModifiers result = baselineModifiers.ApplyCompanding(compand); + Assert.Equal(expected, result); + } + } +} \ No newline at end of file From 9861084a8def04f0635fe5edf18f73166fe9ca8c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 7 Apr 2019 20:29:50 +0200 Subject: [PATCH 049/223] drop FileTestBase usage in ResizeTests --- .../Processing/Processors/Transforms/ResizeTests.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 034b66ae9..34c984248 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -15,7 +15,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { - public class ResizeTests : FileTestBase + public class ResizeTests { public static readonly string[] CommonTestImages = { TestImages.Png.CalliphoraPartial }; @@ -31,6 +31,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms nameof(KnownResamplers.Lanczos5), }; + private const PixelTypes DefaultPixelType = PixelTypes.Rgba32; + + private const PixelTypes CommonNonDefaultPixelTypes = + PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; + [Theory] [WithFileCollection(nameof(CommonTestImages), nameof(AllResamplerNames), DefaultPixelType, 0.5f, null, null)] [WithFileCollection(nameof(CommonTestImages), nameof(SmokeTestResamplerNames), DefaultPixelType, 0.3f, null, null)] @@ -185,7 +190,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2, KnownResamplers.Bicubic)); // Comparer fights decoder with gif-s. Could not use CompareToReferenceOutput here :( - image.DebugSave(provider, extension: Extensions.Gif); + image.DebugSave(provider, extension: "gif"); } } From 985357cf843c6d2b66079d7f6d0791d68a8da864 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 7 Apr 2019 23:18:13 +0200 Subject: [PATCH 050/223] introduce [WithBasicTestPatternImages] --- .../Processors/Transforms/ResizeTests.cs | 17 +++++ .../WithBasicTestPatternImagesAttribute.cs | 37 +++++++++++ .../BasicTestPatternProvider.cs | 65 +++++++++++++++++++ .../ImageProviders/BlankProvider.cs | 3 + .../ImageProviders/SolidProvider.cs | 3 + .../ImageProviders/TestImageProvider.cs | 6 ++ .../ImageProviders/TestPatternProvider.cs | 5 +- .../Tests/TestImageProviderTests.cs | 14 ++++ 8 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 tests/ImageSharp.Tests/TestUtilities/Attributes/WithBasicTestPatternImagesAttribute.cs create mode 100644 tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 34c984248..7f1f5a26a 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -35,6 +35,23 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms private const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; + + [Theory] + [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32)] + public void Resize_BasicSmall(TestImageProvider provider) + where TPixel : struct, IPixel + { + // Basic test case, very helpful for debugging + // resizing: (15, 12) -> (10, 6) + // kernel dimensions: (3, 4) + + using (Image image = provider.GetImage()) + { + var destSize = new Size(image.Width * 2 / 3, image.Height / 2); + image.Mutate(x => x.Resize(destSize, KnownResamplers.Bicubic, false)); + image.DebugSave(provider); + } + } [Theory] [WithFileCollection(nameof(CommonTestImages), nameof(AllResamplerNames), DefaultPixelType, 0.5f, null, null)] diff --git a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithBasicTestPatternImagesAttribute.cs b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithBasicTestPatternImagesAttribute.cs new file mode 100644 index 000000000..1e4324e04 --- /dev/null +++ b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithBasicTestPatternImagesAttribute.cs @@ -0,0 +1,37 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Reflection; + +namespace SixLabors.ImageSharp.Tests +{ + public class WithBasicTestPatternImagesAttribute : ImageDataAttributeBase + { + public WithBasicTestPatternImagesAttribute(int width, int height, PixelTypes pixelTypes, params object[] additionalParameters) + : this(null, width, height, pixelTypes, additionalParameters) + { + } + + public WithBasicTestPatternImagesAttribute(string memberData, int width, int height, PixelTypes pixelTypes, params object[] additionalParameters) + : base(memberData, pixelTypes, additionalParameters) + { + this.Width = width; + this.Height = height; + } + + /// + /// Gets the width + /// + public int Width { get; } + + /// + /// Gets the height + /// + public int Height { get; } + + protected override string GetFactoryMethodName(MethodInfo testMethod) => "BasicTestPattern"; + + protected override object[] GetFactoryMethodArgs(MethodInfo testMethod, Type factoryType) => new object[] { this.Width, this.Height }; + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs new file mode 100644 index 000000000..47bb22aeb --- /dev/null +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs @@ -0,0 +1,65 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Tests +{ + public abstract partial class TestImageProvider + { + private class BasicTestPatternProvider : BlankProvider + { + public BasicTestPatternProvider(int width, int height) + : base(width, height) + { + } + + /// + /// This parameterless constructor is needed for xUnit deserialization + /// + public BasicTestPatternProvider() + { + } + + public override string SourceFileOrDescription => TestUtils.AsInvariantString($"BasicTestPattern{this.Width}x{this.Height}"); + + public override Image GetImage() + { + var result = new Image(this.Width, this.Height); + + TPixel topLeftColor = NamedColors.Red; + TPixel topRightColor = NamedColors.Green; + TPixel bottomLeftColor = NamedColors.Blue; + + // Transparent purple: + TPixel bottomRightColor = default; + bottomRightColor.FromVector4(new Vector4(1f, 0f, 1f, 0.5f)); + + int midY = this.Height / 2; + int midX = this.Width / 2; + + for (int y = 0; y < midY; y++) + { + Span row = result.GetPixelRowSpan(y); + + row.Slice(0, midX).Fill(topLeftColor); + row.Slice(midX, this.Width-midX).Fill(topRightColor); + } + + for (int y = midY; y < this.Height; y++) + { + Span row = result.GetPixelRowSpan(y); + + row.Slice(0, midX).Fill(bottomLeftColor); + row.Slice(midX, this.Width-midX).Fill(bottomRightColor); + } + + return result; + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs index 7821d0b51..1275e522f 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs @@ -20,6 +20,9 @@ namespace SixLabors.ImageSharp.Tests this.Height = height; } + /// + /// This parameterless constructor is needed for xUnit deserialization + /// public BlankProvider() { this.Width = 100; diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs index d68c37a76..1ff95f60d 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs @@ -35,6 +35,9 @@ namespace SixLabors.ImageSharp.Tests this.a = a; } + /// + /// This parameterless constructor is needed for xUnit deserialization + /// public SolidProvider() : base() { diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs index 5b5e4740a..52f66a78b 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs @@ -44,6 +44,12 @@ namespace SixLabors.ImageSharp.Tests public string MethodName { get; private set; } public string OutputSubfolderName { get; private set; } + public static TestImageProvider BasicTestPattern(int width, + int height, + MethodInfo testMethod = null, + PixelTypes pixelTypeOverride = PixelTypes.Undefined) + => new BasicTestPatternProvider(width, height).Init(testMethod, pixelTypeOverride); + public static TestImageProvider TestPattern( int width, int height, diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs index 17e5369d4..336cdbf11 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Net.Mime; using System.Numerics; using SixLabors.ImageSharp.Memory; @@ -25,8 +26,10 @@ namespace SixLabors.ImageSharp.Tests { } + /// + /// This parameterless constructor is needed for xUnit deserialization + /// public TestPatternProvider() - : base() { } diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index cac7828e9..1bee34f1a 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -325,6 +325,20 @@ namespace SixLabors.ImageSharp.Tests } } + [Theory] + [WithBasicTestPatternImages(50, 100, PixelTypes.Rgba32)] + [WithBasicTestPatternImages(49,17, PixelTypes.Rgba32)] + [WithBasicTestPatternImages(20, 10, PixelTypes.Rgba32)] + public void Use_WithBasicTestPatternImages(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image img = provider.GetImage()) + { + img.DebugSave(provider); + } + } + + public static readonly TheoryData BasicData = new TheoryData() { TestImageProvider.Blank(10, 20), From 8695c398f1faed367499053502406a3e0cb05524 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 8 Apr 2019 00:41:18 +0200 Subject: [PATCH 051/223] drop parallelism in ResizeProcessor for simplicity --- .../Transforms/Resize/ResizeProcessor.cs | 72 ++++++++----------- 1 file changed, 29 insertions(+), 43 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 198427d28..37d0ab413 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; using System.Collections.Generic; using System.Linq; using System.Numerics; @@ -244,63 +245,48 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // First process the columns. Since we are not using multiple threads startY and endY // are the upper and lower bounds of the source rectangle. using (Buffer2D firstPassPixelsTransposed = source.MemoryAllocator.Allocate2D(sourceHeight, width)) + using (IMemoryOwner tempBuffer = source.MemoryAllocator.Allocate(Math.Max(source.Width, width))) { firstPassPixelsTransposed.MemorySource.Clear(); - var processColsRect = new Rectangle(0, 0, source.Width, sourceRectangle.Bottom); + for (int y = 0; y < sourceRectangle.Bottom; y++) + { + Span sourceRow = source.GetPixelRowSpan(y).Slice(sourceX); + Span tempRowSpan = tempBuffer.GetSpan().Slice(sourceX, source.Width - sourceX); - ParallelHelper.IterateRowsWithTempBuffer( - processColsRect, - configuration, - (rows, tempRowBuffer) => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span sourceRow = source.GetPixelRowSpan(y).Slice(sourceX); - Span tempRowSpan = tempRowBuffer.Span.Slice(sourceX); - - PixelOperations.Instance.ToVector4(configuration, sourceRow, tempRowSpan, conversionModifiers); - - ref Vector4 firstPassBaseRef = ref firstPassPixelsTransposed.Span[y]; + PixelOperations.Instance.ToVector4(configuration, sourceRow, tempRowSpan, conversionModifiers); - for (int x = minX; x < maxX; x++) - { - ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - startX); - Unsafe.Add(ref firstPassBaseRef, x * sourceHeight) = kernel.Convolve(tempRowSpan); - } - } - }); + ref Vector4 firstPassBaseRef = ref firstPassPixelsTransposed.Span[y]; - var processRowsRect = Rectangle.FromLTRB(0, minY, width, maxY); + for (int x = minX; x < maxX; x++) + { + ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - startX); + Unsafe.Add(ref firstPassBaseRef, x * sourceHeight) = kernel.Convolve(tempRowSpan); + } + } // Now process the rows. - ParallelHelper.IterateRowsWithTempBuffer( - processRowsRect, - configuration, - (rows, tempRowBuffer) => - { - Span tempRowSpan = tempRowBuffer.Span; + Span tempColSpan = tempBuffer.GetSpan().Slice(0, width); - for (int y = rows.Min; y < rows.Max; y++) - { - // Ensure offsets are normalized for cropping and padding. - ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); + for (int y = minY; y < maxY; y++) + { + // Ensure offsets are normalized for cropping and padding. + ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); - ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempRowSpan); + ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempColSpan); - for (int x = 0; x < width; x++) - { - Span firstPassColumn = firstPassPixelsTransposed.GetRowSpan(x).Slice(sourceY); + for (int x = 0; x < width; x++) + { + Span firstPassColumn = firstPassPixelsTransposed.GetRowSpan(x).Slice(sourceY); - // Destination color components - Unsafe.Add(ref tempRowBase, x) = kernel.Convolve(firstPassColumn); - } + // Destination color components + Unsafe.Add(ref tempRowBase, x) = kernel.Convolve(firstPassColumn); + } - Span targetRowSpan = destination.GetPixelRowSpan(y); + Span targetRowSpan = destination.GetPixelRowSpan(y); - PixelOperations.Instance.FromVector4Destructive(configuration, tempRowSpan, targetRowSpan, conversionModifiers); - } - }); + PixelOperations.Instance.FromVector4Destructive(configuration, tempColSpan, targetRowSpan, conversionModifiers); + } } } From 701343a23e0c6aa45fa9025f06b93224f4b97d83 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 8 Apr 2019 00:59:24 +0200 Subject: [PATCH 052/223] ResizeRectangle -> TargetRectangle --- .../Transforms/Resize/ResizeProcessor.cs | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 37d0ab413..cb1ab2d54 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.Sampler = options.Sampler; this.Width = size.Width; this.Height = size.Height; - this.ResizeRectangle = rectangle; + this.TargetRectangle = rectangle; this.Compand = options.Compand; } @@ -89,11 +89,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The target width. /// The target height. /// The source image size - /// + /// /// The structure that specifies the portion of the target image object to draw to. /// /// Whether to compress or expand individual pixel color values on processing. - public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize, Rectangle resizeRectangle, bool compand) + public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize, Rectangle targetRectangle, bool compand) { Guard.NotNull(sampler, nameof(sampler)); @@ -104,13 +104,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms if (width == 0 && height > 0) { width = (int)MathF.Max(min, MathF.Round(sourceSize.Width * height / (float)sourceSize.Height)); - resizeRectangle.Width = width; + targetRectangle.Width = width; } if (height == 0 && width > 0) { height = (int)MathF.Max(min, MathF.Round(sourceSize.Height * width / (float)sourceSize.Width)); - resizeRectangle.Height = height; + targetRectangle.Height = height; } Guard.MustBeGreaterThan(width, 0, nameof(width)); @@ -119,7 +119,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.Sampler = sampler; this.Width = width; this.Height = height; - this.ResizeRectangle = resizeRectangle; + this.TargetRectangle = targetRectangle; this.Compand = compand; } @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// Gets the resize rectangle. /// - public Rectangle ResizeRectangle { get; } + public Rectangle TargetRectangle { get; } /// /// Gets a value indicating whether to compress or expand individual pixel color values on processing. @@ -167,13 +167,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms MemoryAllocator memoryAllocator = source.GetMemoryAllocator(); this.horizontalKernelMap = ResizeKernelMap.Calculate( this.Sampler, - this.ResizeRectangle.Width, + this.TargetRectangle.Width, sourceRectangle.Width, memoryAllocator); this.verticalKernelMap = ResizeKernelMap.Calculate( this.Sampler, - this.ResizeRectangle.Height, + this.TargetRectangle.Height, sourceRectangle.Height, memoryAllocator); } @@ -183,7 +183,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) { // Handle resize dimensions identical to the original - if (source.Width == destination.Width && source.Height == destination.Height && sourceRectangle == this.ResizeRectangle) + if (source.Width == destination.Width && source.Height == destination.Height && sourceRectangle == this.TargetRectangle) { // The cloned will be blank here copy all the pixel data over source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); @@ -194,10 +194,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int height = this.Height; int sourceX = sourceRectangle.X; int sourceY = sourceRectangle.Y; - int startY = this.ResizeRectangle.Y; - int endY = this.ResizeRectangle.Bottom; - int startX = this.ResizeRectangle.X; - int endX = this.ResizeRectangle.Right; + int startY = this.TargetRectangle.Y; + int endY = this.TargetRectangle.Bottom; + int startX = this.TargetRectangle.X; + int endX = this.TargetRectangle.Right; int minX = Math.Max(0, startX); int maxX = Math.Min(width, endX); @@ -209,8 +209,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); // Scaling factors - float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width; - float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height; + float widthFactor = sourceRectangle.Width / (float)this.TargetRectangle.Width; + float heightFactor = sourceRectangle.Height / (float)this.TargetRectangle.Height; ParallelHelper.IterateRows( workingRect, From 48bac7b3340dbe49aa9b0823468142daf82b0bb0 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Fri, 12 Apr 2019 23:37:17 -0500 Subject: [PATCH 053/223] Update metadata names (#879) --- .../Common/Helpers/UnitConverter.cs | 4 +- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 26 ++-- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 26 ++-- src/ImageSharp/Formats/Bmp/BmpFormat.cs | 4 +- src/ImageSharp/Formats/Bmp/BmpMetaData.cs | 12 +- src/ImageSharp/Formats/Gif/GifDecoder.cs | 2 +- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 34 ++--- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 60 ++++---- src/ImageSharp/Formats/Gif/GifFormat.cs | 6 +- .../Formats/Gif/GifFrameMetaData.cs | 12 +- src/ImageSharp/Formats/Gif/GifMetaData.cs | 12 +- .../Formats/Gif/IGifDecoderOptions.cs | 2 +- src/ImageSharp/Formats/IImageFormat.cs | 24 ++-- .../Jpeg/Components/Decoder/JFifMarker.cs | 2 +- .../Formats/Jpeg/JpegDecoderCore.cs | 44 +++--- .../Formats/Jpeg/JpegEncoderCore.cs | 30 ++-- src/ImageSharp/Formats/Jpeg/JpegFormat.cs | 4 +- src/ImageSharp/Formats/Jpeg/JpegMetaData.cs | 12 +- .../Formats/Png/Chunks/PhysicalChunkData.cs | 4 +- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 128 +++++++++--------- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 54 ++++---- src/ImageSharp/Formats/Png/PngFormat.cs | 4 +- src/ImageSharp/Formats/Png/PngMetaData.cs | 12 +- src/ImageSharp/IImageInfo.cs | 4 +- src/ImageSharp/Image.Decode.cs | 6 +- src/ImageSharp/Image.WrapMemory.cs | 18 +-- src/ImageSharp/ImageFrameCollection.cs | 4 +- src/ImageSharp/ImageFrame{TPixel}.cs | 42 +++--- src/ImageSharp/ImageInfo.cs | 10 +- src/ImageSharp/Image{TPixel}.cs | 28 ++-- src/ImageSharp/MetaData/FrameDecodingMode.cs | 2 +- src/ImageSharp/MetaData/ImageFrameMetaData.cs | 42 +++--- src/ImageSharp/MetaData/ImageMetaData.cs | 44 +++--- src/ImageSharp/MetaData/ImageProperty.cs | 2 +- .../MetaData/PixelResolutionUnit.cs | 2 +- .../MetaData/Profiles/Exif/ExifConstants.cs | 2 +- .../MetaData/Profiles/Exif/ExifDataType.cs | 2 +- .../MetaData/Profiles/Exif/ExifParts.cs | 2 +- .../MetaData/Profiles/Exif/ExifProfile.cs | 12 +- .../MetaData/Profiles/Exif/ExifReader.cs | 2 +- .../MetaData/Profiles/Exif/ExifTag.cs | 2 +- .../Exif/ExifTagDescriptionAttribute.cs | 2 +- .../MetaData/Profiles/Exif/ExifTags.cs | 4 +- .../MetaData/Profiles/Exif/ExifValue.cs | 2 +- .../MetaData/Profiles/Exif/ExifWriter.cs | 2 +- .../Profiles/ICC/Curves/IccCurveSegment.cs | 2 +- .../ICC/Curves/IccFormulaCurveElement.cs | 2 +- .../ICC/Curves/IccOneDimensionalCurve.cs | 2 +- .../Profiles/ICC/Curves/IccParametricCurve.cs | 2 +- .../Profiles/ICC/Curves/IccResponseCurve.cs | 2 +- .../ICC/Curves/IccSampledCurveElement.cs | 2 +- .../ICC/DataReader/IccDataReader.Curves.cs | 2 +- .../ICC/DataReader/IccDataReader.Lut.cs | 2 +- .../ICC/DataReader/IccDataReader.Matrix.cs | 2 +- .../IccDataReader.MultiProcessElement.cs | 2 +- .../DataReader/IccDataReader.NonPrimitives.cs | 2 +- .../DataReader/IccDataReader.Primitives.cs | 2 +- .../DataReader/IccDataReader.TagDataEntry.cs | 2 +- .../Profiles/ICC/DataReader/IccDataReader.cs | 2 +- .../ICC/DataWriter/IccDataWriter.Curves.cs | 2 +- .../ICC/DataWriter/IccDataWriter.Lut.cs | 2 +- .../ICC/DataWriter/IccDataWriter.Matrix.cs | 2 +- .../IccDataWriter.MultiProcessElement.cs | 2 +- .../DataWriter/IccDataWriter.NonPrimitives.cs | 2 +- .../DataWriter/IccDataWriter.Primitives.cs | 2 +- .../DataWriter/IccDataWriter.TagDataEntry.cs | 2 +- .../Profiles/ICC/DataWriter/IccDataWriter.cs | 2 +- .../Profiles/ICC/Enums/IccClutDataType.cs | 2 +- .../Profiles/ICC/Enums/IccColorSpaceType.cs | 2 +- .../Profiles/ICC/Enums/IccColorantEncoding.cs | 2 +- .../ICC/Enums/IccCurveMeasurementEncodings.cs | 2 +- .../ICC/Enums/IccCurveSegmentSignature.cs | 2 +- .../Profiles/ICC/Enums/IccDataType.cs | 2 +- .../Profiles/ICC/Enums/IccDeviceAttribute.cs | 2 +- .../Profiles/ICC/Enums/IccFormulaCurveType.cs | 2 +- .../ICC/Enums/IccMeasurementGeometry.cs | 2 +- .../Enums/IccMultiProcessElementSignature.cs | 2 +- .../ICC/Enums/IccParametricCurveType.cs | 2 +- .../ICC/Enums/IccPrimaryPlatformType.cs | 2 +- .../Profiles/ICC/Enums/IccProfileClass.cs | 2 +- .../Profiles/ICC/Enums/IccProfileFlag.cs | 2 +- .../Profiles/ICC/Enums/IccProfileTag.cs | 2 +- .../Profiles/ICC/Enums/IccRenderingIntent.cs | 2 +- .../Profiles/ICC/Enums/IccScreeningFlag.cs | 2 +- .../ICC/Enums/IccScreeningSpotType.cs | 2 +- .../Profiles/ICC/Enums/IccSignatureName.cs | 2 +- .../ICC/Enums/IccStandardIlluminant.cs | 2 +- .../Profiles/ICC/Enums/IccStandardObserver.cs | 2 +- .../Profiles/ICC/Enums/IccTypeSignature.cs | 2 +- .../Exceptions/InvalidIccProfileException.cs | 2 +- .../MetaData/Profiles/ICC/IccProfile.cs | 2 +- .../MetaData/Profiles/ICC/IccProfileHeader.cs | 2 +- .../MetaData/Profiles/ICC/IccReader.cs | 2 +- .../MetaData/Profiles/ICC/IccTagDataEntry.cs | 2 +- .../MetaData/Profiles/ICC/IccWriter.cs | 2 +- .../IccBAcsProcessElement.cs | 2 +- .../IccClutProcessElement.cs | 2 +- .../IccCurveSetProcessElement.cs | 2 +- .../IccEAcsProcessElement.cs | 2 +- .../IccMatrixProcessElement.cs | 2 +- .../IccMultiProcessElement.cs | 2 +- .../IccChromaticityTagDataEntry.cs | 2 +- .../IccColorantOrderTagDataEntry.cs | 2 +- .../IccColorantTableTagDataEntry.cs | 2 +- .../TagDataEntries/IccCrdInfoTagDataEntry.cs | 2 +- .../TagDataEntries/IccCurveTagDataEntry.cs | 2 +- .../ICC/TagDataEntries/IccDataTagDataEntry.cs | 2 +- .../TagDataEntries/IccDateTimeTagDataEntry.cs | 2 +- .../IccFix16ArrayTagDataEntry.cs | 2 +- .../TagDataEntries/IccLut16TagDataEntry.cs | 2 +- .../ICC/TagDataEntries/IccLut8TagDataEntry.cs | 2 +- .../TagDataEntries/IccLutAToBTagDataEntry.cs | 2 +- .../TagDataEntries/IccLutBToATagDataEntry.cs | 2 +- .../IccMeasurementTagDataEntry.cs | 2 +- .../IccMultiLocalizedUnicodeTagDataEntry.cs | 2 +- .../IccMultiProcessElementsTagDataEntry.cs | 2 +- .../IccNamedColor2TagDataEntry.cs | 2 +- .../IccParametricCurveTagDataEntry.cs | 2 +- .../IccProfileSequenceDescTagDataEntry.cs | 2 +- ...ccProfileSequenceIdentifierTagDataEntry.cs | 2 +- .../IccResponseCurveSet16TagDataEntry.cs | 2 +- .../IccScreeningTagDataEntry.cs | 2 +- .../IccSignatureTagDataEntry.cs | 2 +- .../IccTextDescriptionTagDataEntry.cs | 2 +- .../ICC/TagDataEntries/IccTextTagDataEntry.cs | 2 +- .../IccUFix16ArrayTagDataEntry.cs | 2 +- .../IccUInt16ArrayTagDataEntry.cs | 2 +- .../IccUInt32ArrayTagDataEntry.cs | 2 +- .../IccUInt64ArrayTagDataEntry.cs | 2 +- .../IccUInt8ArrayTagDataEntry.cs | 2 +- .../TagDataEntries/IccUcrBgTagDataEntry.cs | 2 +- .../TagDataEntries/IccUnknownTagDataEntry.cs | 2 +- .../IccViewingConditionsTagDataEntry.cs | 2 +- .../ICC/TagDataEntries/IccXyzTagDataEntry.cs | 2 +- .../MetaData/Profiles/ICC/Various/IccClut.cs | 2 +- .../ICC/Various/IccColorantTableEntry.cs | 2 +- .../ICC/Various/IccLocalizedString.cs | 2 +- .../MetaData/Profiles/ICC/Various/IccLut.cs | 2 +- .../Profiles/ICC/Various/IccNamedColor.cs | 2 +- .../Profiles/ICC/Various/IccPositionNumber.cs | 2 +- .../ICC/Various/IccProfileDescription.cs | 2 +- .../Profiles/ICC/Various/IccProfileId.cs | 2 +- .../Various/IccProfileSequenceIdentifier.cs | 2 +- .../Profiles/ICC/Various/IccResponseNumber.cs | 2 +- .../ICC/Various/IccScreeningChannel.cs | 2 +- .../Profiles/ICC/Various/IccTagTableEntry.cs | 2 +- .../Profiles/ICC/Various/IccVersion.cs | 2 +- .../Transforms/AffineTransformProcessor.cs | 4 +- .../Transforms/AutoOrientProcessor.cs | 10 +- .../Processors/Transforms/CropProcessor.cs | 4 +- .../ProjectiveTransformProcessor.cs | 4 +- .../Transforms/Resize/ResizeProcessor.cs | 4 +- .../Processors/Transforms/RotateProcessor.cs | 4 +- .../Transforms/TransformProcessorHelpers.cs | 4 +- .../Formats/Bmp/BmpDecoderTests.cs | 4 +- .../Formats/Bmp/BmpEncoderTests.cs | 6 +- .../Formats/Bmp/BmpMetaDataTests.cs | 4 +- .../Formats/GeneralFormatTests.cs | 4 +- .../Formats/Gif/GifDecoderTests.cs | 20 +-- .../Formats/Gif/GifEncoderTests.cs | 34 ++--- .../Formats/Gif/GifFrameMetaDataTests.cs | 4 +- .../Formats/Gif/GifMetaDataTests.cs | 4 +- .../Formats/Jpg/JFifMarkerTests.cs | 2 +- .../Formats/Jpg/JpegDecoderTests.MetaData.cs | 34 ++--- .../Formats/Jpg/JpegEncoderTests.cs | 6 +- .../Formats/Jpg/JpegMetaDataTests.cs | 4 +- .../Formats/Png/PngDecoderTests.cs | 18 +-- .../Formats/Png/PngEncoderTests.cs | 10 +- .../Formats/Png/PngMetaDataTests.cs | 4 +- .../Image/ImageTests.WrapMemory.cs | 6 +- tests/ImageSharp.Tests/Image/ImageTests.cs | 6 +- tests/ImageSharp.Tests/ImageInfoTests.cs | 6 +- .../MetaData/ImageFrameMetaDataTests.cs | 16 +-- .../MetaData/ImageMetaDataTests.cs | 32 ++--- .../MetaData/ImagePropertyTests.cs | 2 +- .../Profiles/Exif/ExifProfileTests.cs | 104 +++++++------- .../MetaData/Profiles/Exif/ExifReaderTests.cs | 2 +- .../Exif/ExifTagDescriptionAttributeTests.cs | 2 +- .../MetaData/Profiles/Exif/ExifValueTests.cs | 4 +- .../DataReader/IccDataReader.CurvesTests.cs | 2 +- .../ICC/DataReader/IccDataReader.LutTests.cs | 2 +- .../DataReader/IccDataReader.MatrixTests.cs | 2 +- .../IccDataReader.MultiProcessElementTests.cs | 2 +- .../IccDataReader.NonPrimitivesTests.cs | 2 +- .../IccDataReader.PrimitivesTests.cs | 2 +- .../IccDataReader.TagDataEntryTests.cs | 2 +- .../ICC/DataReader/IccDataReaderTests.cs | 2 +- .../DataWriter/IccDataWriter.CurvesTests.cs | 2 +- .../ICC/DataWriter/IccDataWriter.LutTests.cs | 2 +- .../DataWriter/IccDataWriter.MatrixTests.cs | 2 +- .../IccDataWriter.MultiProcessElementTests.cs | 2 +- .../IccDataWriter.NonPrimitivesTests.cs | 2 +- .../IccDataWriter.PrimitivesTests.cs | 2 +- .../IccDataWriter.TagDataEntryTests.cs | 2 +- .../ICC/DataWriter/IccDataWriterTests.cs | 2 +- .../MetaData/Profiles/ICC/IccProfileTests.cs | 2 +- .../MetaData/Profiles/ICC/IccReaderTests.cs | 2 +- .../MetaData/Profiles/ICC/IccWriterTests.cs | 2 +- .../Profiles/ICC/Various/IccProfileIdTests.cs | 2 +- .../Processors/Transforms/AutoOrientTests.cs | 8 +- .../Transforms/TransformsHelpersTest.cs | 4 +- .../TestDataIcc/IccTestDataCurves.cs | 2 +- .../TestDataIcc/IccTestDataLut.cs | 2 +- .../IccTestDataMultiProcessElements.cs | 2 +- .../TestDataIcc/IccTestDataNonPrimitives.cs | 2 +- .../TestDataIcc/IccTestDataProfiles.cs | 2 +- .../TestDataIcc/IccTestDataTagDataEntry.cs | 2 +- .../SystemDrawingReferenceDecoder.cs | 4 +- 208 files changed, 699 insertions(+), 699 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/UnitConverter.cs b/src/ImageSharp/Common/Helpers/UnitConverter.cs index c8b25bf56..75dbb032c 100644 --- a/src/ImageSharp/Common/Helpers/UnitConverter.cs +++ b/src/ImageSharp/Common/Helpers/UnitConverter.cs @@ -2,8 +2,8 @@ // Licensed under the Apache License, Version 2.0. using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.MetaData; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; namespace SixLabors.ImageSharp.Common.Helpers { diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index d33ada286..b52c3754e 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -9,7 +9,7 @@ using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; @@ -66,12 +66,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// The metadata. /// - private ImageMetaData metaData; + private ImageMetadata metadata; /// /// The bmp specific metadata. /// - private BmpMetaData bmpMetaData; + private BmpMetadata bmpMetadata; /// /// The file header containing general information. @@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp { int bytesPerColorMapEntry = this.ReadImageHeaders(stream, out bool inverted, out byte[] palette); - var image = new Image(this.configuration, this.infoHeader.Width, this.infoHeader.Height, this.metaData); + var image = new Image(this.configuration, this.infoHeader.Width, this.infoHeader.Height, this.metadata); Buffer2D pixels = image.GetRootFramePixelBuffer(); @@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp case BmpCompression.RGB: if (this.infoHeader.BitsPerPixel == 32) { - if (this.bmpMetaData.InfoHeaderType == BmpInfoHeaderType.WinVersion3) + if (this.bmpMetadata.InfoHeaderType == BmpInfoHeaderType.WinVersion3) { this.ReadRgb32Slow(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); } @@ -188,7 +188,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp public IImageInfo Identify(Stream stream) { this.ReadImageHeaders(stream, out _, out _); - return new ImageInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), this.infoHeader.Width, this.infoHeader.Height, this.metaData); + return new ImageInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), this.infoHeader.Width, this.infoHeader.Height, this.metadata); } /// @@ -999,7 +999,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp } // Resolution is stored in PPM. - var meta = new ImageMetaData + var meta = new ImageMetadata { ResolutionUnits = PixelResolutionUnit.PixelsPerMeter }; @@ -1011,21 +1011,21 @@ namespace SixLabors.ImageSharp.Formats.Bmp else { // Convert default metadata values to PPM. - meta.HorizontalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetaData.DefaultHorizontalResolution)); - meta.VerticalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetaData.DefaultVerticalResolution)); + meta.HorizontalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetadata.DefaultHorizontalResolution)); + meta.VerticalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetadata.DefaultVerticalResolution)); } - this.metaData = meta; + this.metadata = meta; short bitsPerPixel = this.infoHeader.BitsPerPixel; - this.bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance); - this.bmpMetaData.InfoHeaderType = infoHeaderType; + this.bmpMetadata = this.metadata.GetFormatMetadata(BmpFormat.Instance); + this.bmpMetadata.InfoHeaderType = infoHeaderType; // We can only encode at these bit rates so far. if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24) || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel32)) { - this.bmpMetaData.BitsPerPixel = (BmpBitsPerPixel)bitsPerPixel; + this.bmpMetadata.BitsPerPixel = (BmpBitsPerPixel)bitsPerPixel; } // skip the remaining header because we can't read those parts diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 27a38bc0d..ad526f668 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -7,7 +7,7 @@ using System.IO; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; @@ -73,9 +73,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp Guard.NotNull(stream, nameof(stream)); this.configuration = image.GetConfiguration(); - ImageMetaData metaData = image.MetaData; - BmpMetaData bmpMetaData = metaData.GetFormatMetaData(BmpFormat.Instance); - this.bitsPerPixel = this.bitsPerPixel ?? bmpMetaData.BitsPerPixel; + ImageMetadata metadata = image.Metadata; + BmpMetadata bmpMetadata = metadata.GetFormatMetadata(BmpFormat.Instance); + this.bitsPerPixel = this.bitsPerPixel ?? bmpMetadata.BitsPerPixel; short bpp = (short)this.bitsPerPixel; int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32); @@ -85,27 +85,27 @@ namespace SixLabors.ImageSharp.Formats.Bmp int hResolution = 0; int vResolution = 0; - if (metaData.ResolutionUnits != PixelResolutionUnit.AspectRatio) + if (metadata.ResolutionUnits != PixelResolutionUnit.AspectRatio) { - if (metaData.HorizontalResolution > 0 && metaData.VerticalResolution > 0) + if (metadata.HorizontalResolution > 0 && metadata.VerticalResolution > 0) { - switch (metaData.ResolutionUnits) + switch (metadata.ResolutionUnits) { case PixelResolutionUnit.PixelsPerInch: - hResolution = (int)Math.Round(UnitConverter.InchToMeter(metaData.HorizontalResolution)); - vResolution = (int)Math.Round(UnitConverter.InchToMeter(metaData.VerticalResolution)); + hResolution = (int)Math.Round(UnitConverter.InchToMeter(metadata.HorizontalResolution)); + vResolution = (int)Math.Round(UnitConverter.InchToMeter(metadata.VerticalResolution)); break; case PixelResolutionUnit.PixelsPerCentimeter: - hResolution = (int)Math.Round(UnitConverter.CmToMeter(metaData.HorizontalResolution)); - vResolution = (int)Math.Round(UnitConverter.CmToMeter(metaData.VerticalResolution)); + hResolution = (int)Math.Round(UnitConverter.CmToMeter(metadata.HorizontalResolution)); + vResolution = (int)Math.Round(UnitConverter.CmToMeter(metadata.VerticalResolution)); break; case PixelResolutionUnit.PixelsPerMeter: - hResolution = (int)Math.Round(metaData.HorizontalResolution); - vResolution = (int)Math.Round(metaData.VerticalResolution); + hResolution = (int)Math.Round(metadata.HorizontalResolution); + vResolution = (int)Math.Round(metadata.VerticalResolution); break; } diff --git a/src/ImageSharp/Formats/Bmp/BmpFormat.cs b/src/ImageSharp/Formats/Bmp/BmpFormat.cs index a5eaab8eb..056fbe840 100644 --- a/src/ImageSharp/Formats/Bmp/BmpFormat.cs +++ b/src/ImageSharp/Formats/Bmp/BmpFormat.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Registers the image encoders, decoders and mime type detectors for the bmp format. /// - public sealed class BmpFormat : IImageFormat + public sealed class BmpFormat : IImageFormat { private BmpFormat() { @@ -32,6 +32,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp public IEnumerable FileExtensions => BmpConstants.FileExtensions; /// - public BmpMetaData CreateDefaultFormatMetaData() => new BmpMetaData(); + public BmpMetadata CreateDefaultFormatMetadata() => new BmpMetadata(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs index 2d8685617..83d4eefe4 100644 --- a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs +++ b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs @@ -6,20 +6,20 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Provides Bmp specific metadata information for the image. /// - public class BmpMetaData : IDeepCloneable + public class BmpMetadata : IDeepCloneable { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public BmpMetaData() + public BmpMetadata() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The metadata to create an instance from. - private BmpMetaData(BmpMetaData other) + private BmpMetadata(BmpMetadata other) { this.BitsPerPixel = other.BitsPerPixel; this.InfoHeaderType = other.InfoHeaderType; @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24; /// - public IDeepCloneable DeepClone() => new BmpMetaData(this); + public IDeepCloneable DeepClone() => new BmpMetadata(this); // TODO: Colors used once we support encoding palette bmps. } diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs index 42c76d640..6af75f2d0 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoder.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs @@ -3,7 +3,7 @@ using System.IO; using System.Text; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Gif diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index bfa91416a..e16ecb42e 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -8,7 +8,7 @@ using System.Runtime.InteropServices; using System.Text; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; using SixLabors.Primitives; @@ -63,12 +63,12 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The abstract metadata. /// - private ImageMetaData metaData; + private ImageMetadata metadata; /// /// The gif specific metadata. /// - private GifMetaData gifMetaData; + private GifMetadata gifMetadata; /// /// Initializes a new instance of the class. @@ -223,7 +223,7 @@ namespace SixLabors.ImageSharp.Formats.Gif new PixelTypeInfo(this.logicalScreenDescriptor.BitsPerPixel), this.logicalScreenDescriptor.Width, this.logicalScreenDescriptor.Height, - this.metaData); + this.metadata); } /// @@ -276,7 +276,7 @@ namespace SixLabors.ImageSharp.Formats.Gif if (subBlockSize == GifConstants.NetscapeLoopingSubBlockSize) { this.stream.Read(this.buffer, 0, GifConstants.NetscapeLoopingSubBlockSize); - this.gifMetaData.RepeatCount = GifNetscapeLoopingApplicationExtension.Parse(this.buffer.AsSpan(1)).RepeatCount; + this.gifMetadata.RepeatCount = GifNetscapeLoopingApplicationExtension.Parse(this.buffer.AsSpan(1)).RepeatCount; this.stream.Skip(1); // Skip the terminator. return; } @@ -334,7 +334,7 @@ namespace SixLabors.ImageSharp.Formats.Gif { this.stream.Read(commentsBuffer.Array, 0, length); string comments = this.TextEncoding.GetString(commentsBuffer.Array, 0, length); - this.metaData.Properties.Add(new ImageProperty(GifConstants.Comments, comments)); + this.metadata.Properties.Add(new ImageProperty(GifConstants.Comments, comments)); } } } @@ -416,9 +416,9 @@ namespace SixLabors.ImageSharp.Formats.Gif if (previousFrame is null) { // This initializes the image to become fully transparent because the alpha channel is zero. - image = new Image(this.configuration, imageWidth, imageHeight, this.metaData); + image = new Image(this.configuration, imageWidth, imageHeight, this.metadata); - this.SetFrameMetaData(image.Frames.RootFrame.MetaData); + this.SetFrameMetadata(image.Frames.RootFrame.Metadata); imageFrame = image.Frames.RootFrame; } @@ -431,7 +431,7 @@ namespace SixLabors.ImageSharp.Formats.Gif currentFrame = image.Frames.AddFrame(previousFrame); // This clones the frame and adds it the collection - this.SetFrameMetaData(currentFrame.MetaData); + this.SetFrameMetadata(currentFrame.Metadata); imageFrame = currentFrame; @@ -549,11 +549,11 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Sets the frames metadata. /// - /// The meta data. + /// The metadata. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void SetFrameMetaData(ImageFrameMetaData meta) + private void SetFrameMetadata(ImageFrameMetadata meta) { - GifFrameMetaData gifMeta = meta.GetFormatMetaData(GifFormat.Instance); + GifFrameMetadata gifMeta = meta.GetFormatMetadata(GifFormat.Instance); if (this.graphicsControlExtension.DelayTime > 0) { gifMeta.FrameDelay = this.graphicsControlExtension.DelayTime; @@ -586,7 +586,7 @@ namespace SixLabors.ImageSharp.Formats.Gif this.stream.Skip(6); this.ReadLogicalScreenDescriptor(); - var meta = new ImageMetaData(); + var meta = new ImageMetadata(); // The Pixel Aspect Ratio is defined to be the quotient of the pixel's // width over its height. The value range in this field allows @@ -614,16 +614,16 @@ namespace SixLabors.ImageSharp.Formats.Gif } } - this.metaData = meta; - this.gifMetaData = meta.GetFormatMetaData(GifFormat.Instance); - this.gifMetaData.ColorTableMode = this.logicalScreenDescriptor.GlobalColorTableFlag + this.metadata = meta; + this.gifMetadata = meta.GetFormatMetadata(GifFormat.Instance); + this.gifMetadata.ColorTableMode = this.logicalScreenDescriptor.GlobalColorTableFlag ? GifColorTableMode.Global : GifColorTableMode.Local; if (this.logicalScreenDescriptor.GlobalColorTableFlag) { int globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3; - this.gifMetaData.GlobalColorTableLength = globalColorTableLength; + this.gifMetadata.GlobalColorTableLength = globalColorTableLength; this.globalColorTable = this.MemoryAllocator.AllocateManagedByteBuffer(globalColorTableLength, AllocationOptions.Clean); diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index c8580144a..e5a5463eb 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -10,7 +10,7 @@ using System.Text; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.Memory; @@ -58,9 +58,9 @@ namespace SixLabors.ImageSharp.Formats.Gif private int bitDepth; /// - /// Gif specific meta data. + /// Gif specific metadata. /// - private GifMetaData gifMetaData; + private GifMetadata gifMetadata; /// /// Initializes a new instance of the class. @@ -89,9 +89,9 @@ namespace SixLabors.ImageSharp.Formats.Gif this.configuration = image.GetConfiguration(); - ImageMetaData metaData = image.MetaData; - this.gifMetaData = metaData.GetFormatMetaData(GifFormat.Instance); - this.colorTableMode = this.colorTableMode ?? this.gifMetaData.ColorTableMode; + ImageMetadata metadata = image.Metadata; + this.gifMetadata = metadata.GetFormatMetadata(GifFormat.Instance); + this.colorTableMode = this.colorTableMode ?? this.gifMetadata.ColorTableMode; bool useGlobalTable = this.colorTableMode == GifColorTableMode.Global; // Quantize the image returning a palette. @@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Formats.Gif // Write the LSD. int index = this.GetTransparentIndex(quantized); - this.WriteLogicalScreenDescriptor(metaData, image.Width, image.Height, index, useGlobalTable, stream); + this.WriteLogicalScreenDescriptor(metadata, image.Width, image.Height, index, useGlobalTable, stream); if (useGlobalTable) { @@ -114,12 +114,12 @@ namespace SixLabors.ImageSharp.Formats.Gif } // Write the comments. - this.WriteComments(metaData, stream); + this.WriteComments(metadata, stream); // Write application extension to allow additional frames. if (image.Frames.Count > 1) { - this.WriteApplicationExtension(stream, this.gifMetaData.RepeatCount); + this.WriteApplicationExtension(stream, this.gifMetadata.RepeatCount); } if (useGlobalTable) @@ -147,9 +147,9 @@ namespace SixLabors.ImageSharp.Formats.Gif for (int i = 0; i < image.Frames.Count; i++) { ImageFrame frame = image.Frames[i]; - ImageFrameMetaData metaData = frame.MetaData; - GifFrameMetaData frameMetaData = metaData.GetFormatMetaData(GifFormat.Instance); - this.WriteGraphicalControlExtension(frameMetaData, transparencyIndex, stream); + ImageFrameMetadata metadata = frame.Metadata; + GifFrameMetadata frameMetadata = metadata.GetFormatMetadata(GifFormat.Instance); + this.WriteGraphicalControlExtension(frameMetadata, transparencyIndex, stream); this.WriteImageDescriptor(frame, false, stream); if (i == 0) @@ -170,20 +170,20 @@ namespace SixLabors.ImageSharp.Formats.Gif where TPixel : struct, IPixel { ImageFrame previousFrame = null; - GifFrameMetaData previousMeta = null; + GifFrameMetadata previousMeta = null; foreach (ImageFrame frame in image.Frames) { - ImageFrameMetaData metaData = frame.MetaData; - GifFrameMetaData frameMetaData = metaData.GetFormatMetaData(GifFormat.Instance); + ImageFrameMetadata metadata = frame.Metadata; + GifFrameMetadata frameMetadata = metadata.GetFormatMetadata(GifFormat.Instance); if (quantized is null) { // Allow each frame to be encoded at whatever color depth the frame designates if set. - if (previousFrame != null && previousMeta.ColorTableLength != frameMetaData.ColorTableLength - && frameMetaData.ColorTableLength > 0) + if (previousFrame != null && previousMeta.ColorTableLength != frameMetadata.ColorTableLength + && frameMetadata.ColorTableLength > 0) { quantized = this.quantizer.CreateFrameQuantizer( image.GetConfiguration(), - frameMetaData.ColorTableLength).QuantizeFrame(frame); + frameMetadata.ColorTableLength).QuantizeFrame(frame); } else { @@ -193,7 +193,7 @@ namespace SixLabors.ImageSharp.Formats.Gif } this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8); - this.WriteGraphicalControlExtension(frameMetaData, this.GetTransparentIndex(quantized), stream); + this.WriteGraphicalControlExtension(frameMetadata, this.GetTransparentIndex(quantized), stream); this.WriteImageDescriptor(frame, true, stream); this.WriteColorTable(quantized, stream); this.WriteImageData(quantized, stream); @@ -201,7 +201,7 @@ namespace SixLabors.ImageSharp.Formats.Gif quantized?.Dispose(); quantized = null; // So next frame can regenerate it previousFrame = frame; - previousMeta = frameMetaData; + previousMeta = frameMetadata; } } @@ -250,14 +250,14 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Writes the logical screen descriptor to the stream. /// - /// The image metadata. + /// The image metadata. /// The image width. /// The image height. /// The transparency index to set the default background index to. /// Whether to use a global or local color table. /// The stream to write to. private void WriteLogicalScreenDescriptor( - ImageMetaData metaData, + ImageMetadata metadata, int width, int height, int transparencyIndex, @@ -277,10 +277,10 @@ namespace SixLabors.ImageSharp.Formats.Gif // Aspect Ratio = (Pixel Aspect Ratio + 15) / 64 byte ratio = 0; - if (metaData.ResolutionUnits == PixelResolutionUnit.AspectRatio) + if (metadata.ResolutionUnits == PixelResolutionUnit.AspectRatio) { - double hr = metaData.HorizontalResolution; - double vr = metaData.VerticalResolution; + double hr = metadata.HorizontalResolution; + double vr = metadata.VerticalResolution; if (hr != vr) { if (hr > vr) @@ -326,7 +326,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The metadata to be extract the comment data. /// The stream to write to. - private void WriteComments(ImageMetaData metadata, Stream stream) + private void WriteComments(ImageMetadata metadata, Stream stream) { if (!metadata.TryGetProperty(GifConstants.Comments, out ImageProperty property) || string.IsNullOrEmpty(property.Value)) @@ -350,18 +350,18 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Writes the graphics control extension to the stream. /// - /// The metadata of the image or frame. + /// The metadata of the image or frame. /// The index of the color in the color palette to make transparent. /// The stream to write to. - private void WriteGraphicalControlExtension(GifFrameMetaData metaData, int transparencyIndex, Stream stream) + private void WriteGraphicalControlExtension(GifFrameMetadata metadata, int transparencyIndex, Stream stream) { byte packedValue = GifGraphicControlExtension.GetPackedValue( - disposalMethod: metaData.DisposalMethod, + disposalMethod: metadata.DisposalMethod, transparencyFlag: transparencyIndex > -1); var extension = new GifGraphicControlExtension( packed: packedValue, - delayTime: (ushort)metaData.FrameDelay, + delayTime: (ushort)metadata.FrameDelay, transparencyIndex: unchecked((byte)transparencyIndex)); this.WriteExtension(extension, stream); diff --git a/src/ImageSharp/Formats/Gif/GifFormat.cs b/src/ImageSharp/Formats/Gif/GifFormat.cs index 07d4a5454..abe87819c 100644 --- a/src/ImageSharp/Formats/Gif/GifFormat.cs +++ b/src/ImageSharp/Formats/Gif/GifFormat.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Registers the image encoders, decoders and mime type detectors for the gif format. /// - public sealed class GifFormat : IImageFormat + public sealed class GifFormat : IImageFormat { private GifFormat() { @@ -32,9 +32,9 @@ namespace SixLabors.ImageSharp.Formats.Gif public IEnumerable FileExtensions => GifConstants.FileExtensions; /// - public GifMetaData CreateDefaultFormatMetaData() => new GifMetaData(); + public GifMetadata CreateDefaultFormatMetadata() => new GifMetadata(); /// - public GifFrameMetaData CreateDefaultFormatFrameMetaData() => new GifFrameMetaData(); + public GifFrameMetadata CreateDefaultFormatFrameMetadata() => new GifFrameMetadata(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs index 0042c6a10..613825ad6 100644 --- a/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs +++ b/src/ImageSharp/Formats/Gif/GifFrameMetaData.cs @@ -6,20 +6,20 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Provides Gif specific metadata information for the image frame. /// - public class GifFrameMetaData : IDeepCloneable + public class GifFrameMetadata : IDeepCloneable { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public GifFrameMetaData() + public GifFrameMetadata() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The metadata to create an instance from. - private GifFrameMetaData(GifFrameMetaData other) + private GifFrameMetadata(GifFrameMetadata other) { this.ColorTableLength = other.ColorTableLength; this.FrameDelay = other.FrameDelay; @@ -49,6 +49,6 @@ namespace SixLabors.ImageSharp.Formats.Gif public GifDisposalMethod DisposalMethod { get; set; } /// - public IDeepCloneable DeepClone() => new GifFrameMetaData(this); + public IDeepCloneable DeepClone() => new GifFrameMetadata(this); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/GifMetaData.cs b/src/ImageSharp/Formats/Gif/GifMetaData.cs index bb7fb5051..0b6566fbf 100644 --- a/src/ImageSharp/Formats/Gif/GifMetaData.cs +++ b/src/ImageSharp/Formats/Gif/GifMetaData.cs @@ -6,20 +6,20 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// Provides Gif specific metadata information for the image. /// - public class GifMetaData : IDeepCloneable + public class GifMetadata : IDeepCloneable { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public GifMetaData() + public GifMetadata() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The metadata to create an instance from. - private GifMetaData(GifMetaData other) + private GifMetadata(GifMetadata other) { this.RepeatCount = other.RepeatCount; this.ColorTableMode = other.ColorTableMode; @@ -45,6 +45,6 @@ namespace SixLabors.ImageSharp.Formats.Gif public int GlobalColorTableLength { get; set; } /// - public IDeepCloneable DeepClone() => new GifMetaData(this); + public IDeepCloneable DeepClone() => new GifMetadata(this); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs index 0c59163cc..871b511a0 100644 --- a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs +++ b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System.Text; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; namespace SixLabors.ImageSharp.Formats.Gif { diff --git a/src/ImageSharp/Formats/IImageFormat.cs b/src/ImageSharp/Formats/IImageFormat.cs index 3cd289df7..bd0d6357c 100644 --- a/src/ImageSharp/Formats/IImageFormat.cs +++ b/src/ImageSharp/Formats/IImageFormat.cs @@ -34,30 +34,30 @@ namespace SixLabors.ImageSharp.Formats /// /// Defines the contract for an image format containing metadata. /// - /// The type of format metadata. - public interface IImageFormat : IImageFormat - where TFormatMetaData : class + /// The type of format metadata. + public interface IImageFormat : IImageFormat + where TFormatMetadata : class { /// /// Creates a default instance of the format metadata. /// - /// The . - TFormatMetaData CreateDefaultFormatMetaData(); + /// The . + TFormatMetadata CreateDefaultFormatMetadata(); } /// /// Defines the contract for an image format containing metadata with multiple frames. /// - /// The type of format metadata. - /// The type of format frame metadata. - public interface IImageFormat : IImageFormat - where TFormatMetaData : class - where TFormatFrameMetaData : class + /// The type of format metadata. + /// The type of format frame metadata. + public interface IImageFormat : IImageFormat + where TFormatMetadata : class + where TFormatFrameMetadata : class { /// /// Creates a default instance of the format frame metadata. /// - /// The . - TFormatFrameMetaData CreateDefaultFormatFrameMetaData(); + /// The . + TFormatFrameMetadata CreateDefaultFormatFrameMetadata(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs index 5bd5920db..7497c8a40 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 891dd5282..9852b36e4 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -12,9 +12,9 @@ using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; using SixLabors.Memory; @@ -149,9 +149,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg public bool IgnoreMetadata { get; } /// - /// Gets the decoded by this decoder instance. + /// Gets the decoded by this decoder instance. /// - public ImageMetaData MetaData { get; private set; } + public ImageMetadata Metadata { get; private set; } /// public int ComponentCount { get; private set; } @@ -222,7 +222,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.ParseStream(stream); this.InitExifProfile(); this.InitIccProfile(); - this.InitDerivedMetaDataProperties(); + this.InitDerivedMetadataProperties(); return this.PostProcessIntoImage(); } @@ -235,9 +235,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.ParseStream(stream, true); this.InitExifProfile(); this.InitIccProfile(); - this.InitDerivedMetaDataProperties(); + this.InitDerivedMetadataProperties(); - return new ImageInfo(new PixelTypeInfo(this.BitsPerPixel), this.ImageWidth, this.ImageHeight, this.MetaData); + return new ImageInfo(new PixelTypeInfo(this.BitsPerPixel), this.ImageWidth, this.ImageHeight, this.Metadata); } /// @@ -247,7 +247,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// Whether to decode metadata only. public void ParseStream(Stream stream, bool metadataOnly = false) { - this.MetaData = new ImageMetaData(); + this.Metadata = new ImageMetadata(); this.InputStream = new DoubleBufferedStreamReader(this.configuration.MemoryAllocator, stream); // Check for the Start Of Image marker. @@ -430,7 +430,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { if (this.isExif) { - this.MetaData.ExifProfile = new ExifProfile(this.exifData); + this.Metadata.ExifProfile = new ExifProfile(this.exifData); } } @@ -444,21 +444,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg var profile = new IccProfile(this.iccData); if (profile.CheckIsValid()) { - this.MetaData.IccProfile = profile; + this.Metadata.IccProfile = profile; } } } /// - /// Assigns derived metadata properties to , eg. horizontal and vertical resolution if it has a JFIF header. + /// Assigns derived metadata properties to , eg. horizontal and vertical resolution if it has a JFIF header. /// - private void InitDerivedMetaDataProperties() + private void InitDerivedMetadataProperties() { if (this.jFif.XDensity > 0 && this.jFif.YDensity > 0) { - this.MetaData.HorizontalResolution = this.jFif.XDensity; - this.MetaData.VerticalResolution = this.jFif.YDensity; - this.MetaData.ResolutionUnits = this.jFif.DensityUnits; + this.Metadata.HorizontalResolution = this.jFif.XDensity; + this.Metadata.VerticalResolution = this.jFif.YDensity; + this.Metadata.ResolutionUnits = this.jFif.DensityUnits; } else if (this.isExif) { @@ -467,16 +467,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg if (horizontalValue > 0 && verticalValue > 0) { - this.MetaData.HorizontalResolution = horizontalValue; - this.MetaData.VerticalResolution = verticalValue; - this.MetaData.ResolutionUnits = UnitConverter.ExifProfileToResolutionUnit(this.MetaData.ExifProfile); + this.Metadata.HorizontalResolution = horizontalValue; + this.Metadata.VerticalResolution = verticalValue; + this.Metadata.ResolutionUnits = UnitConverter.ExifProfileToResolutionUnit(this.Metadata.ExifProfile); } } } private double GetExifResolutionValue(ExifTag tag) { - if (!this.MetaData.ExifProfile.TryGetValue(tag, out ExifValue exifValue)) + if (!this.Metadata.ExifProfile.TryGetValue(tag, out ExifValue exifValue)) { return 0; } @@ -713,7 +713,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg JpegThrowHelper.ThrowBadMarker(nameof(JpegConstants.Markers.DQT), remaining); } - this.MetaData.GetFormatMetaData(JpegFormat.Instance).Quality = QualityEvaluator.EstimateQuality(this.QuantizationTables); + this.Metadata.GetFormatMetadata(JpegFormat.Instance).Quality = QualityEvaluator.EstimateQuality(this.QuantizationTables); } /// @@ -992,7 +992,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.configuration, this.ImageWidth, this.ImageHeight, - this.MetaData); + this.Metadata); using (var postProcessor = new JpegImagePostProcessor(this.configuration, this)) { diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index 4544244f0..d4ce28107 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -10,9 +10,9 @@ using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; using SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder; -using SixLabors.ImageSharp.MetaData; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Jpeg @@ -204,10 +204,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } this.outputStream = stream; - ImageMetaData metaData = image.MetaData; + ImageMetadata metadata = image.Metadata; // System.Drawing produces identical output for jpegs with a quality parameter of 0 and 1. - int qlty = (this.quality ?? metaData.GetFormatMetaData(JpegFormat.Instance).Quality).Clamp(1, 100); + int qlty = (this.quality ?? metadata.GetFormatMetadata(JpegFormat.Instance).Quality).Clamp(1, 100); this.subsample = this.subsample ?? (qlty >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420); // Convert from a quality rating to a scaling factor. @@ -229,10 +229,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg int componentCount = 3; // Write the Start Of Image marker. - this.WriteApplicationHeader(metaData); + this.WriteApplicationHeader(metadata); // Write Exif and ICC profiles - this.WriteProfiles(metaData); + this.WriteProfiles(metadata); // Write the quantization tables. this.WriteDefineQuantizationTables(); @@ -448,8 +448,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Writes the application header containing the JFIF identifier plus extra data. /// - /// The image meta data. - private void WriteApplicationHeader(ImageMetaData meta) + /// The image metadata. + private void WriteApplicationHeader(ImageMetadata meta) { // Write the start of image marker. Markers are always prefixed with 0xff. this.buffer[0] = JpegConstants.Markers.XFF; @@ -791,17 +791,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Writes the metadata profiles to the image. /// - /// The image meta data. - private void WriteProfiles(ImageMetaData metaData) + /// The image metadata. + private void WriteProfiles(ImageMetadata metadata) { - if (metaData is null) + if (metadata is null) { return; } - metaData.SyncProfiles(); - this.WriteExifProfile(metaData.ExifProfile); - this.WriteIccProfile(metaData.IccProfile); + metadata.SyncProfiles(); + this.WriteExifProfile(metadata.ExifProfile); + this.WriteIccProfile(metadata.IccProfile); } /// diff --git a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs index 6b23ceac7..f56072a4b 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegFormat.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegFormat.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Registers the image encoders, decoders and mime type detectors for the jpeg format. /// - public sealed class JpegFormat : IImageFormat + public sealed class JpegFormat : IImageFormat { private JpegFormat() { @@ -32,6 +32,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg public IEnumerable FileExtensions => JpegConstants.FileExtensions; /// - public JpegMetaData CreateDefaultFormatMetaData() => new JpegMetaData(); + public JpegMetadata CreateDefaultFormatMetadata() => new JpegMetadata(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs index fcad29e5d..9f0deae02 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegMetaData.cs @@ -6,20 +6,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Provides Jpeg specific metadata information for the image. /// - public class JpegMetaData : IDeepCloneable + public class JpegMetadata : IDeepCloneable { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public JpegMetaData() + public JpegMetadata() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The metadata to create an instance from. - private JpegMetaData(JpegMetaData other) => this.Quality = other.Quality; + private JpegMetadata(JpegMetadata other) => this.Quality = other.Quality; /// /// Gets or sets the encoded quality. @@ -27,6 +27,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg public int Quality { get; set; } = 75; /// - public IDeepCloneable DeepClone() => new JpegMetaData(this); + public IDeepCloneable DeepClone() => new JpegMetadata(this); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs b/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs index 1d0e280bd..8b3c3e9aa 100644 --- a/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs +++ b/src/ImageSharp/Formats/Png/Chunks/PhysicalChunkData.cs @@ -4,7 +4,7 @@ using System; using System.Buffers.Binary; using SixLabors.ImageSharp.Common.Helpers; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; namespace SixLabors.ImageSharp.Formats.Png.Chunks { @@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Chunks /// /// The metadata. /// The constructed PngPhysicalChunkData instance. - public static PhysicalChunkData FromMetadata(ImageMetaData meta) + public static PhysicalChunkData FromMetadata(ImageMetadata meta) { byte unitSpecifier = 0; uint x; diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 9ffac5e62..5e9d1440a 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -12,8 +12,8 @@ using SixLabors.ImageSharp.Formats.Png.Chunks; using SixLabors.ImageSharp.Formats.Png.Filters; using SixLabors.ImageSharp.Formats.Png.Zlib; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; @@ -157,8 +157,8 @@ namespace SixLabors.ImageSharp.Formats.Png public Image Decode(Stream stream) where TPixel : struct, IPixel { - var metaData = new ImageMetaData(); - PngMetaData pngMetaData = metaData.GetFormatMetaData(PngFormat.Instance); + var metadata = new ImageMetadata(); + PngMetadata pngMetadata = metadata.GetFormatMetadata(PngFormat.Instance); this.currentStream = stream; this.currentStream.Skip(8); Image image = null; @@ -171,24 +171,24 @@ namespace SixLabors.ImageSharp.Formats.Png switch (chunk.Type) { case PngChunkType.Header: - this.ReadHeaderChunk(pngMetaData, chunk.Data.Array); + this.ReadHeaderChunk(pngMetadata, chunk.Data.Array); break; case PngChunkType.Physical: - this.ReadPhysicalChunk(metaData, chunk.Data.GetSpan()); + this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); break; case PngChunkType.Gamma: - this.ReadGammaChunk(pngMetaData, chunk.Data.GetSpan()); + this.ReadGammaChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.Data: if (image is null) { - this.InitializeImage(metaData, out image); + this.InitializeImage(metadata, out image); } using (var deframeStream = new ZlibInflateStream(this.currentStream, this.ReadNextDataChunk)) { deframeStream.AllocateNewBytes(chunk.Length); - this.ReadScanlines(deframeStream.CompressedStream, image.Frames.RootFrame, pngMetaData); + this.ReadScanlines(deframeStream.CompressedStream, image.Frames.RootFrame, pngMetadata); } break; @@ -201,17 +201,17 @@ namespace SixLabors.ImageSharp.Formats.Png byte[] alpha = new byte[chunk.Length]; Buffer.BlockCopy(chunk.Data.Array, 0, alpha, 0, chunk.Length); this.paletteAlpha = alpha; - this.AssignTransparentMarkers(alpha, pngMetaData); + this.AssignTransparentMarkers(alpha, pngMetadata); break; case PngChunkType.Text: - this.ReadTextChunk(metaData, chunk.Data.Array.AsSpan(0, chunk.Length)); + this.ReadTextChunk(metadata, chunk.Data.Array.AsSpan(0, chunk.Length)); break; case PngChunkType.Exif: if (!this.ignoreMetadata) { byte[] exifData = new byte[chunk.Length]; Buffer.BlockCopy(chunk.Data.Array, 0, exifData, 0, chunk.Length); - metaData.ExifProfile = new ExifProfile(exifData); + metadata.ExifProfile = new ExifProfile(exifData); } break; @@ -246,8 +246,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// The containing image data. public IImageInfo Identify(Stream stream) { - var metaData = new ImageMetaData(); - PngMetaData pngMetaData = metaData.GetFormatMetaData(PngFormat.Instance); + var metadata = new ImageMetadata(); + PngMetadata pngMetadata = metadata.GetFormatMetadata(PngFormat.Instance); this.currentStream = stream; this.currentStream.Skip(8); try @@ -259,19 +259,19 @@ namespace SixLabors.ImageSharp.Formats.Png switch (chunk.Type) { case PngChunkType.Header: - this.ReadHeaderChunk(pngMetaData, chunk.Data.Array); + this.ReadHeaderChunk(pngMetadata, chunk.Data.Array); break; case PngChunkType.Physical: - this.ReadPhysicalChunk(metaData, chunk.Data.GetSpan()); + this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); break; case PngChunkType.Gamma: - this.ReadGammaChunk(pngMetaData, chunk.Data.GetSpan()); + this.ReadGammaChunk(pngMetadata, chunk.Data.GetSpan()); break; case PngChunkType.Data: this.SkipChunkDataAndCrc(chunk); break; case PngChunkType.Text: - this.ReadTextChunk(metaData, chunk.Data.Array.AsSpan(0, chunk.Length)); + this.ReadTextChunk(metadata, chunk.Data.Array.AsSpan(0, chunk.Length)); break; case PngChunkType.End: this.isEndChunkReached = true; @@ -295,7 +295,7 @@ namespace SixLabors.ImageSharp.Formats.Png throw new ImageFormatException("PNG Image does not contain a header chunk"); } - return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metaData); + return new ImageInfo(new PixelTypeInfo(this.CalculateBitsPerPixel()), this.header.Width, this.header.Height, metadata); } /// @@ -350,7 +350,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The metadata to read to. /// The data containing physical data. - private void ReadPhysicalChunk(ImageMetaData metadata, ReadOnlySpan data) + private void ReadPhysicalChunk(ImageMetadata metadata, ReadOnlySpan data) { var physicalChunk = PhysicalChunkData.Parse(data); @@ -367,7 +367,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The metadata to read to. /// The data containing physical data. - private void ReadGammaChunk(PngMetaData pngMetadata, ReadOnlySpan data) + private void ReadGammaChunk(PngMetadata pngMetadata, ReadOnlySpan data) { // The value is encoded as a 4-byte unsigned integer, representing gamma times 100000. // For example, a gamma of 1/2.2 would be stored as 45455. @@ -380,7 +380,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The type the pixels will be /// The metadata information for the image /// The image that we will populate - private void InitializeImage(ImageMetaData metadata, out Image image) + private void InitializeImage(ImageMetadata metadata, out Image image) where TPixel : struct, IPixel { image = new Image(this.configuration, this.header.Width, this.header.Height, metadata); @@ -471,17 +471,17 @@ namespace SixLabors.ImageSharp.Formats.Png /// The pixel format. /// The containing data. /// The pixel data. - /// The png meta data - private void ReadScanlines(Stream dataStream, ImageFrame image, PngMetaData pngMetaData) + /// The png metadata + private void ReadScanlines(Stream dataStream, ImageFrame image, PngMetadata pngMetadata) where TPixel : struct, IPixel { if (this.header.InterlaceMethod == PngInterlaceMode.Adam7) { - this.DecodeInterlacedPixelData(dataStream, image, pngMetaData); + this.DecodeInterlacedPixelData(dataStream, image, pngMetadata); } else { - this.DecodePixelData(dataStream, image, pngMetaData); + this.DecodePixelData(dataStream, image, pngMetadata); } } @@ -491,8 +491,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// The pixel format. /// The compressed pixel data stream. /// The image to decode to. - /// The png meta data - private void DecodePixelData(Stream compressedStream, ImageFrame image, PngMetaData pngMetaData) + /// The png metadata + private void DecodePixelData(Stream compressedStream, ImageFrame image, PngMetadata pngMetadata) where TPixel : struct, IPixel { while (this.currentRow < this.header.Height) @@ -532,7 +532,7 @@ namespace SixLabors.ImageSharp.Formats.Png throw new ImageFormatException("Unknown filter type."); } - this.ProcessDefilteredScanline(scanlineSpan, image, pngMetaData); + this.ProcessDefilteredScanline(scanlineSpan, image, pngMetadata); this.SwapBuffers(); this.currentRow++; @@ -546,8 +546,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// The pixel format. /// The compressed pixel data stream. /// The current image. - /// The png meta data - private void DecodeInterlacedPixelData(Stream compressedStream, ImageFrame image, PngMetaData pngMetaData) + /// The png metadata. + private void DecodeInterlacedPixelData(Stream compressedStream, ImageFrame image, PngMetadata pngMetadata) where TPixel : struct, IPixel { while (true) @@ -604,7 +604,7 @@ namespace SixLabors.ImageSharp.Formats.Png } Span rowSpan = image.GetPixelRowSpan(this.currentRow); - this.ProcessInterlacedDefilteredScanline(this.scanline.GetSpan(), rowSpan, pngMetaData, Adam7.FirstColumn[this.pass], Adam7.ColumnIncrement[this.pass]); + this.ProcessInterlacedDefilteredScanline(this.scanline.GetSpan(), rowSpan, pngMetadata, Adam7.FirstColumn[this.pass], Adam7.ColumnIncrement[this.pass]); this.SwapBuffers(); @@ -632,8 +632,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// The pixel format. /// The de-filtered scanline /// The image - /// The png meta data - private void ProcessDefilteredScanline(ReadOnlySpan defilteredScanline, ImageFrame pixels, PngMetaData pngMetaData) + /// The png metadata. + private void ProcessDefilteredScanline(ReadOnlySpan defilteredScanline, ImageFrame pixels, PngMetadata pngMetadata) where TPixel : struct, IPixel { Span rowSpan = pixels.GetPixelRowSpan(this.currentRow); @@ -653,9 +653,9 @@ namespace SixLabors.ImageSharp.Formats.Png this.header, scanlineSpan, rowSpan, - pngMetaData.HasTrans, - pngMetaData.TransparentGray16.GetValueOrDefault(), - pngMetaData.TransparentGray8.GetValueOrDefault()); + pngMetadata.HasTrans, + pngMetadata.TransparentGray16.GetValueOrDefault(), + pngMetadata.TransparentGray8.GetValueOrDefault()); break; @@ -687,9 +687,9 @@ namespace SixLabors.ImageSharp.Formats.Png rowSpan, this.bytesPerPixel, this.bytesPerSample, - pngMetaData.HasTrans, - pngMetaData.TransparentRgb48.GetValueOrDefault(), - pngMetaData.TransparentRgb24.GetValueOrDefault()); + pngMetadata.HasTrans, + pngMetadata.TransparentRgb48.GetValueOrDefault(), + pngMetadata.TransparentRgb24.GetValueOrDefault()); break; @@ -714,10 +714,10 @@ namespace SixLabors.ImageSharp.Formats.Png /// The pixel format. /// The de-filtered scanline /// The current image row. - /// The png meta data + /// The png metadata. /// The column start index. Always 0 for none interlaced images. /// The column increment. Always 1 for none interlaced images. - private void ProcessInterlacedDefilteredScanline(ReadOnlySpan defilteredScanline, Span rowSpan, PngMetaData pngMetaData, int pixelOffset = 0, int increment = 1) + private void ProcessInterlacedDefilteredScanline(ReadOnlySpan defilteredScanline, Span rowSpan, PngMetadata pngMetadata, int pixelOffset = 0, int increment = 1) where TPixel : struct, IPixel { // Trim the first marker byte from the buffer @@ -737,9 +737,9 @@ namespace SixLabors.ImageSharp.Formats.Png rowSpan, pixelOffset, increment, - pngMetaData.HasTrans, - pngMetaData.TransparentGray16.GetValueOrDefault(), - pngMetaData.TransparentGray8.GetValueOrDefault()); + pngMetadata.HasTrans, + pngMetadata.TransparentGray16.GetValueOrDefault(), + pngMetadata.TransparentGray8.GetValueOrDefault()); break; @@ -776,9 +776,9 @@ namespace SixLabors.ImageSharp.Formats.Png increment, this.bytesPerPixel, this.bytesPerSample, - pngMetaData.HasTrans, - pngMetaData.TransparentRgb48.GetValueOrDefault(), - pngMetaData.TransparentRgb24.GetValueOrDefault()); + pngMetadata.HasTrans, + pngMetadata.TransparentRgb48.GetValueOrDefault(), + pngMetadata.TransparentRgb24.GetValueOrDefault()); break; @@ -799,11 +799,11 @@ namespace SixLabors.ImageSharp.Formats.Png } /// - /// Decodes and assigns marker colors that identify transparent pixels in non indexed images + /// Decodes and assigns marker colors that identify transparent pixels in non indexed images. /// - /// The alpha tRNS array - /// The png meta data - private void AssignTransparentMarkers(ReadOnlySpan alpha, PngMetaData pngMetaData) + /// The alpha tRNS array. + /// The png metadata. + private void AssignTransparentMarkers(ReadOnlySpan alpha, PngMetadata pngMetadata) { if (this.pngColorType == PngColorType.Rgb) { @@ -815,16 +815,16 @@ namespace SixLabors.ImageSharp.Formats.Png ushort gc = BinaryPrimitives.ReadUInt16LittleEndian(alpha.Slice(2, 2)); ushort bc = BinaryPrimitives.ReadUInt16LittleEndian(alpha.Slice(4, 2)); - pngMetaData.TransparentRgb48 = new Rgb48(rc, gc, bc); - pngMetaData.HasTrans = true; + pngMetadata.TransparentRgb48 = new Rgb48(rc, gc, bc); + pngMetadata.HasTrans = true; return; } byte r = ReadByteLittleEndian(alpha, 0); byte g = ReadByteLittleEndian(alpha, 2); byte b = ReadByteLittleEndian(alpha, 4); - pngMetaData.TransparentRgb24 = new Rgb24(r, g, b); - pngMetaData.HasTrans = true; + pngMetadata.TransparentRgb24 = new Rgb24(r, g, b); + pngMetadata.HasTrans = true; } } else if (this.pngColorType == PngColorType.Grayscale) @@ -833,14 +833,14 @@ namespace SixLabors.ImageSharp.Formats.Png { if (this.header.BitDepth == 16) { - pngMetaData.TransparentGray16 = new Gray16(BinaryPrimitives.ReadUInt16LittleEndian(alpha.Slice(0, 2))); + pngMetadata.TransparentGray16 = new Gray16(BinaryPrimitives.ReadUInt16LittleEndian(alpha.Slice(0, 2))); } else { - pngMetaData.TransparentGray8 = new Gray8(ReadByteLittleEndian(alpha, 0)); + pngMetadata.TransparentGray8 = new Gray8(ReadByteLittleEndian(alpha, 0)); } - pngMetaData.HasTrans = true; + pngMetadata.HasTrans = true; } } } @@ -848,16 +848,16 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Reads a header chunk from the data. /// - /// The png metadata. + /// The png metadata. /// The containing data. - private void ReadHeaderChunk(PngMetaData pngMetaData, ReadOnlySpan data) + private void ReadHeaderChunk(PngMetadata pngMetadata, ReadOnlySpan data) { this.header = PngHeader.Parse(data); this.header.Validate(); - pngMetaData.BitDepth = (PngBitDepth)this.header.BitDepth; - pngMetaData.ColorType = this.header.ColorType; + pngMetadata.BitDepth = (PngBitDepth)this.header.BitDepth; + pngMetadata.ColorType = this.header.ColorType; this.pngColorType = this.header.ColorType; } @@ -867,7 +867,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// The metadata to decode to. /// The containing the data. - private void ReadTextChunk(ImageMetaData metadata, ReadOnlySpan data) + private void ReadTextChunk(ImageMetadata metadata, ReadOnlySpan data) { if (this.ignoreMetadata) { diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 96e2dd946..9818e6cf1 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -14,7 +14,7 @@ using SixLabors.ImageSharp.Formats.Png.Chunks; using SixLabors.ImageSharp.Formats.Png.Filters; using SixLabors.ImageSharp.Formats.Png.Zlib; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.Memory; @@ -211,12 +211,12 @@ namespace SixLabors.ImageSharp.Formats.Png this.height = image.Height; // Always take the encoder options over the metadata values. - ImageMetaData metaData = image.MetaData; - PngMetaData pngMetaData = metaData.GetFormatMetaData(PngFormat.Instance); - this.gamma = this.gamma ?? pngMetaData.Gamma; + ImageMetadata metadata = image.Metadata; + PngMetadata pngMetadata = metadata.GetFormatMetadata(PngFormat.Instance); + this.gamma = this.gamma ?? pngMetadata.Gamma; this.writeGamma = this.gamma > 0; - this.pngColorType = this.pngColorType ?? pngMetaData.ColorType; - this.pngBitDepth = this.pngBitDepth ?? pngMetaData.BitDepth; + this.pngColorType = this.pngColorType ?? pngMetadata.ColorType; + this.pngBitDepth = this.pngBitDepth ?? pngMetadata.BitDepth; this.use16Bit = this.pngBitDepth == PngBitDepth.Bit16; // Ensure we are not allowing impossible combinations. @@ -290,14 +290,14 @@ namespace SixLabors.ImageSharp.Formats.Png this.WritePaletteChunk(stream, quantized); } - if (pngMetaData.HasTrans) + if (pngMetadata.HasTrans) { - this.WriteTransparencyChunk(stream, pngMetaData); + this.WriteTransparencyChunk(stream, pngMetadata); } - this.WritePhysicalChunk(stream, metaData); + this.WritePhysicalChunk(stream, metadata); this.WriteGammaChunk(stream); - this.WriteExifChunk(stream, metaData); + this.WriteExifChunk(stream, metadata); this.WriteDataChunks(image.Frames.RootFrame, quantized, stream); this.WriteEndChunk(stream); stream.Flush(); @@ -714,8 +714,8 @@ namespace SixLabors.ImageSharp.Formats.Png /// Writes the physical dimension information to the stream. /// /// The containing image data. - /// The image meta data. - private void WritePhysicalChunk(Stream stream, ImageMetaData meta) + /// The image metadata. + private void WritePhysicalChunk(Stream stream, ImageMetadata meta) { PhysicalChunkData.FromMetadata(meta).WriteTo(this.chunkDataBuffer); @@ -723,11 +723,11 @@ namespace SixLabors.ImageSharp.Formats.Png } /// - /// Writes the eXIf chunk to the stream, if any EXIF Profile values are present in the meta data. + /// Writes the eXIf chunk to the stream, if any EXIF Profile values are present in the metadata. /// /// The containing image data. - /// The image meta data. - private void WriteExifChunk(Stream stream, ImageMetaData meta) + /// The image metadata. + private void WriteExifChunk(Stream stream, ImageMetadata meta) { if (meta.ExifProfile?.Values.Count > 0) { @@ -757,42 +757,42 @@ namespace SixLabors.ImageSharp.Formats.Png /// Writes the transparency chunk to the stream /// /// The containing image data. - /// The image meta data. - private void WriteTransparencyChunk(Stream stream, PngMetaData pngMetaData) + /// The image metadata. + private void WriteTransparencyChunk(Stream stream, PngMetadata pngMetadata) { Span alpha = this.chunkDataBuffer.AsSpan(); - if (pngMetaData.ColorType == PngColorType.Rgb) + if (pngMetadata.ColorType == PngColorType.Rgb) { - if (pngMetaData.TransparentRgb48.HasValue && this.use16Bit) + if (pngMetadata.TransparentRgb48.HasValue && this.use16Bit) { - Rgb48 rgb = pngMetaData.TransparentRgb48.Value; + Rgb48 rgb = pngMetadata.TransparentRgb48.Value; BinaryPrimitives.WriteUInt16LittleEndian(alpha, rgb.R); BinaryPrimitives.WriteUInt16LittleEndian(alpha.Slice(2, 2), rgb.G); BinaryPrimitives.WriteUInt16LittleEndian(alpha.Slice(4, 2), rgb.B); this.WriteChunk(stream, PngChunkType.Transparency, this.chunkDataBuffer, 0, 6); } - else if (pngMetaData.TransparentRgb24.HasValue) + else if (pngMetadata.TransparentRgb24.HasValue) { alpha.Clear(); - Rgb24 rgb = pngMetaData.TransparentRgb24.Value; + Rgb24 rgb = pngMetadata.TransparentRgb24.Value; alpha[1] = rgb.R; alpha[3] = rgb.G; alpha[5] = rgb.B; this.WriteChunk(stream, PngChunkType.Transparency, this.chunkDataBuffer, 0, 6); } } - else if (pngMetaData.ColorType == PngColorType.Grayscale) + else if (pngMetadata.ColorType == PngColorType.Grayscale) { - if (pngMetaData.TransparentGray16.HasValue && this.use16Bit) + if (pngMetadata.TransparentGray16.HasValue && this.use16Bit) { - BinaryPrimitives.WriteUInt16LittleEndian(alpha, pngMetaData.TransparentGray16.Value.PackedValue); + BinaryPrimitives.WriteUInt16LittleEndian(alpha, pngMetadata.TransparentGray16.Value.PackedValue); this.WriteChunk(stream, PngChunkType.Transparency, this.chunkDataBuffer, 0, 2); } - else if (pngMetaData.TransparentGray8.HasValue) + else if (pngMetadata.TransparentGray8.HasValue) { alpha.Clear(); - alpha[1] = pngMetaData.TransparentGray8.Value.PackedValue; + alpha[1] = pngMetadata.TransparentGray8.Value.PackedValue; this.WriteChunk(stream, PngChunkType.Transparency, this.chunkDataBuffer, 0, 2); } } diff --git a/src/ImageSharp/Formats/Png/PngFormat.cs b/src/ImageSharp/Formats/Png/PngFormat.cs index 210e2a837..408e37802 100644 --- a/src/ImageSharp/Formats/Png/PngFormat.cs +++ b/src/ImageSharp/Formats/Png/PngFormat.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Registers the image encoders, decoders and mime type detectors for the png format. /// - public sealed class PngFormat : IImageFormat + public sealed class PngFormat : IImageFormat { private PngFormat() { @@ -32,6 +32,6 @@ namespace SixLabors.ImageSharp.Formats.Png public IEnumerable FileExtensions => PngConstants.FileExtensions; /// - public PngMetaData CreateDefaultFormatMetaData() => new PngMetaData(); + public PngMetadata CreateDefaultFormatMetadata() => new PngMetadata(); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/PngMetaData.cs b/src/ImageSharp/Formats/Png/PngMetaData.cs index d5ab3d255..dd951763f 100644 --- a/src/ImageSharp/Formats/Png/PngMetaData.cs +++ b/src/ImageSharp/Formats/Png/PngMetaData.cs @@ -8,20 +8,20 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Provides Png specific metadata information for the image. /// - public class PngMetaData : IDeepCloneable + public class PngMetadata : IDeepCloneable { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public PngMetaData() + public PngMetadata() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The metadata to create an instance from. - private PngMetaData(PngMetaData other) + private PngMetadata(PngMetadata other) { this.BitDepth = other.BitDepth; this.ColorType = other.ColorType; @@ -75,6 +75,6 @@ namespace SixLabors.ImageSharp.Formats.Png public bool HasTrans { get; set; } /// - public IDeepCloneable DeepClone() => new PngMetaData(this); + public IDeepCloneable DeepClone() => new PngMetadata(this); } } \ No newline at end of file diff --git a/src/ImageSharp/IImageInfo.cs b/src/ImageSharp/IImageInfo.cs index b1b1afc66..b270c2c4d 100644 --- a/src/ImageSharp/IImageInfo.cs +++ b/src/ImageSharp/IImageInfo.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; namespace SixLabors.ImageSharp { @@ -30,6 +30,6 @@ namespace SixLabors.ImageSharp /// /// Gets the metadata of the image. /// - ImageMetaData MetaData { get; } + ImageMetadata Metadata { get; } } } \ No newline at end of file diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index ffdab25e2..9e83d173f 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -5,7 +5,7 @@ using System.IO; using System.Linq; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; @@ -25,13 +25,13 @@ namespace SixLabors.ImageSharp /// The /// The width of the image /// The height of the image - /// The + /// The /// The result internal static Image CreateUninitialized( Configuration configuration, int width, int height, - ImageMetaData metadata) + ImageMetadata metadata) where TPixel : struct, IPixel { Buffer2D uninitializedMemoryBuffer = diff --git a/src/ImageSharp/Image.WrapMemory.cs b/src/ImageSharp/Image.WrapMemory.cs index 4bb24a126..3d788bb73 100644 --- a/src/ImageSharp/Image.WrapMemory.cs +++ b/src/ImageSharp/Image.WrapMemory.cs @@ -5,7 +5,7 @@ using System; using System.Buffers; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp @@ -24,18 +24,18 @@ namespace SixLabors.ImageSharp /// The pixel memory. /// The width of the memory image. /// The height of the memory image. - /// The . + /// The . /// An instance public static Image WrapMemory( Configuration config, Memory pixelMemory, int width, int height, - ImageMetaData metaData) + ImageMetadata metadata) where TPixel : struct, IPixel { var memorySource = new MemorySource(pixelMemory); - return new Image(config, memorySource, width, height, metaData); + return new Image(config, memorySource, width, height, metadata); } /// @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp int height) where TPixel : struct, IPixel { - return WrapMemory(config, pixelMemory, width, height, new ImageMetaData()); + return WrapMemory(config, pixelMemory, width, height, new ImageMetadata()); } /// @@ -89,18 +89,18 @@ namespace SixLabors.ImageSharp /// The that is being transferred to the image /// The width of the memory image. /// The height of the memory image. - /// The + /// The /// An instance public static Image WrapMemory( Configuration config, IMemoryOwner pixelMemoryOwner, int width, int height, - ImageMetaData metaData) + ImageMetadata metadata) where TPixel : struct, IPixel { var memorySource = new MemorySource(pixelMemoryOwner, false); - return new Image(config, memorySource, width, height, metaData); + return new Image(config, memorySource, width, height, metadata); } /// @@ -123,7 +123,7 @@ namespace SixLabors.ImageSharp int height) where TPixel : struct, IPixel { - return WrapMemory(config, pixelMemoryOwner, width, height, new ImageMetaData()); + return WrapMemory(config, pixelMemoryOwner, width, height, new ImageMetadata()); } /// diff --git a/src/ImageSharp/ImageFrameCollection.cs b/src/ImageSharp/ImageFrameCollection.cs index bbe05ce43..7e516434c 100644 --- a/src/ImageSharp/ImageFrameCollection.cs +++ b/src/ImageSharp/ImageFrameCollection.cs @@ -192,7 +192,7 @@ namespace SixLabors.ImageSharp this.frames.Remove(frame); - return new Image(this.parent.GetConfiguration(), this.parent.MetaData.DeepClone(), new[] { frame }); + return new Image(this.parent.GetConfiguration(), this.parent.Metadata.DeepClone(), new[] { frame }); } /// @@ -205,7 +205,7 @@ namespace SixLabors.ImageSharp { ImageFrame frame = this[index]; ImageFrame clonedFrame = frame.Clone(); - return new Image(this.parent.GetConfiguration(), this.parent.MetaData.DeepClone(), new[] { clonedFrame }); + return new Image(this.parent.GetConfiguration(), this.parent.Metadata.DeepClone(), new[] { clonedFrame }); } /// diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs index f69ae3757..4f0be5971 100644 --- a/src/ImageSharp/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/ImageFrame{TPixel}.cs @@ -6,7 +6,7 @@ using System.Runtime.CompilerServices; using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp /// The width of the image in pixels. /// The height of the image in pixels. internal ImageFrame(Configuration configuration, int width, int height) - : this(configuration, width, height, new ImageFrameMetaData()) + : this(configuration, width, height, new ImageFrameMetadata()) { } @@ -39,9 +39,9 @@ namespace SixLabors.ImageSharp /// /// The configuration which allows altering default behaviour or extending the library. /// The of the frame. - /// The meta data. - internal ImageFrame(Configuration configuration, Size size, ImageFrameMetaData metaData) - : this(configuration, size.Width, size.Height, metaData) + /// The metadata. + internal ImageFrame(Configuration configuration, Size size, ImageFrameMetadata metadata) + : this(configuration, size.Width, size.Height, metadata) { } @@ -51,9 +51,9 @@ namespace SixLabors.ImageSharp /// The configuration which allows altering default behaviour or extending the library. /// The width of the image in pixels. /// The height of the image in pixels. - /// The meta data. - internal ImageFrame(Configuration configuration, int width, int height, ImageFrameMetaData metaData) - : this(configuration, width, height, default(TPixel), metaData) + /// The metadata. + internal ImageFrame(Configuration configuration, int width, int height, ImageFrameMetadata metadata) + : this(configuration, width, height, default(TPixel), metadata) { } @@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp /// The height of the image in pixels. /// The color to clear the image with. internal ImageFrame(Configuration configuration, int width, int height, TPixel backgroundColor) - : this(configuration, width, height, backgroundColor, new ImageFrameMetaData()) + : this(configuration, width, height, backgroundColor, new ImageFrameMetadata()) { } @@ -76,8 +76,8 @@ namespace SixLabors.ImageSharp /// The width of the image in pixels. /// The height of the image in pixels. /// The color to clear the image with. - /// The meta data. - internal ImageFrame(Configuration configuration, int width, int height, TPixel backgroundColor, ImageFrameMetaData metaData) + /// The metadata. + internal ImageFrame(Configuration configuration, int width, int height, TPixel backgroundColor, ImageFrameMetadata metadata) { Guard.NotNull(configuration, nameof(configuration)); Guard.MustBeGreaterThan(width, 0, nameof(width)); @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp this.Configuration = configuration; this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = this.MemoryAllocator.Allocate2D(width, height); - this.MetaData = metaData ?? new ImageFrameMetaData(); + this.Metadata = metadata ?? new ImageFrameMetadata(); this.Clear(configuration.GetParallelOptions(), backgroundColor); } @@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp /// The height of the image in pixels. /// The memory source. internal ImageFrame(Configuration configuration, int width, int height, MemorySource memorySource) - : this(configuration, width, height, memorySource, new ImageFrameMetaData()) + : this(configuration, width, height, memorySource, new ImageFrameMetadata()) { } @@ -109,18 +109,18 @@ namespace SixLabors.ImageSharp /// The width of the image in pixels. /// The height of the image in pixels. /// The memory source. - /// The meta data. - internal ImageFrame(Configuration configuration, int width, int height, MemorySource memorySource, ImageFrameMetaData metaData) + /// The metadata. + internal ImageFrame(Configuration configuration, int width, int height, MemorySource memorySource, ImageFrameMetadata metadata) { Guard.NotNull(configuration, nameof(configuration)); Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); - Guard.NotNull(metaData, nameof(metaData)); + Guard.NotNull(metadata, nameof(metadata)); this.Configuration = configuration; this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = new Buffer2D(memorySource, width, height); - this.MetaData = metaData; + this.Metadata = metadata; } /// @@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = this.MemoryAllocator.Allocate2D(source.PixelBuffer.Width, source.PixelBuffer.Height); source.PixelBuffer.GetSpan().CopyTo(this.PixelBuffer.GetSpan()); - this.MetaData = source.MetaData.DeepClone(); + this.Metadata = source.Metadata.DeepClone(); } /// @@ -169,9 +169,9 @@ namespace SixLabors.ImageSharp public int Height => this.PixelBuffer.Height; /// - /// Gets the meta data of the frame. + /// Gets the metadata of the frame. /// - public ImageFrameMetaData MetaData { get; } + public ImageFrameMetadata Metadata { get; } /// /// Gets or sets the pixel at the specified position. @@ -289,7 +289,7 @@ namespace SixLabors.ImageSharp return this.Clone(configuration) as ImageFrame; } - var target = new ImageFrame(configuration, this.Width, this.Height, this.MetaData.DeepClone()); + var target = new ImageFrame(configuration, this.Width, this.Height, this.Metadata.DeepClone()); ParallelHelper.IterateRows( this.Bounds(), diff --git a/src/ImageSharp/ImageInfo.cs b/src/ImageSharp/ImageInfo.cs index 6f894cb59..12dcf1ed7 100644 --- a/src/ImageSharp/ImageInfo.cs +++ b/src/ImageSharp/ImageInfo.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; namespace SixLabors.ImageSharp { @@ -17,13 +17,13 @@ namespace SixLabors.ImageSharp /// The image pixel type information. /// The width of the image in pixels. /// The height of the image in pixels. - /// The images metadata. - public ImageInfo(PixelTypeInfo pixelType, int width, int height, ImageMetaData metaData) + /// The images metadata. + public ImageInfo(PixelTypeInfo pixelType, int width, int height, ImageMetadata metadata) { this.PixelType = pixelType; this.Width = width; this.Height = height; - this.MetaData = metaData; + this.Metadata = metadata; } /// @@ -36,6 +36,6 @@ namespace SixLabors.ImageSharp public int Height { get; } /// - public ImageMetaData MetaData { get; } + public ImageMetadata Metadata { get; } } } \ No newline at end of file diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 178194b21..f2bef78e1 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -9,7 +9,7 @@ using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp @@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp /// The width of the image in pixels. /// The height of the image in pixels. public Image(Configuration configuration, int width, int height) - : this(configuration, width, height, new ImageMetaData()) + : this(configuration, width, height, new ImageMetadata()) { } @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp /// The height of the image in pixels. /// The color to initialize the pixels with. public Image(Configuration configuration, int width, int height, TPixel backgroundColor) - : this(configuration, width, height, backgroundColor, new ImageMetaData()) + : this(configuration, width, height, backgroundColor, new ImageMetadata()) { } @@ -67,11 +67,11 @@ namespace SixLabors.ImageSharp /// The width of the image in pixels. /// The height of the image in pixels. /// The images metadata. - internal Image(Configuration configuration, int width, int height, ImageMetaData metadata) + internal Image(Configuration configuration, int width, int height, ImageMetadata metadata) { this.configuration = configuration ?? Configuration.Default; this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); - this.MetaData = metadata ?? new ImageMetaData(); + this.Metadata = metadata ?? new ImageMetadata(); this.Frames = new ImageFrameCollection(this, width, height, default(TPixel)); } @@ -84,11 +84,11 @@ namespace SixLabors.ImageSharp /// The width of the image in pixels. /// The height of the image in pixels. /// The images metadata. - internal Image(Configuration configuration, MemorySource memorySource, int width, int height, ImageMetaData metadata) + internal Image(Configuration configuration, MemorySource memorySource, int width, int height, ImageMetadata metadata) { this.configuration = configuration; this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); - this.MetaData = metadata; + this.Metadata = metadata; this.Frames = new ImageFrameCollection(this, width, height, memorySource); } @@ -101,11 +101,11 @@ namespace SixLabors.ImageSharp /// The height of the image in pixels. /// The color to initialize the pixels with. /// The images metadata. - internal Image(Configuration configuration, int width, int height, TPixel backgroundColor, ImageMetaData metadata) + internal Image(Configuration configuration, int width, int height, TPixel backgroundColor, ImageMetadata metadata) { this.configuration = configuration ?? Configuration.Default; this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); - this.MetaData = metadata ?? new ImageMetaData(); + this.Metadata = metadata ?? new ImageMetadata(); this.Frames = new ImageFrameCollection(this, width, height, backgroundColor); } @@ -116,11 +116,11 @@ namespace SixLabors.ImageSharp /// The configuration providing initialization code which allows extending the library. /// The images metadata. /// The frames that will be owned by this image instance. - internal Image(Configuration configuration, ImageMetaData metadata, IEnumerable> frames) + internal Image(Configuration configuration, ImageMetadata metadata, IEnumerable> frames) { this.configuration = configuration ?? Configuration.Default; this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); - this.MetaData = metadata ?? new ImageMetaData(); + this.Metadata = metadata ?? new ImageMetadata(); this.Frames = new ImageFrameCollection(this, frames); } @@ -140,7 +140,7 @@ namespace SixLabors.ImageSharp public int Height => this.Frames.RootFrame.Height; /// - public ImageMetaData MetaData { get; } + public ImageMetadata Metadata { get; } /// /// Gets the frames. @@ -193,7 +193,7 @@ namespace SixLabors.ImageSharp public Image Clone(Configuration configuration) { IEnumerable> clonedFrames = this.Frames.Select(x => x.Clone(configuration)); - return new Image(configuration, this.MetaData.DeepClone(), clonedFrames); + return new Image(configuration, this.Metadata.DeepClone(), clonedFrames); } /// @@ -214,7 +214,7 @@ namespace SixLabors.ImageSharp where TPixel2 : struct, IPixel { IEnumerable> clonedFrames = this.Frames.Select(x => x.CloneAs(configuration)); - return new Image(configuration, this.MetaData.DeepClone(), clonedFrames); + return new Image(configuration, this.Metadata.DeepClone(), clonedFrames); } /// diff --git a/src/ImageSharp/MetaData/FrameDecodingMode.cs b/src/ImageSharp/MetaData/FrameDecodingMode.cs index 2863fbf8f..835e43354 100644 --- a/src/ImageSharp/MetaData/FrameDecodingMode.cs +++ b/src/ImageSharp/MetaData/FrameDecodingMode.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData +namespace SixLabors.ImageSharp.Metadata { /// /// Enumerated frame process modes to apply to multi-frame images. diff --git a/src/ImageSharp/MetaData/ImageFrameMetaData.cs b/src/ImageSharp/MetaData/ImageFrameMetaData.cs index f1f884be6..3858a7d0a 100644 --- a/src/ImageSharp/MetaData/ImageFrameMetaData.cs +++ b/src/ImageSharp/MetaData/ImageFrameMetaData.cs @@ -4,62 +4,62 @@ using System.Collections.Generic; using SixLabors.ImageSharp.Formats; -namespace SixLabors.ImageSharp.MetaData +namespace SixLabors.ImageSharp.Metadata { /// /// Encapsulates the metadata of an image frame. /// - public sealed class ImageFrameMetaData : IDeepCloneable + public sealed class ImageFrameMetadata : IDeepCloneable { - private readonly Dictionary formatMetaData = new Dictionary(); + private readonly Dictionary formatMetadata = new Dictionary(); /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - internal ImageFrameMetaData() + internal ImageFrameMetadata() { } /// - /// Initializes a new instance of the class + /// Initializes a new instance of the class /// by making a copy from other metadata. /// /// - /// The other to create this instance from. + /// The other to create this instance from. /// - internal ImageFrameMetaData(ImageFrameMetaData other) + internal ImageFrameMetadata(ImageFrameMetadata other) { DebugGuard.NotNull(other, nameof(other)); - foreach (KeyValuePair meta in other.formatMetaData) + foreach (KeyValuePair meta in other.formatMetadata) { - this.formatMetaData.Add(meta.Key, meta.Value.DeepClone()); + this.formatMetadata.Add(meta.Key, meta.Value.DeepClone()); } } /// - public ImageFrameMetaData DeepClone() => new ImageFrameMetaData(this); + public ImageFrameMetadata DeepClone() => new ImageFrameMetadata(this); /// /// Gets the metadata value associated with the specified key. /// - /// The type of format metadata. - /// The type of format frame metadata. + /// The type of format metadata. + /// The type of format frame metadata. /// The key of the value to get. /// - /// The . + /// The . /// - public TFormatFrameMetaData GetFormatMetaData(IImageFormat key) - where TFormatMetaData : class - where TFormatFrameMetaData : class, IDeepCloneable + public TFormatFrameMetadata GetFormatMetadata(IImageFormat key) + where TFormatMetadata : class + where TFormatFrameMetadata : class, IDeepCloneable { - if (this.formatMetaData.TryGetValue(key, out IDeepCloneable meta)) + if (this.formatMetadata.TryGetValue(key, out IDeepCloneable meta)) { - return (TFormatFrameMetaData)meta; + return (TFormatFrameMetadata)meta; } - TFormatFrameMetaData newMeta = key.CreateDefaultFormatFrameMetaData(); - this.formatMetaData[key] = newMeta; + TFormatFrameMetadata newMeta = key.CreateDefaultFormatFrameMetadata(); + this.formatMetadata[key] = newMeta; return newMeta; } } diff --git a/src/ImageSharp/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs index 73549d98a..b9efca4fe 100644 --- a/src/ImageSharp/MetaData/ImageMetaData.cs +++ b/src/ImageSharp/MetaData/ImageMetaData.cs @@ -3,15 +3,15 @@ using System.Collections.Generic; using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.MetaData +namespace SixLabors.ImageSharp.Metadata { /// /// Encapsulates the metadata of an image. /// - public sealed class ImageMetaData : IDeepCloneable + public sealed class ImageMetadata : IDeepCloneable { /// /// The default horizontal resolution value (dots per inch) in x direction. @@ -31,14 +31,14 @@ namespace SixLabors.ImageSharp.MetaData /// public const PixelResolutionUnit DefaultPixelResolutionUnits = PixelResolutionUnit.PixelsPerInch; - private readonly Dictionary formatMetaData = new Dictionary(); + private readonly Dictionary formatMetadata = new Dictionary(); private double horizontalResolution; private double verticalResolution; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - internal ImageMetaData() + internal ImageMetadata() { this.horizontalResolution = DefaultHorizontalResolution; this.verticalResolution = DefaultVerticalResolution; @@ -46,21 +46,21 @@ namespace SixLabors.ImageSharp.MetaData } /// - /// Initializes a new instance of the class + /// Initializes a new instance of the class /// by making a copy from other metadata. /// /// - /// The other to create this instance from. + /// The other to create this instance from. /// - private ImageMetaData(ImageMetaData other) + private ImageMetadata(ImageMetadata other) { this.HorizontalResolution = other.HorizontalResolution; this.VerticalResolution = other.VerticalResolution; this.ResolutionUnits = other.ResolutionUnits; - foreach (KeyValuePair meta in other.formatMetaData) + foreach (KeyValuePair meta in other.formatMetadata) { - this.formatMetaData.Add(meta.Key, meta.Value.DeepClone()); + this.formatMetadata.Add(meta.Key, meta.Value.DeepClone()); } foreach (ImageProperty property in other.Properties) @@ -135,26 +135,26 @@ namespace SixLabors.ImageSharp.MetaData /// /// Gets the metadata value associated with the specified key. /// - /// The type of metadata. + /// The type of metadata. /// The key of the value to get. /// - /// The . + /// The . /// - public TFormatMetaData GetFormatMetaData(IImageFormat key) - where TFormatMetaData : class, IDeepCloneable + public TFormatMetadata GetFormatMetadata(IImageFormat key) + where TFormatMetadata : class, IDeepCloneable { - if (this.formatMetaData.TryGetValue(key, out IDeepCloneable meta)) + if (this.formatMetadata.TryGetValue(key, out IDeepCloneable meta)) { - return (TFormatMetaData)meta; + return (TFormatMetadata)meta; } - TFormatMetaData newMeta = key.CreateDefaultFormatMetaData(); - this.formatMetaData[key] = newMeta; + TFormatMetadata newMeta = key.CreateDefaultFormatMetadata(); + this.formatMetadata[key] = newMeta; return newMeta; } /// - public ImageMetaData DeepClone() => new ImageMetaData(this); + public ImageMetadata DeepClone() => new ImageMetadata(this); /// /// Looks up a property with the provided name. @@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.MetaData } /// - /// Synchronizes the profiles with the current meta data. + /// Synchronizes the profiles with the current metadata. /// internal void SyncProfiles() => this.ExifProfile?.Sync(this); } diff --git a/src/ImageSharp/MetaData/ImageProperty.cs b/src/ImageSharp/MetaData/ImageProperty.cs index 6d38b6bf1..905e42dab 100644 --- a/src/ImageSharp/MetaData/ImageProperty.cs +++ b/src/ImageSharp/MetaData/ImageProperty.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData +namespace SixLabors.ImageSharp.Metadata { /// /// Stores meta information about a image, like the name of the author, diff --git a/src/ImageSharp/MetaData/PixelResolutionUnit.cs b/src/ImageSharp/MetaData/PixelResolutionUnit.cs index ce848004f..661e7a308 100644 --- a/src/ImageSharp/MetaData/PixelResolutionUnit.cs +++ b/src/ImageSharp/MetaData/PixelResolutionUnit.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData +namespace SixLabors.ImageSharp.Metadata { /// /// Provides enumeration of available pixel density units. diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifConstants.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifConstants.cs index fb2a893d1..c7112c47a 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifConstants.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifConstants.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Exif +namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { internal static class ExifConstants { diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifDataType.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifDataType.cs index 5bd38b195..83e7f7fe8 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifDataType.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifDataType.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Exif +namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { /// /// Specifies exif data types. diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifParts.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifParts.cs index b1b42ad43..d22dc730f 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifParts.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifParts.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Exif +namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { /// /// Specifies which parts will be written when the profile is added to an image. diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs index 37ceaf10f..3d90cb3a9 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs @@ -7,7 +7,7 @@ using System.IO; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; -namespace SixLabors.ImageSharp.MetaData.Profiles.Exif +namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { /// /// Represents an EXIF profile providing access to the collection of values. @@ -249,13 +249,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif public ExifProfile DeepClone() => new ExifProfile(this); /// - /// Synchronizes the profiles with the specified meta data. + /// Synchronizes the profiles with the specified metadata. /// - /// The meta data. - internal void Sync(ImageMetaData metaData) + /// The metadata. + internal void Sync(ImageMetadata metadata) { - this.SyncResolution(ExifTag.XResolution, metaData.HorizontalResolution); - this.SyncResolution(ExifTag.YResolution, metaData.VerticalResolution); + this.SyncResolution(ExifTag.XResolution, metadata.HorizontalResolution); + this.SyncResolution(ExifTag.YResolution, metadata.VerticalResolution); } private void SyncResolution(ExifTag tag, double resolution) diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs index cf95affb0..e40e6c26c 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs @@ -10,7 +10,7 @@ using System.Runtime.CompilerServices; using System.Text; using SixLabors.ImageSharp.Primitives; -namespace SixLabors.ImageSharp.MetaData.Profiles.Exif +namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { /// /// Reads and parses EXIF data from a byte array. diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifTag.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifTag.cs index 625f95b63..ddd4591fa 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifTag.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifTag.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Exif +namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { /// /// All exif tags from the Exif standard 2.2 diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifTagDescriptionAttribute.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifTagDescriptionAttribute.cs index 286fdbe57..0188c662e 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifTagDescriptionAttribute.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifTagDescriptionAttribute.cs @@ -4,7 +4,7 @@ using System; using System.Reflection; -namespace SixLabors.ImageSharp.MetaData.Profiles.Exif +namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { /// /// Class that provides a description for an ExifTag value. diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs index e999d00b8..0ed3a43b7 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifTags.cs @@ -1,9 +1,9 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using static SixLabors.ImageSharp.MetaData.Profiles.Exif.ExifTag; +using static SixLabors.ImageSharp.Metadata.Profiles.Exif.ExifTag; -namespace SixLabors.ImageSharp.MetaData.Profiles.Exif +namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { internal static class ExifTags { diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs index 409c55253..05a9f35c9 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs @@ -6,7 +6,7 @@ using System.Globalization; using System.Text; using SixLabors.ImageSharp.Primitives; -namespace SixLabors.ImageSharp.MetaData.Profiles.Exif +namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { /// /// Represent the value of the EXIF profile. diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs index 9079526d5..93fe7fbbe 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; using System.Text; using SixLabors.ImageSharp.Primitives; -namespace SixLabors.ImageSharp.MetaData.Profiles.Exif +namespace SixLabors.ImageSharp.Metadata.Profiles.Exif { /// /// Contains methods for writing EXIF metadata. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccCurveSegment.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccCurveSegment.cs index 516887bcd..7bf1f8421 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccCurveSegment.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccCurveSegment.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A segment of a curve diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccFormulaCurveElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccFormulaCurveElement.cs index d168c5c28..d013f6ef1 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccFormulaCurveElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccFormulaCurveElement.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A formula based curve segment diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs index 7076e5144..e1d362a7f 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A one dimensional ICC curve. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs index efc2ca537..04a9faf7d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A parametric curve diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs index de08485ac..4f0345d35 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs @@ -5,7 +5,7 @@ using System; using System.Linq; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A response curve diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccSampledCurveElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccSampledCurveElement.cs index d9badf5a8..4872bd2b0 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccSampledCurveElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccSampledCurveElement.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A sampled curve segment diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Curves.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Curves.cs index b27083dc4..111911080 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Curves.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Curves.cs @@ -3,7 +3,7 @@ using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to read ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Lut.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Lut.cs index f9d56b0ff..5262e3ee9 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Lut.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Lut.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to read ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Matrix.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Matrix.cs index 495d73a78..3157b9ef3 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Matrix.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Matrix.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to read ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.MultiProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.MultiProcessElement.cs index 2b39b1d6c..425305828 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.MultiProcessElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.MultiProcessElement.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to read ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs index 7dc8cf98a..aacbbcc1d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs @@ -4,7 +4,7 @@ using System; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to read ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs index bb85a5ca3..2cbf798ec 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs @@ -6,7 +6,7 @@ using System.Buffers.Binary; using System.Runtime.CompilerServices; using System.Text; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to read ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs index c572b7f21..3f330ef72 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs @@ -5,7 +5,7 @@ using System; using System.Globalization; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to read ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs index 91a28fd74..7d694bec6 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.cs @@ -4,7 +4,7 @@ using System; using System.Text; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to read ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Curves.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Curves.cs index d5f5d5a9b..c48ba8ab7 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Curves.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Curves.cs @@ -3,7 +3,7 @@ using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to write ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs index 38a3dd457..016bd8009 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to write ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Matrix.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Matrix.cs index 79b913219..b0bd377cb 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Matrix.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Matrix.cs @@ -4,7 +4,7 @@ using System.Numerics; using SixLabors.ImageSharp.Primitives; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to write ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElement.cs index 48c6734ae..824a9bef6 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElement.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to write ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs index 1a3c2c0ac..e681f84b8 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs @@ -4,7 +4,7 @@ using System; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to write ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs index 404285b50..6c49eb0c4 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs @@ -4,7 +4,7 @@ using System; using System.Text; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to write ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs index 51ea2d4e4..13fb023d3 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs @@ -3,7 +3,7 @@ using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to write ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.cs index 21b7b6421..17f15df71 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.cs @@ -4,7 +4,7 @@ using System; using System.IO; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Provides methods to write ICC data types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccClutDataType.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccClutDataType.cs index fe0c9b8b5..71e68f6af 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccClutDataType.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccClutDataType.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Color lookup table data type diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccColorSpaceType.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccColorSpaceType.cs index 0913cda41..721545df3 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccColorSpaceType.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccColorSpaceType.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Color Space Type diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccColorantEncoding.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccColorantEncoding.cs index bec71e0db..14b2dd960 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccColorantEncoding.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccColorantEncoding.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Colorant Encoding diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccCurveMeasurementEncodings.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccCurveMeasurementEncodings.cs index cfd2671e9..a620632da 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccCurveMeasurementEncodings.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccCurveMeasurementEncodings.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Curve Measurement Encodings diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccCurveSegmentSignature.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccCurveSegmentSignature.cs index e9b8cc26b..9a5ae1805 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccCurveSegmentSignature.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccCurveSegmentSignature.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Curve Segment Signature diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccDataType.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccDataType.cs index b13edb53f..de1f11636 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccDataType.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccDataType.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Enumerates the basic data types as defined in ICC.1:2010 version 4.3.0.0 diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccDeviceAttribute.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccDeviceAttribute.cs index 88cca866d..c8598b0e0 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccDeviceAttribute.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccDeviceAttribute.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Device attributes. Can be combined with a logical OR diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccFormulaCurveType.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccFormulaCurveType.cs index 2a375b0d1..11e5985af 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccFormulaCurveType.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccFormulaCurveType.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Formula curve segment type diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccMeasurementGeometry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccMeasurementGeometry.cs index fe6575c41..937324194 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccMeasurementGeometry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccMeasurementGeometry.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Measurement Geometry diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccMultiProcessElementSignature.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccMultiProcessElementSignature.cs index fe5d30922..d7f78889d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccMultiProcessElementSignature.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccMultiProcessElementSignature.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Multi process element signature diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccParametricCurveType.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccParametricCurveType.cs index 374b4ad93..fce08a3af 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccParametricCurveType.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccParametricCurveType.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Formula curve segment type diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccPrimaryPlatformType.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccPrimaryPlatformType.cs index 1563078f7..035fd3d4d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccPrimaryPlatformType.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccPrimaryPlatformType.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Enumerates the primary platform/operating system framework for which the profile was created diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileClass.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileClass.cs index 8f0427db2..3d59192a7 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileClass.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileClass.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Profile Class Name diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileFlag.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileFlag.cs index 1e9ec18e8..9fbe5b5b5 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileFlag.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileFlag.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Profile flags. Can be combined with a logical OR. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileTag.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileTag.cs index 61d34dca1..b19641e0f 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileTag.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccProfileTag.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. // ReSharper disable InconsistentNaming -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Enumerates the ICC Profile Tags as defined in ICC.1:2010 version 4.3.0.0 diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccRenderingIntent.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccRenderingIntent.cs index 7cb9c00f3..8ae241b44 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccRenderingIntent.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccRenderingIntent.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Rendering intent diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningFlag.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningFlag.cs index 839ab8c6b..b43ad52c4 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningFlag.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningFlag.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Screening flags. Can be combined with a logical OR. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningSpotType.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningSpotType.cs index f1d73c626..0631892b6 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningSpotType.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningSpotType.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Enumerates the screening spot types diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccSignatureName.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccSignatureName.cs index 4773ab6c2..f93d22f3e 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccSignatureName.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccSignatureName.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Signature Name diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccStandardIlluminant.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccStandardIlluminant.cs index fe0c40657..fc8ebae5c 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccStandardIlluminant.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccStandardIlluminant.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Standard Illuminant diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccStandardObserver.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccStandardObserver.cs index a393c258b..1454b2827 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccStandardObserver.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccStandardObserver.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Standard Observer diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccTypeSignature.cs b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccTypeSignature.cs index ad0db4df9..d7a18579e 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccTypeSignature.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Enums/IccTypeSignature.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Type Signature diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Exceptions/InvalidIccProfileException.cs b/src/ImageSharp/MetaData/Profiles/ICC/Exceptions/InvalidIccProfileException.cs index f69067041..019bf9202 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Exceptions/InvalidIccProfileException.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Exceptions/InvalidIccProfileException.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Represents an error that happened while reading or writing a corrupt/invalid ICC profile diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs index 5d75a6df9..afdd7ebfb 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccProfile.cs @@ -4,7 +4,7 @@ using System; using System.Security.Cryptography; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Represents an ICC profile diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccProfileHeader.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccProfileHeader.cs index 189b40275..326dd351e 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccProfileHeader.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccProfileHeader.cs @@ -4,7 +4,7 @@ using System; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Contains all values of an ICC profile header. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs index 9f9d373ae..30a6de40d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Reads and parses ICC data from a byte array diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs index 4c6bb0785..658d4c2f1 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The data of an ICC tag entry diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs index 91a3bba54..b5a7c830d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Contains methods for writing ICC profiles. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs index 09931a1f9..c825a3535 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A placeholder (might be used for future ICC versions) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs index 6aba18632..7ee7f821d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A CLUT (color lookup table) element to process data diff --git a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs index 7585fc212..d72aff3c9 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A set of curves to process data diff --git a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs index 7e0e1eda8..d6f42aea7 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A placeholder (might be used for future ICC versions) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs index e6170f768..0d8683397 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs @@ -5,7 +5,7 @@ using System; using SixLabors.ImageSharp.Primitives; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A matrix element to process data diff --git a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs index db2d56cc3..24649d8b5 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// An element to process data diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs index e9a812d8c..b4d711f59 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The chromaticity tag type provides basic chromaticity data diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs index b5f8fd5c4..4136b9a38 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This tag specifies the laydown order in which colorants diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs index 9f2b4c90a..28d01450c 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The purpose of this tag is to identify the colorants used in diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs index 4d393dfb3..bcf9d5c9e 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type contains the PostScript product name to which this profile diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs index 0d34d3ceb..f2205cbad 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The type contains a one-dimensional table of double values. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs index 0b8367303..6a0b6c05e 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Text; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The dataType is a simple data structure that contains diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs index 104d24309..371397a6f 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type is a representation of the time and date. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs index 0a114ea1f..50bfca175 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type represents an array of doubles (from 32bit fixed point values). diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs index 415f6941e..d84fc1431 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs @@ -5,7 +5,7 @@ using System; using System.Linq; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This structure represents a color transform using tables diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs index 04a49e316..5c8ce2d2c 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs @@ -5,7 +5,7 @@ using System; using System.Linq; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This structure represents a color transform using tables diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs index f7c094632..4cee555e5 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs @@ -5,7 +5,7 @@ using System; using System.Linq; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This structure represents a color transform. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs index 27572acd0..8e9479ff8 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs @@ -5,7 +5,7 @@ using System; using System.Linq; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This structure represents a color transform. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs index 9247ca593..ad3a9f2c3 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The measurementType information refers only to the internal diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs index 1a06eb588..3084ff612 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This tag structure contains a set of records each referencing diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs index f13fdb17f..dc78e7520 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This structure represents a color transform, containing diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs index 957b8d5c3..30516578f 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The namedColor2Type is a count value and array of structures diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs index 9ec497d3b..752d05aae 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The parametricCurveType describes a one-dimensional curve by diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs index ff6911526..3c3a6c761 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type is an array of structures, each of which contains information diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs index c6cc0903c..06e52cb63 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type is an array of structures, each of which contains information diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs index 494aa2888..6051bf841 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The purpose of this tag type is to provide a mechanism to relate physical diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs index a073291ad..bf64e4fed 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type describes various screening parameters including diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs index 287f0efb0..87d369f85 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Typically this type is used for registered tags that can diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs index 8e6f4bc19..4134779c3 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Globalization; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The TextDescriptionType contains three types of text description. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs index ab3b3fb6f..6cf9e9154 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This is a simple text structure that contains a text string. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs index 464cbb9e7..3e4a5ff3a 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type represents an array of doubles (from 32bit values). diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs index 1e7a7f8a9..46799b16a 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type represents an array of unsigned shorts. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs index affdc8720..9fbbf8bf5 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type represents an array of unsigned 32bit integers. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs index 36d48d613..053181a26 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type represents an array of unsigned 64bit integers. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs index b2f267757..099916d89 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type represents an array of bytes. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs index 510930e39..d28b6edc9 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type contains curves representing the under color removal and black generation diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs index a0089e735..0227983fa 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This tag stores data of an unknown tag data entry diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs index bd636d4f2..2b2893c38 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// This type represents a set of viewing condition parameters. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs index c1c14d8cb..505b73a89 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs @@ -4,7 +4,7 @@ using System; using System.Numerics; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// The XYZType contains an array of XYZ values. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs index 3f7cad3af..c53ba9520 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Color Lookup Table diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs index 4bcd1b686..db1feea9a 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Entry of ICC colorant table diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs index 1920e97fe..b2852c8a3 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs @@ -4,7 +4,7 @@ using System; using System.Globalization; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A string with a specific locale. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLut.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLut.cs index c46d6884b..9e0c6c40d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLut.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLut.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Lookup Table diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs index b7cb5bc49..22bf1bb76 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A specific color with a name diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs index 745312f56..c9b75903d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Position of an object within an ICC profile diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs index 7e7c527ea..76ac5961d 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// ICC Profile description diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs index 710e6bb25..4a73f7e07 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// ICC Profile ID diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs index ae451c5db..9eb9fc7c3 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs @@ -4,7 +4,7 @@ using System; using System.Linq; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Description of a profile within a sequence. diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs index 8cae86992..859080263 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Associates a normalized device code with a measurement value diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs index 7e2072d5b..354442b47 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs @@ -4,7 +4,7 @@ using System; using System.Runtime.InteropServices; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// A single channel of a diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs index 7713c4faa..889dec41e 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Entry of ICC tag table diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccVersion.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccVersion.cs index 2486cc80a..b388fa5a4 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccVersion.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccVersion.cs @@ -3,7 +3,7 @@ using System; -namespace SixLabors.ImageSharp.MetaData.Profiles.Icc +namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// /// Represents the ICC profile version number. diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs index 0f71c732d..7633ed441 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs @@ -53,10 +53,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { // We will always be creating the clone even for mutate because we may need to resize the canvas IEnumerable> frames = - source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions, x.MetaData.DeepClone())); + source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions, x.Metadata.DeepClone())); // Use the overload to prevent an extra frame being added - return new Image(source.GetConfiguration(), source.MetaData.DeepClone(), frames); + return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); } /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs index a610ae5bb..5b9e3dde2 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; using SixLabors.Primitives; @@ -73,12 +73,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The private static OrientationMode GetExifOrientation(Image source) { - if (source.MetaData.ExifProfile is null) + if (source.Metadata.ExifProfile is null) { return OrientationMode.Unknown; } - ExifValue value = source.MetaData.ExifProfile.GetValue(ExifTag.Orientation); + ExifValue value = source.Metadata.ExifProfile.GetValue(ExifTag.Orientation); if (value is null) { return OrientationMode.Unknown; @@ -92,10 +92,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms else { orientation = (OrientationMode)Convert.ToUInt16(value.Value); - source.MetaData.ExifProfile.RemoveValue(ExifTag.Orientation); + source.Metadata.ExifProfile.RemoveValue(ExifTag.Orientation); } - source.MetaData.ExifProfile.SetValue(ExifTag.Orientation, (ushort)OrientationMode.TopLeft); + source.Metadata.ExifProfile.SetValue(ExifTag.Orientation, (ushort)OrientationMode.TopLeft); return orientation; } diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs index 3b1d7e94d..5baa196a0 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs @@ -39,10 +39,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.CropRectangle.Width, this.CropRectangle.Height, x.MetaData.DeepClone())); + IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.CropRectangle.Width, this.CropRectangle.Height, x.Metadata.DeepClone())); // Use the overload to prevent an extra frame being added - return new Image(source.GetConfiguration(), source.MetaData.DeepClone(), frames); + return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); } /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs index 8a5d7563f..6c7271c5e 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs @@ -53,10 +53,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { // We will always be creating the clone even for mutate because we may need to resize the canvas IEnumerable> frames = - source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions.Width, this.TargetDimensions.Height, x.MetaData.DeepClone())); + source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions.Width, this.TargetDimensions.Height, x.Metadata.DeepClone())); // Use the overload to prevent an extra frame being added - return new Image(source.GetConfiguration(), source.MetaData.DeepClone(), frames); + return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); } /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 2c186a276..21011ac71 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -151,10 +151,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.Width, this.Height, x.MetaData.DeepClone())); + IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.Width, this.Height, x.Metadata.DeepClone())); // Use the overload to prevent an extra frame being added - return new Image(source.GetConfiguration(), source.MetaData.DeepClone(), frames); + return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); } /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs index 69ecf5921..57902a5e6 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs @@ -5,7 +5,7 @@ using System; using System.Numerics; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// protected override void AfterImageApply(Image source, Image destination, Rectangle sourceRectangle) { - ExifProfile profile = destination.MetaData.ExifProfile; + ExifProfile profile = destination.Metadata.ExifProfile; if (profile is null) { return; diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs index f5536d046..7bb666bce 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Transforms @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public static void UpdateDimensionalMetData(Image image) where TPixel : struct, IPixel { - ExifProfile profile = image.MetaData.ExifProfile; + ExifProfile profile = image.Metadata.ExifProfile; if (profile is null) { return; diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index ad47ed1e7..05fadd458 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -13,7 +13,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests { - using SixLabors.ImageSharp.MetaData; + using SixLabors.ImageSharp.Metadata; using static TestImages.Bmp; public class BmpDecoderTests @@ -237,7 +237,7 @@ namespace SixLabors.ImageSharp.Tests var decoder = new BmpDecoder(); using (Image image = decoder.Decode(Configuration.Default, stream)) { - ImageMetaData meta = image.MetaData; + ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index f818be8a9..c9745ef4f 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -3,7 +3,7 @@ using System.IO; using SixLabors.ImageSharp.Formats.Bmp; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using Xunit; @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Tests memStream.Position = 0; using (var output = Image.Load(memStream)) { - ImageMetaData meta = output.MetaData; + ImageMetadata meta = output.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); @@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Tests memStream.Position = 0; using (var output = Image.Load(memStream)) { - BmpMetaData meta = output.MetaData.GetFormatMetaData(BmpFormat.Instance); + BmpMetadata meta = output.Metadata.GetFormatMetadata(BmpFormat.Instance); Assert.Equal(bmpBitsPerPixel, meta.BitsPerPixel); } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs index 991768a11..ab72214f6 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs @@ -11,8 +11,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [Fact] public void CloneIsDeep() { - var meta = new BmpMetaData() { BitsPerPixel = BmpBitsPerPixel.Pixel24 }; - var clone = (BmpMetaData)meta.DeepClone(); + var meta = new BmpMetadata() { BitsPerPixel = BmpBitsPerPixel.Pixel24 }; + var clone = (BmpMetadata)meta.DeepClone(); clone.BitsPerPixel = BmpBitsPerPixel.Pixel32; diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs index aed1edfbf..e8fdbd892 100644 --- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs +++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs @@ -27,8 +27,8 @@ namespace SixLabors.ImageSharp.Tests { using (Image image = provider.GetImage()) { - image.MetaData.VerticalResolution = 150; - image.MetaData.HorizontalResolution = 150; + image.Metadata.VerticalResolution = 150; + image.Metadata.HorizontalResolution = 150; image.DebugSave(provider); } } diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index 5bfbb058b..b13362aa3 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -7,7 +7,7 @@ using System.IO; using System.Text; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats.Gif; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using Xunit; @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif public static readonly TheoryData RatioFiles = new TheoryData { - { TestImages.Gif.Rings, (int)ImageMetaData.DefaultHorizontalResolution, (int)ImageMetaData.DefaultVerticalResolution , PixelResolutionUnit.PixelsPerInch}, + { TestImages.Gif.Rings, (int)ImageMetadata.DefaultHorizontalResolution, (int)ImageMetadata.DefaultVerticalResolution , PixelResolutionUnit.PixelsPerInch}, { TestImages.Gif.Ratio1x4, 1, 4 , PixelResolutionUnit.AspectRatio}, { TestImages.Gif.Ratio4x1, 4, 1, PixelResolutionUnit.AspectRatio } }; @@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var decoder = new GifDecoder(); using (Image image = decoder.Decode(Configuration.Default, stream)) { - ImageMetaData meta = image.MetaData; + ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); @@ -118,7 +118,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif { var decoder = new GifDecoder(); IImageInfo image = decoder.Identify(Configuration.Default, stream); - ImageMetaData meta = image.MetaData; + ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); @@ -167,9 +167,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif using (Image image = testFile.CreateImage(options)) { - Assert.Equal(1, image.MetaData.Properties.Count); - Assert.Equal("Comments", image.MetaData.Properties[0].Name); - Assert.Equal("ImageSharp", image.MetaData.Properties[0].Value); + Assert.Equal(1, image.Metadata.Properties.Count); + Assert.Equal("Comments", image.Metadata.Properties[0].Name); + Assert.Equal("ImageSharp", image.Metadata.Properties[0].Value); } } @@ -185,7 +185,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif using (Image image = testFile.CreateImage(options)) { - Assert.Equal(0, image.MetaData.Properties.Count); + Assert.Equal(0, image.Metadata.Properties.Count); } } @@ -201,8 +201,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif using (Image image = testFile.CreateImage(options)) { - Assert.Equal(1, image.MetaData.Properties.Count); - Assert.Equal("浉条卥慨灲", image.MetaData.Properties[0].Value); + Assert.Equal(1, image.Metadata.Properties.Count); + Assert.Equal("浉条卥慨灲", image.Metadata.Properties[0].Value); } } diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index b74a7a85f..cac4030d5 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -3,7 +3,7 @@ using System.IO; using SixLabors.ImageSharp.Formats.Gif; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif public static readonly TheoryData RatioFiles = new TheoryData { - { TestImages.Gif.Rings, (int)ImageMetaData.DefaultHorizontalResolution, (int)ImageMetaData.DefaultVerticalResolution , PixelResolutionUnit.PixelsPerInch}, + { TestImages.Gif.Rings, (int)ImageMetadata.DefaultHorizontalResolution, (int)ImageMetadata.DefaultVerticalResolution , PixelResolutionUnit.PixelsPerInch}, { TestImages.Gif.Ratio1x4, 1, 4 , PixelResolutionUnit.AspectRatio}, { TestImages.Gif.Ratio4x1, 4, 1, PixelResolutionUnit.AspectRatio } }; @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif memStream.Position = 0; using (var output = Image.Load(memStream)) { - ImageMetaData meta = output.MetaData; + ImageMetadata meta = output.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); @@ -92,9 +92,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif memStream.Position = 0; using (var output = Image.Load(memStream)) { - Assert.Equal(1, output.MetaData.Properties.Count); - Assert.Equal("Comments", output.MetaData.Properties[0].Name); - Assert.Equal("ImageSharp", output.MetaData.Properties[0].Value); + Assert.Equal(1, output.Metadata.Properties.Count); + Assert.Equal("Comments", output.Metadata.Properties[0].Name); + Assert.Equal("ImageSharp", output.Metadata.Properties[0].Value); } } } @@ -109,7 +109,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif using (Image input = testFile.CreateImage()) { - input.MetaData.Properties.Clear(); + input.Metadata.Properties.Clear(); using (var memStream = new MemoryStream()) { input.SaveAsGif(memStream, options); @@ -117,7 +117,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif memStream.Position = 0; using (var output = Image.Load(memStream)) { - Assert.Equal(0, output.MetaData.Properties.Count); + Assert.Equal(0, output.Metadata.Properties.Count); } } } @@ -129,7 +129,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif using (var input = new Image(1, 1)) { string comments = new string('c', 256); - input.MetaData.Properties.Add(new ImageProperty("Comments", comments)); + input.Metadata.Properties.Add(new ImageProperty("Comments", comments)); using (var memStream = new MemoryStream()) { @@ -138,9 +138,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif memStream.Position = 0; using (var output = Image.Load(memStream)) { - Assert.Equal(1, output.MetaData.Properties.Count); - Assert.Equal("Comments", output.MetaData.Properties[0].Name); - Assert.Equal(255, output.MetaData.Properties[0].Value.Length); + Assert.Equal(1, output.Metadata.Properties.Count); + Assert.Equal("Comments", output.Metadata.Properties[0].Name); + Assert.Equal(255, output.Metadata.Properties[0].Value.Length); } } } @@ -181,8 +181,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif inStream.Position = 0; var image = Image.Load(inStream); - GifMetaData metaData = image.MetaData.GetFormatMetaData(GifFormat.Instance); - GifFrameMetaData frameMetaData = image.Frames.RootFrame.MetaData.GetFormatMetaData(GifFormat.Instance); + GifMetadata metaData = image.Metadata.GetFormatMetadata(GifFormat.Instance); + GifFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetFormatMetadata(GifFormat.Instance); GifColorTableMode colorMode = metaData.ColorTableMode; var encoder = new GifEncoder() { @@ -196,7 +196,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif outStream.Position = 0; var clone = Image.Load(outStream); - GifMetaData cloneMetaData = clone.MetaData.GetFormatMetaData(GifFormat.Instance); + GifMetadata cloneMetaData = clone.Metadata.GetFormatMetadata(GifFormat.Instance); Assert.Equal(metaData.ColorTableMode, cloneMetaData.ColorTableMode); // Gifiddle and Cyotek GifInfo say this image has 64 colors. @@ -204,8 +204,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif for (int i = 0; i < image.Frames.Count; i++) { - GifFrameMetaData ifm = image.Frames[i].MetaData.GetFormatMetaData(GifFormat.Instance); - GifFrameMetaData cifm = clone.Frames[i].MetaData.GetFormatMetaData(GifFormat.Instance); + GifFrameMetadata ifm = image.Frames[i].Metadata.GetFormatMetadata(GifFormat.Instance); + GifFrameMetadata cifm = clone.Frames[i].Metadata.GetFormatMetadata(GifFormat.Instance); Assert.Equal(ifm.ColorTableLength, cifm.ColorTableLength); Assert.Equal(ifm.FrameDelay, cifm.FrameDelay); diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetaDataTests.cs index a39fc47b4..d82bfbf22 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetaDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetaDataTests.cs @@ -11,14 +11,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif [Fact] public void CloneIsDeep() { - var meta = new GifFrameMetaData() + var meta = new GifFrameMetadata() { FrameDelay = 1, DisposalMethod = GifDisposalMethod.RestoreToBackground, ColorTableLength = 2 }; - var clone = (GifFrameMetaData)meta.DeepClone(); + var clone = (GifFrameMetadata)meta.DeepClone(); clone.FrameDelay = 2; clone.DisposalMethod = GifDisposalMethod.RestoreToPrevious; diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifMetaDataTests.cs index 29db32b4a..8510a3461 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifMetaDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifMetaDataTests.cs @@ -11,14 +11,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif [Fact] public void CloneIsDeep() { - var meta = new GifMetaData() + var meta = new GifMetadata() { RepeatCount = 1, ColorTableMode = GifColorTableMode.Global, GlobalColorTableLength = 2 }; - var clone = (GifMetaData)meta.DeepClone(); + var clone = (GifMetadata)meta.DeepClone(); clone.RepeatCount = 2; clone.ColorTableMode = GifColorTableMode.Local; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs index b2dc3534d..aebf80d08 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs index 1f1583a39..48acc9ea4 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs @@ -3,8 +3,8 @@ using System.IO; using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Formats.Jpeg; - using SixLabors.ImageSharp.MetaData; + using SixLabors.ImageSharp.Metadata; public partial class JpegDecoderTests { @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var decoder = new JpegDecoder(); using (Image image = decoder.Decode(Configuration.Default, stream)) { - ImageMetaData meta = image.MetaData; + ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); @@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { var decoder = new JpegDecoder(); IImageInfo image = decoder.Identify(Configuration.Default, stream); - ImageMetaData meta = image.MetaData; + ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); @@ -118,7 +118,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { var decoder = new JpegDecoder(); IImageInfo image = decoder.Identify(Configuration.Default, stream); - JpegMetaData meta = image.MetaData.GetFormatMetaData(JpegFormat.Instance); + JpegMetadata meta = image.Metadata.GetFormatMetadata(JpegFormat.Instance); Assert.Equal(quality, meta.Quality); } } @@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var decoder = new JpegDecoder(); using (Image image = decoder.Decode(Configuration.Default, stream)) { - JpegMetaData meta = image.MetaData.GetFormatMetaData(JpegFormat.Instance); + JpegMetadata meta = image.Metadata.GetFormatMetadata(JpegFormat.Instance); Assert.Equal(quality, meta.Quality); } } @@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg Assert.Equal(bpp32, imageInfo.PixelType.BitsPerPixel); } - ExifProfile exifProfile = imageInfo.MetaData.ExifProfile; + ExifProfile exifProfile = imageInfo.Metadata.ExifProfile; if (exifProfilePresent) { @@ -192,7 +192,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg Assert.Null(exifProfile); } - IccProfile iccProfile = imageInfo.MetaData.IccProfile; + IccProfile iccProfile = imageInfo.Metadata.IccProfile; if (iccProfilePresent) { @@ -220,13 +220,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg { if (ignoreMetaData) { - Assert.Null(image.MetaData.ExifProfile); - Assert.Null(image.MetaData.IccProfile); + Assert.Null(image.Metadata.ExifProfile); + Assert.Null(image.Metadata.IccProfile); } else { - Assert.NotNull(image.MetaData.ExifProfile); - Assert.NotNull(image.MetaData.IccProfile); + Assert.NotNull(image.Metadata.ExifProfile); + Assert.NotNull(image.Metadata.IccProfile); } } } @@ -239,8 +239,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImageInfo(TestImages.Jpeg.Baseline.Floorplan, JpegDecoder, useIdentify, imageInfo => { - Assert.Equal(300, imageInfo.MetaData.HorizontalResolution); - Assert.Equal(300, imageInfo.MetaData.VerticalResolution); + Assert.Equal(300, imageInfo.Metadata.HorizontalResolution); + Assert.Equal(300, imageInfo.Metadata.VerticalResolution); }); } @@ -252,8 +252,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImageInfo(TestImages.Jpeg.Baseline.Jpeg420Exif, JpegDecoder, useIdentify, imageInfo => { - Assert.Equal(72, imageInfo.MetaData.HorizontalResolution); - Assert.Equal(72, imageInfo.MetaData.VerticalResolution); + Assert.Equal(72, imageInfo.Metadata.HorizontalResolution); + Assert.Equal(72, imageInfo.Metadata.VerticalResolution); }); } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs index 598d99274..618947130 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs @@ -3,7 +3,7 @@ using System.IO; using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg memStream.Position = 0; using (var output = Image.Load(memStream)) { - JpegMetaData meta = output.MetaData.GetFormatMetaData(JpegFormat.Instance); + JpegMetadata meta = output.Metadata.GetFormatMetadata(JpegFormat.Instance); Assert.Equal(quality, meta.Quality); } } @@ -189,7 +189,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg memStream.Position = 0; using (var output = Image.Load(memStream)) { - ImageMetaData meta = output.MetaData; + ImageMetadata meta = output.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegMetaDataTests.cs index 431de4be3..793bdd522 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegMetaDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegMetaDataTests.cs @@ -11,8 +11,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Fact] public void CloneIsDeep() { - var meta = new JpegMetaData() { Quality = 50 }; - var clone = (JpegMetaData)meta.DeepClone(); + var meta = new JpegMetadata() { Quality = 50 }; + var clone = (JpegMetadata)meta.DeepClone(); clone.Quality = 99; diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index fe406c992..0dbccd250 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -8,7 +8,7 @@ using System.IO; using System.Text; using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; @@ -204,9 +204,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png using (Image image = testFile.CreateImage(options)) { - Assert.Equal(1, image.MetaData.Properties.Count); - Assert.Equal("Software", image.MetaData.Properties[0].Name); - Assert.Equal("paint.net 4.0.6", image.MetaData.Properties[0].Value); + Assert.Equal(1, image.Metadata.Properties.Count); + Assert.Equal("Software", image.Metadata.Properties[0].Name); + Assert.Equal("paint.net 4.0.6", image.Metadata.Properties[0].Value); } } @@ -222,7 +222,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png using (Image image = testFile.CreateImage(options)) { - Assert.Equal(0, image.MetaData.Properties.Count); + Assert.Equal(0, image.Metadata.Properties.Count); } } @@ -238,8 +238,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png using (Image image = testFile.CreateImage(options)) { - Assert.Equal(1, image.MetaData.Properties.Count); - Assert.Equal("潓瑦慷敲", image.MetaData.Properties[0].Name); + Assert.Equal(1, image.Metadata.Properties.Count); + Assert.Equal("潓瑦慷敲", image.Metadata.Properties[0].Name); } } @@ -270,7 +270,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var decoder = new PngDecoder(); using (Image image = decoder.Decode(Configuration.Default, stream)) { - ImageMetaData meta = image.MetaData; + ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); @@ -287,7 +287,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png { var decoder = new PngDecoder(); IImageInfo image = decoder.Identify(Configuration.Default, stream); - ImageMetaData meta = image.MetaData; + ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index 9079b15fb..5aa69dd6a 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -7,7 +7,7 @@ using System.Linq; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; @@ -228,7 +228,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png memStream.Position = 0; using (var output = Image.Load(memStream)) { - ImageMetaData meta = output.MetaData; + ImageMetadata meta = output.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); Assert.Equal(yResolution, meta.VerticalResolution); Assert.Equal(resolutionUnit, meta.ResolutionUnits); @@ -253,7 +253,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png memStream.Position = 0; using (var output = Image.Load(memStream)) { - PngMetaData meta = output.MetaData.GetFormatMetaData(PngFormat.Instance); + PngMetadata meta = output.Metadata.GetFormatMetadata(PngFormat.Instance); Assert.Equal(pngBitDepth, meta.BitDepth); } @@ -270,7 +270,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var testFile = TestFile.Create(imagePath); using (Image input = testFile.CreateImage()) { - PngMetaData inMeta = input.MetaData.GetFormatMetaData(PngFormat.Instance); + PngMetadata inMeta = input.Metadata.GetFormatMetadata(PngFormat.Instance); Assert.True(inMeta.HasTrans); using (var memStream = new MemoryStream()) @@ -279,7 +279,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png memStream.Position = 0; using (var output = Image.Load(memStream)) { - PngMetaData outMeta = output.MetaData.GetFormatMetaData(PngFormat.Instance); + PngMetadata outMeta = output.Metadata.GetFormatMetadata(PngFormat.Instance); Assert.True(outMeta.HasTrans); switch (pngColorType) diff --git a/tests/ImageSharp.Tests/Formats/Png/PngMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngMetaDataTests.cs index a21bb9acb..72fc2f865 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngMetaDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngMetaDataTests.cs @@ -11,13 +11,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png [Fact] public void CloneIsDeep() { - var meta = new PngMetaData() + var meta = new PngMetadata() { BitDepth = PngBitDepth.Bit16, ColorType = PngColorType.GrayscaleWithAlpha, Gamma = 2 }; - var clone = (PngMetaData)meta.DeepClone(); + var clone = (PngMetadata)meta.DeepClone(); clone.BitDepth = PngBitDepth.Bit2; clone.ColorType = PngColorType.Palette; diff --git a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs index 16d999ad2..d51470292 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs @@ -9,7 +9,7 @@ using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Common.Helpers; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Shapes; using SixLabors.ImageSharp.Processing; @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Tests public void WrapMemory_CreatedImageIsCorrect() { Configuration cfg = Configuration.Default.Clone(); - var metaData = new ImageMetaData(); + var metaData = new ImageMetadata(); var array = new Rgba32[25]; var memory = new Memory(array); @@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Tests Assert.True(Unsafe.AreSame(ref array[0], ref pixel0)); Assert.Equal(cfg, image.GetConfiguration()); - Assert.Equal(metaData, image.MetaData); + Assert.Equal(metaData, image.Metadata); } } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.cs b/tests/ImageSharp.Tests/Image/ImageTests.cs index c5c7d19e1..60384c057 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.Memory; @@ -72,14 +72,14 @@ namespace SixLabors.ImageSharp.Tests byte dirtyValue = 123; configuration.MemoryAllocator = new TestMemoryAllocator(dirtyValue); - var metadata = new ImageMetaData(); + var metadata = new ImageMetadata(); using (Image image = Image.CreateUninitialized(configuration, 21, 22, metadata)) { Assert.Equal(21, image.Width); Assert.Equal(22, image.Height); Assert.Same(configuration, image.GetConfiguration()); - Assert.Same(metadata, image.MetaData); + Assert.Same(metadata, image.Metadata); Assert.Equal(dirtyValue, image[5, 5].PackedValue); } diff --git a/tests/ImageSharp.Tests/ImageInfoTests.cs b/tests/ImageSharp.Tests/ImageInfoTests.cs index 91f6804c0..67804a18f 100644 --- a/tests/ImageSharp.Tests/ImageInfoTests.cs +++ b/tests/ImageSharp.Tests/ImageInfoTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.Primitives; using Xunit; @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Tests var size = new Size(Width, Height); var rectangle = new Rectangle(0, 0, Width, Height); var pixelType = new PixelTypeInfo(8); - var meta = new ImageMetaData(); + var meta = new ImageMetadata(); var info = new ImageInfo(pixelType, Width, Height, meta); @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Tests Assert.Equal(Height, info.Height); Assert.Equal(size, info.Size()); Assert.Equal(rectangle, info.Bounds()); - Assert.Equal(meta, info.MetaData); + Assert.Equal(meta, info.Metadata); } } } diff --git a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs index 8c4903960..bafb117f7 100644 --- a/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs +++ b/tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Formats.Gif; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using Xunit; namespace SixLabors.ImageSharp.Tests @@ -19,14 +19,14 @@ namespace SixLabors.ImageSharp.Tests const int colorTableLength = 128; const GifDisposalMethod disposalMethod = GifDisposalMethod.RestoreToBackground; - var metaData = new ImageFrameMetaData(); - GifFrameMetaData gifFrameMetaData = metaData.GetFormatMetaData(GifFormat.Instance); + var metaData = new ImageFrameMetadata(); + GifFrameMetadata gifFrameMetaData = metaData.GetFormatMetadata(GifFormat.Instance); gifFrameMetaData.FrameDelay = frameDelay; gifFrameMetaData.ColorTableLength = colorTableLength; gifFrameMetaData.DisposalMethod = disposalMethod; - var clone = new ImageFrameMetaData(metaData); - GifFrameMetaData cloneGifFrameMetaData = clone.GetFormatMetaData(GifFormat.Instance); + var clone = new ImageFrameMetadata(metaData); + GifFrameMetadata cloneGifFrameMetaData = clone.GetFormatMetadata(GifFormat.Instance); Assert.Equal(frameDelay, cloneGifFrameMetaData.FrameDelay); Assert.Equal(colorTableLength, cloneGifFrameMetaData.ColorTableLength); @@ -36,9 +36,9 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void CloneIsDeep() { - var metaData = new ImageFrameMetaData(); - ImageFrameMetaData clone = metaData.DeepClone(); - Assert.False(metaData.GetFormatMetaData(GifFormat.Instance).Equals(clone.GetFormatMetaData(GifFormat.Instance))); + var metaData = new ImageFrameMetadata(); + ImageFrameMetadata clone = metaData.DeepClone(); + Assert.False(metaData.GetFormatMetadata(GifFormat.Instance).Equals(clone.GetFormatMetadata(GifFormat.Instance))); } } } diff --git a/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs index b9619cb3f..5f02ce7ae 100644 --- a/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs +++ b/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs @@ -2,8 +2,8 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Formats.Gif; -using SixLabors.ImageSharp.MetaData; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; @@ -12,14 +12,14 @@ using Xunit; namespace SixLabors.ImageSharp.Tests { /// - /// Tests the class. + /// Tests the class. /// public class ImageMetaDataTests { [Fact] public void ConstructorImageMetaData() { - var metaData = new ImageMetaData(); + var metaData = new ImageMetadata(); var exifProfile = new ExifProfile(); var imageProperty = new ImageProperty("name", "value"); @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Tests metaData.VerticalResolution = 2; metaData.Properties.Add(imageProperty); - ImageMetaData clone = metaData.DeepClone(); + ImageMetadata clone = metaData.DeepClone(); Assert.Equal(exifProfile.ToByteArray(), clone.ExifProfile.ToByteArray()); Assert.Equal(4, clone.HorizontalResolution); @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void CloneIsDeep() { - var metaData = new ImageMetaData(); + var metaData = new ImageMetadata(); var exifProfile = new ExifProfile(); var imageProperty = new ImageProperty("name", "value"); @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests metaData.VerticalResolution = 2; metaData.Properties.Add(imageProperty); - ImageMetaData clone = metaData.DeepClone(); + ImageMetadata clone = metaData.DeepClone(); clone.HorizontalResolution = 2; clone.VerticalResolution = 4; @@ -58,13 +58,13 @@ namespace SixLabors.ImageSharp.Tests Assert.False(metaData.HorizontalResolution.Equals(clone.HorizontalResolution)); Assert.False(metaData.VerticalResolution.Equals(clone.VerticalResolution)); Assert.False(metaData.Properties.Equals(clone.Properties)); - Assert.False(metaData.GetFormatMetaData(GifFormat.Instance).Equals(clone.GetFormatMetaData(GifFormat.Instance))); + Assert.False(metaData.GetFormatMetadata(GifFormat.Instance).Equals(clone.GetFormatMetadata(GifFormat.Instance))); } [Fact] public void HorizontalResolution() { - var metaData = new ImageMetaData(); + var metaData = new ImageMetadata(); Assert.Equal(96, metaData.HorizontalResolution); metaData.HorizontalResolution = 0; @@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void VerticalResolution() { - var metaData = new ImageMetaData(); + var metaData = new ImageMetadata(); Assert.Equal(96, metaData.VerticalResolution); metaData.VerticalResolution = 0; @@ -101,14 +101,14 @@ namespace SixLabors.ImageSharp.Tests exifProfile.SetValue(ExifTag.YResolution, new Rational(300)); var image = new Image(1, 1); - image.MetaData.ExifProfile = exifProfile; - image.MetaData.HorizontalResolution = 400; - image.MetaData.VerticalResolution = 500; + image.Metadata.ExifProfile = exifProfile; + image.Metadata.HorizontalResolution = 400; + image.Metadata.VerticalResolution = 500; - image.MetaData.SyncProfiles(); + image.Metadata.SyncProfiles(); - Assert.Equal(400, ((Rational)image.MetaData.ExifProfile.GetValue(ExifTag.XResolution).Value).ToDouble()); - Assert.Equal(500, ((Rational)image.MetaData.ExifProfile.GetValue(ExifTag.YResolution).Value).ToDouble()); + Assert.Equal(400, ((Rational)image.Metadata.ExifProfile.GetValue(ExifTag.XResolution).Value).ToDouble()); + Assert.Equal(500, ((Rational)image.Metadata.ExifProfile.GetValue(ExifTag.YResolution).Value).ToDouble()); } } } diff --git a/tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs b/tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs index b5886522a..8cce5ba41 100644 --- a/tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs +++ b/tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using Xunit; namespace SixLabors.ImageSharp.Tests diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs index c10ffb6c8..9d145f380 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs @@ -8,8 +8,8 @@ using System.IO; using System.Linq; using System.Text; using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; -using SixLabors.ImageSharp.MetaData; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; @@ -43,17 +43,17 @@ namespace SixLabors.ImageSharp.Tests { Image image = TestFile.Create(TestImages.Jpeg.Baseline.Calliphora).CreateImage(); - Assert.Null(image.MetaData.ExifProfile); + Assert.Null(image.Metadata.ExifProfile); - image.MetaData.ExifProfile = new ExifProfile(); - image.MetaData.ExifProfile.SetValue(ExifTag.Copyright, "Dirk Lemstra"); + image.Metadata.ExifProfile = new ExifProfile(); + image.Metadata.ExifProfile.SetValue(ExifTag.Copyright, "Dirk Lemstra"); image = WriteAndRead(image, imageFormat); - Assert.NotNull(image.MetaData.ExifProfile); - Assert.Equal(1, image.MetaData.ExifProfile.Values.Count()); + Assert.NotNull(image.Metadata.ExifProfile); + Assert.Equal(1, image.Metadata.ExifProfile.Values.Count()); - ExifValue value = image.MetaData.ExifProfile.Values.FirstOrDefault(val => val.Tag == ExifTag.Copyright); + ExifValue value = image.Metadata.ExifProfile.Values.FirstOrDefault(val => val.Tag == ExifTag.Copyright); TestValue(value, "Dirk Lemstra"); } @@ -94,11 +94,11 @@ namespace SixLabors.ImageSharp.Tests profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime)); var image = new Image(1, 1); - image.MetaData.ExifProfile = profile; + image.Metadata.ExifProfile = profile; image = WriteAndRead(image, imageFormat); - profile = image.MetaData.ExifProfile; + profile = image.Metadata.ExifProfile; Assert.NotNull(profile); ExifValue value = profile.GetValue(ExifTag.ExposureTime); @@ -109,11 +109,11 @@ namespace SixLabors.ImageSharp.Tests profile = GetExifProfile(); profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime, true)); - image.MetaData.ExifProfile = profile; + image.Metadata.ExifProfile = profile; image = WriteAndRead(image, imageFormat); - profile = image.MetaData.ExifProfile; + profile = image.Metadata.ExifProfile; Assert.NotNull(profile); value = profile.GetValue(ExifTag.ExposureTime); @@ -127,24 +127,24 @@ namespace SixLabors.ImageSharp.Tests public void ReadWriteInfinity(TestImageWriteFormat imageFormat) { Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage(); - image.MetaData.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.PositiveInfinity)); + image.Metadata.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.PositiveInfinity)); image = WriteAndReadJpeg(image); - ExifValue value = image.MetaData.ExifProfile.GetValue(ExifTag.ExposureBiasValue); + ExifValue value = image.Metadata.ExifProfile.GetValue(ExifTag.ExposureBiasValue); Assert.NotNull(value); Assert.Equal(new SignedRational(double.PositiveInfinity), value.Value); - image.MetaData.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.NegativeInfinity)); + image.Metadata.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.NegativeInfinity)); image = WriteAndRead(image, imageFormat); - value = image.MetaData.ExifProfile.GetValue(ExifTag.ExposureBiasValue); + value = image.Metadata.ExifProfile.GetValue(ExifTag.ExposureBiasValue); Assert.NotNull(value); Assert.Equal(new SignedRational(double.NegativeInfinity), value.Value); - image.MetaData.ExifProfile.SetValue(ExifTag.FlashEnergy, new Rational(double.NegativeInfinity)); + image.Metadata.ExifProfile.SetValue(ExifTag.FlashEnergy, new Rational(double.NegativeInfinity)); image = WriteAndRead(image, imageFormat); - value = image.MetaData.ExifProfile.GetValue(ExifTag.FlashEnergy); + value = image.Metadata.ExifProfile.GetValue(ExifTag.FlashEnergy); Assert.NotNull(value); Assert.Equal(new Rational(double.PositiveInfinity), value.Value); } @@ -157,74 +157,74 @@ namespace SixLabors.ImageSharp.Tests var latitude = new Rational[] { new Rational(12.3), new Rational(4.56), new Rational(789.0) }; Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage(); - image.MetaData.ExifProfile.SetValue(ExifTag.Software, "ImageSharp"); + image.Metadata.ExifProfile.SetValue(ExifTag.Software, "ImageSharp"); - ExifValue value = image.MetaData.ExifProfile.GetValue(ExifTag.Software); + ExifValue value = image.Metadata.ExifProfile.GetValue(ExifTag.Software); TestValue(value, "ImageSharp"); Assert.Throws(() => { value.WithValue(15); }); - image.MetaData.ExifProfile.SetValue(ExifTag.ShutterSpeedValue, new SignedRational(75.55)); + image.Metadata.ExifProfile.SetValue(ExifTag.ShutterSpeedValue, new SignedRational(75.55)); - value = image.MetaData.ExifProfile.GetValue(ExifTag.ShutterSpeedValue); + value = image.Metadata.ExifProfile.GetValue(ExifTag.ShutterSpeedValue); TestValue(value, new SignedRational(7555, 100)); Assert.Throws(() => { value.WithValue(75); }); - image.MetaData.ExifProfile.SetValue(ExifTag.XResolution, new Rational(150.0)); + image.Metadata.ExifProfile.SetValue(ExifTag.XResolution, new Rational(150.0)); // We also need to change this value because this overrides XResolution when the image is written. - image.MetaData.HorizontalResolution = 150.0; + image.Metadata.HorizontalResolution = 150.0; - value = image.MetaData.ExifProfile.GetValue(ExifTag.XResolution); + value = image.Metadata.ExifProfile.GetValue(ExifTag.XResolution); TestValue(value, new Rational(150, 1)); Assert.Throws(() => { value.WithValue("ImageSharp"); }); - image.MetaData.ExifProfile.SetValue(ExifTag.ReferenceBlackWhite, null); + image.Metadata.ExifProfile.SetValue(ExifTag.ReferenceBlackWhite, null); - value = image.MetaData.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite); + value = image.Metadata.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite); TestValue(value, (string)null); - image.MetaData.ExifProfile.SetValue(ExifTag.GPSLatitude, latitude); + image.Metadata.ExifProfile.SetValue(ExifTag.GPSLatitude, latitude); - value = image.MetaData.ExifProfile.GetValue(ExifTag.GPSLatitude); + value = image.Metadata.ExifProfile.GetValue(ExifTag.GPSLatitude); TestValue(value, latitude); image = WriteAndRead(image, imageFormat); - Assert.NotNull(image.MetaData.ExifProfile); - Assert.Equal(17, image.MetaData.ExifProfile.Values.Count()); + Assert.NotNull(image.Metadata.ExifProfile); + Assert.Equal(17, image.Metadata.ExifProfile.Values.Count()); - value = image.MetaData.ExifProfile.GetValue(ExifTag.Software); + value = image.Metadata.ExifProfile.GetValue(ExifTag.Software); TestValue(value, "ImageSharp"); - value = image.MetaData.ExifProfile.GetValue(ExifTag.ShutterSpeedValue); + value = image.Metadata.ExifProfile.GetValue(ExifTag.ShutterSpeedValue); TestValue(value, new SignedRational(75.55)); - value = image.MetaData.ExifProfile.GetValue(ExifTag.XResolution); + value = image.Metadata.ExifProfile.GetValue(ExifTag.XResolution); TestValue(value, new Rational(150.0)); - value = image.MetaData.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite); + value = image.Metadata.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite); Assert.Null(value); - value = image.MetaData.ExifProfile.GetValue(ExifTag.GPSLatitude); + value = image.Metadata.ExifProfile.GetValue(ExifTag.GPSLatitude); TestValue(value, latitude); - image.MetaData.ExifProfile.Parts = ExifParts.ExifTags; + image.Metadata.ExifProfile.Parts = ExifParts.ExifTags; image = WriteAndRead(image, imageFormat); - Assert.NotNull(image.MetaData.ExifProfile); - Assert.Equal(8, image.MetaData.ExifProfile.Values.Count()); + Assert.NotNull(image.Metadata.ExifProfile); + Assert.Equal(8, image.Metadata.ExifProfile.Values.Count()); - Assert.NotNull(image.MetaData.ExifProfile.GetValue(ExifTag.ColorSpace)); - Assert.True(image.MetaData.ExifProfile.RemoveValue(ExifTag.ColorSpace)); - Assert.False(image.MetaData.ExifProfile.RemoveValue(ExifTag.ColorSpace)); - Assert.Null(image.MetaData.ExifProfile.GetValue(ExifTag.ColorSpace)); + Assert.NotNull(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace)); + Assert.True(image.Metadata.ExifProfile.RemoveValue(ExifTag.ColorSpace)); + Assert.False(image.Metadata.ExifProfile.RemoveValue(ExifTag.ColorSpace)); + Assert.Null(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace)); - Assert.Equal(7, image.MetaData.ExifProfile.Values.Count()); + Assert.Equal(7, image.Metadata.ExifProfile.Values.Count()); } [Fact] @@ -234,7 +234,7 @@ namespace SixLabors.ImageSharp.Tests exifProfile.SetValue(ExifTag.XResolution, new Rational(200)); exifProfile.SetValue(ExifTag.YResolution, new Rational(300)); - var metaData = new ImageMetaData + var metaData = new ImageMetadata { ExifProfile = exifProfile, HorizontalResolution = 200, @@ -292,13 +292,13 @@ namespace SixLabors.ImageSharp.Tests ExifProfile expectedProfile = CreateExifProfile(); var expectedProfileTags = expectedProfile.Values.Select(x => x.Tag).ToList(); expectedProfile.SetValue(exifValueToChange, junk.ToString()); - image.MetaData.ExifProfile = expectedProfile; + image.Metadata.ExifProfile = expectedProfile; // act Image reloadedImage = WriteAndRead(image, TestImageWriteFormat.Jpeg); // assert - ExifProfile actualProfile = reloadedImage.MetaData.ExifProfile; + ExifProfile actualProfile = reloadedImage.Metadata.ExifProfile; Assert.NotNull(actualProfile); foreach (ExifTag expectedProfileTag in expectedProfileTags) { @@ -317,7 +317,7 @@ namespace SixLabors.ImageSharp.Tests Image image = TestFile.Create(TestImages.Jpeg.Progressive.Bad.ExifUndefType).CreateImage(); Assert.NotNull(image); - ExifProfile profile = image.MetaData.ExifProfile; + ExifProfile profile = image.Metadata.ExifProfile; Assert.NotNull(profile); foreach (ExifValue value in profile.Values) @@ -335,7 +335,7 @@ namespace SixLabors.ImageSharp.Tests // This images contains array in the exif profile that has zero components. Image image = TestFile.Create(TestImages.Jpeg.Issues.InvalidCast520).CreateImage(); - ExifProfile profile = image.MetaData.ExifProfile; + ExifProfile profile = image.Metadata.ExifProfile; Assert.NotNull(profile); // Force parsing of the profile. @@ -353,13 +353,13 @@ namespace SixLabors.ImageSharp.Tests // arrange var image = new Image(1, 1); ExifProfile expected = CreateExifProfile(); - image.MetaData.ExifProfile = expected; + image.Metadata.ExifProfile = expected; // act Image reloadedImage = WriteAndRead(image, imageFormat); // assert - ExifProfile actual = reloadedImage.MetaData.ExifProfile; + ExifProfile actual = reloadedImage.Metadata.ExifProfile; Assert.NotNull(actual); foreach (KeyValuePair expectedProfileValue in TestProfileValues) { @@ -410,7 +410,7 @@ namespace SixLabors.ImageSharp.Tests { Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage(); - ExifProfile profile = image.MetaData.ExifProfile; + ExifProfile profile = image.Metadata.ExifProfile; Assert.NotNull(profile); return profile; diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifReaderTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifReaderTests.cs index c9542a98a..19ff7d269 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifReaderTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifReaderTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System.Collections.Generic; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using Xunit; namespace SixLabors.ImageSharp.Tests diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifTagDescriptionAttributeTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifTagDescriptionAttributeTests.cs index 2b8d4d716..144a6e4a3 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifTagDescriptionAttributeTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifTagDescriptionAttributeTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using Xunit; namespace SixLabors.ImageSharp.Tests diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs index 8bc192af5..4327cae33 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System.Linq; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.Tests ExifProfile profile; using (Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage()) { - profile = image.MetaData.ExifProfile; + profile = image.Metadata.ExifProfile; } Assert.NotNull(profile); diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.CurvesTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.CurvesTests.cs index beca4db49..b6fa98b61 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.CurvesTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.CurvesTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.LutTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.LutTests.cs index 43a1ed7f4..04284cb49 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.LutTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.LutTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.MatrixTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.MatrixTests.cs index 328cc3fa6..7987e9410 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.MatrixTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.MatrixTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.MultiProcessElementTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.MultiProcessElementTests.cs index 5599e80d1..f9e5428cd 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.MultiProcessElementTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.MultiProcessElementTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs index 86f308ea1..6296390a0 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs @@ -3,7 +3,7 @@ using System; using System.Numerics; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.PrimitivesTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.PrimitivesTests.cs index f8924c43c..e73ee7c9e 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.PrimitivesTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.PrimitivesTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs index aba587846..dc2c5b6ac 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReaderTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReaderTests.cs index a3e5a20f6..fc3502e3e 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReaderTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReaderTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.CurvesTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.CurvesTests.cs index 6a47c988c..585bda648 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.CurvesTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.CurvesTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.LutTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.LutTests.cs index 9286ac815..621673ce4 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.LutTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.LutTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MatrixTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MatrixTests.cs index 71dd18621..b43c17f79 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MatrixTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MatrixTests.cs @@ -3,7 +3,7 @@ using System.Numerics; using SixLabors.Memory; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElementTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElementTests.cs index 43165c617..829b556af 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElementTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElementTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs index 1d482e2c1..ed8a10551 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs @@ -3,7 +3,7 @@ using System; using System.Numerics; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.PrimitivesTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.PrimitivesTests.cs index 845a149b5..098950be8 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.PrimitivesTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.PrimitivesTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs index f3ef5effb..269a8d561 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriterTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriterTests.cs index a3f796275..b7b446699 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriterTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriterTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs index 17b5dacc4..a1944669d 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccProfileTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccReaderTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccReaderTests.cs index c91076afc..b4ed52a3d 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccReaderTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccReaderTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccWriterTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccWriterTests.cs index 99ae73f49..43c27335a 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccWriterTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccWriterTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/Various/IccProfileIdTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/Various/IccProfileIdTests.cs index 46b8b31b4..5c80ac36b 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/Various/IccProfileIdTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/Various/IccProfileIdTests.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; using Xunit; namespace SixLabors.ImageSharp.Tests.Icc diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs index 9b37fb266..28b01061e 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; @@ -45,8 +45,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { using (Image image = provider.GetImage()) { - image.MetaData.ExifProfile = new ExifProfile(); - image.MetaData.ExifProfile.SetValue(ExifTag.Orientation, orientation); + image.Metadata.ExifProfile = new ExifProfile(); + image.Metadata.ExifProfile.SetValue(ExifTag.Orientation, orientation); image.Mutate(x => x.RotateFlip(rotateType, flipType)); image.DebugSave(provider, string.Join("_", rotateType, flipType, orientation, "1_before")); @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms using (Image image = provider.GetImage()) { - image.MetaData.ExifProfile = new ExifProfile(bytes); + image.Metadata.ExifProfile = new ExifProfile(bytes); image.Mutate(x => x.AutoOrient()); } } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs index 909e50535..a62f4fc7c 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Transforms; using Xunit; @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms using (var img = new Image(xy, xy)) { var profile = new ExifProfile(); - img.MetaData.ExifProfile = profile; + img.Metadata.ExifProfile = profile; profile.SetValue(ExifTag.PixelXDimension, (uint)xy); profile.SetValue(ExifTag.PixelYDimension, (uint)xy); diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs index b39892a81..334ee026d 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataCurves.cs @@ -2,7 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System.Numerics; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; namespace SixLabors.ImageSharp.Tests { diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataLut.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataLut.cs index 4ab0b0f6b..5ef2156c7 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataLut.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataLut.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; namespace SixLabors.ImageSharp.Tests { diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMultiProcessElements.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMultiProcessElements.cs index fb648198d..586e84680 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMultiProcessElements.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataMultiProcessElements.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; namespace SixLabors.ImageSharp.Tests { diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs index f16da90c6..f19029f8c 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs @@ -4,7 +4,7 @@ using System; using System.Globalization; using System.Numerics; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; namespace SixLabors.ImageSharp.Tests { diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs index b037a7a9a..49ff19046 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs @@ -3,7 +3,7 @@ using System; using System.Numerics; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; namespace SixLabors.ImageSharp.Tests { diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs index f7c4efa92..b5da22443 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Numerics; -using SixLabors.ImageSharp.MetaData.Profiles.Icc; +using SixLabors.ImageSharp.Metadata.Profiles.Icc; namespace SixLabors.ImageSharp.Tests { diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs index 427a56542..7a775c081 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs @@ -4,7 +4,7 @@ using System.IO; using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.MetaData; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs using (var sourceBitmap = new System.Drawing.Bitmap(stream)) { var pixelType = new PixelTypeInfo(System.Drawing.Image.GetPixelFormatSize(sourceBitmap.PixelFormat)); - return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetaData()); + return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetadata()); } } } From cb189525e37b60816ad5cca6c5dc96d2b69a3949 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Sat, 13 Apr 2019 07:40:48 -0500 Subject: [PATCH 054/223] Nits - Colorspaces (#880) * Add missing periods * Only perform matrix inversion once in CieXyzToLinearRgbConverter * Eliminate unnessary ToVector3 call * Seal GammaWorkingSpace * Address stylecop violation * Add periods * Fix colorspace companding --- .../ColorSpaces/CieXyChromaticityCoordinates.cs | 2 +- .../ColorSpaces/Companding/GammaCompanding.cs | 2 +- .../ColorSpaces/Companding/LCompanding.cs | 6 +++--- .../ColorSpaces/Companding/Rec2020Companding.cs | 13 +++++++++---- .../ColorSpaces/Companding/Rec709Companding.cs | 6 ++++-- .../Conversion/ColorSpaceConverter.CieLch.cs | 2 -- .../Converters/CieXyzAndCieXyyConverter.cs | 2 +- .../Converters/CieXyzToLinearRgbConverter.cs | 14 +++++++++----- .../Converters/CmykAndRgbConverter.cs | 4 ++-- .../Converters/LinearRgbToRgbConverter.cs | 15 +++++++-------- .../Converters/RgbToLinearRgbConverter.cs | 15 +++++++-------- .../Converters/YCbCrAndRgbConverter.cs | 4 ++-- .../WorkingSpaces/GammaWorkingSpace.cs | 2 +- .../Colorspaces/Companding/CompandingTests.cs | 15 ++++++--------- 14 files changed, 53 insertions(+), 49 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs index 49c1da9f1..8e14274f6 100644 --- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs @@ -8,7 +8,7 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces { /// - /// Represents the coordinates of CIEXY chromaticity space + /// Represents the coordinates of CIEXY chromaticity space. /// public readonly struct CieXyChromaticityCoordinates : IEquatable { diff --git a/src/ImageSharp/ColorSpaces/Companding/GammaCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/GammaCompanding.cs index 13cca1582..09b324b00 100644 --- a/src/ImageSharp/ColorSpaces/Companding/GammaCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/GammaCompanding.cs @@ -7,7 +7,7 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces.Companding { /// - /// Implements gamma companding + /// Implements gamma companding. /// /// /// diff --git a/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs index 9e2cf8ad8..80b8aee7e 100644 --- a/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs @@ -8,7 +8,7 @@ using SixLabors.ImageSharp.ColorSpaces.Conversion; namespace SixLabors.ImageSharp.ColorSpaces.Companding { /// - /// Implements L* companding + /// Implements L* companding. /// /// /// For more info see: @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// The representing the linear channel value. [MethodImpl(InliningOptions.ShortMethod)] public static float Expand(float channel) - => channel <= 0.08 ? 100 * channel / CieConstants.Kappa : ImageMaths.Pow3((channel + 0.16F) / 1.16F); + => channel <= 0.08F ? (100F * channel) / CieConstants.Kappa : ImageMaths.Pow3((channel + 0.16F) / 1.16F); /// /// Compresses an uncompanded channel (linear) to its nonlinear equivalent. @@ -33,6 +33,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// The representing the nonlinear channel value. [MethodImpl(InliningOptions.ShortMethod)] public static float Compress(float channel) - => channel <= CieConstants.Epsilon ? channel * CieConstants.Kappa / 100F : MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F; + => channel <= CieConstants.Epsilon ? (channel * CieConstants.Kappa) / 100F : (1.16F * MathF.Pow(channel, 0.3333333F)) - 0.16F; } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Companding/Rec2020Companding.cs b/src/ImageSharp/ColorSpaces/Companding/Rec2020Companding.cs index a3a912172..773fe8164 100644 --- a/src/ImageSharp/ColorSpaces/Companding/Rec2020Companding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/Rec2020Companding.cs @@ -7,14 +7,19 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces.Companding { /// - /// Implements Rec. 2020 companding function (for 12-bits). + /// Implements Rec. 2020 companding function. /// /// /// - /// For 10-bits, companding is identical to /// public static class Rec2020Companding { + private const float Alpha = 1.09929682680944F; + private const float AlphaMinusOne = Alpha - 1F; + private const float Beta = 0.018053968510807F; + private const float InverseBeta = Beta * 4.5F; + private const float Epsilon = 1 / 0.45F; + /// /// Expands a companded channel to its linear equivalent with respect to the energy. /// @@ -22,7 +27,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// The representing the linear channel value. [MethodImpl(InliningOptions.ShortMethod)] public static float Expand(float channel) - => channel < 0.08145F ? channel / 4.5F : MathF.Pow((channel + 0.0993F) / 1.0993F, 2.222222F); + => channel < InverseBeta ? channel / 4.5F : MathF.Pow((channel + AlphaMinusOne) / Alpha, Epsilon); /// /// Compresses an uncompanded channel (linear) to its nonlinear equivalent. @@ -31,6 +36,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// The representing the nonlinear channel value. [MethodImpl(InliningOptions.ShortMethod)] public static float Compress(float channel) - => channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F; + => channel < Beta ? 4.5F * channel : (Alpha * MathF.Pow(channel, 0.45F)) - AlphaMinusOne; } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Companding/Rec709Companding.cs b/src/ImageSharp/ColorSpaces/Companding/Rec709Companding.cs index e2e802d08..edc0b9763 100644 --- a/src/ImageSharp/ColorSpaces/Companding/Rec709Companding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/Rec709Companding.cs @@ -14,6 +14,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// public static class Rec709Companding { + private const float Epsilon = 1 / 0.45F; + /// /// Expands a companded channel to its linear equivalent with respect to the energy. /// @@ -21,7 +23,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// The representing the linear channel value. [MethodImpl(InliningOptions.ShortMethod)] public static float Expand(float channel) - => channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F); + => channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, Epsilon); /// /// Compresses an uncompanded channel (linear) to its nonlinear equivalent. @@ -30,6 +32,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// The representing the nonlinear channel value. [MethodImpl(InliningOptions.ShortMethod)] public static float Compress(float channel) - => channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F; + => channel < 0.018F ? 4.5F * channel : (1.099F * MathF.Pow(channel, 0.45F)) - 0.099F; } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs index 381073619..7f4abfa7b 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs @@ -26,10 +26,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLch ToCieLch(in CieLab color) { - // Adaptation CieLab adapted = this.Adapt(color); - // Conversion return CieLabToCieLchConverter.Convert(adapted); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs index f33d1ddcc..7767b7b44 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs @@ -7,7 +7,7 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation { /// - /// Color converter between CIE XYZ and CIE xyY + /// Color converter between CIE XYZ and CIE xyY. /// for formulas. /// internal sealed class CieXyzAndCieXyyConverter diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs index 3812cdbdd..f166e4c14 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs @@ -28,11 +28,15 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation public CieXyzToLinearRgbConverter(RgbWorkingSpaceBase workingSpace) { this.TargetWorkingSpace = workingSpace; - this.conversionMatrix = GetRgbToCieXyzMatrix(workingSpace); + + // Gets the inverted Rgb -> Xyz matrix + Matrix4x4.Invert(GetRgbToCieXyzMatrix(workingSpace), out Matrix4x4 inverted); + + this.conversionMatrix = inverted; } /// - /// Gets the target working space + /// Gets the target working space. /// public RgbWorkingSpaceBase TargetWorkingSpace { get; } @@ -40,12 +44,12 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// Performs the conversion from the input to an instance of type. /// /// The input color instance. - /// The converted result + /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] public LinearRgb Convert(in CieXyz input) { - Matrix4x4.Invert(this.conversionMatrix, out Matrix4x4 inverted); - var vector = Vector3.Transform(input.ToVector3(), inverted); + var vector = Vector3.Transform(input.ToVector3(), this.conversionMatrix); + return new LinearRgb(vector, this.TargetWorkingSpace); } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs index 29fd32905..0700dab43 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs @@ -8,7 +8,7 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation { /// - /// Color converter between and + /// Color converter between and . /// internal sealed class CmykAndRgbConverter { @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// Performs the conversion from the input to an instance of type. /// /// The input color instance. - /// The converted result + /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] public Cmyk Convert(in Rgb input) { diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs index 1cc055bee..845443093 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs @@ -6,7 +6,7 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation { /// - /// Color converter between and + /// Color converter between and . /// internal sealed class LinearRgbToRgbConverter { @@ -14,16 +14,15 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// Performs the conversion from the input to an instance of type. /// /// The input color instance. - /// The converted result + /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] public Rgb Convert(in LinearRgb input) { - var vector = input.ToVector3(); - vector.X = input.WorkingSpace.Compress(vector.X); - vector.Y = input.WorkingSpace.Compress(vector.Y); - vector.Z = input.WorkingSpace.Compress(vector.Z); - - return new Rgb(vector, input.WorkingSpace); + return new Rgb( + r: input.WorkingSpace.Compress(input.R), + g: input.WorkingSpace.Compress(input.G), + b: input.WorkingSpace.Compress(input.B), + workingSpace: input.WorkingSpace); } } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs index 03912a421..4ddbe42e5 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs @@ -6,7 +6,7 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation { /// - /// Color converter between Rgb and LinearRgb + /// Color converter between Rgb and LinearRgb. /// internal class RgbToLinearRgbConverter { @@ -14,16 +14,15 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// Performs the conversion from the input to an instance of type. /// /// The input color instance. - /// The converted result + /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] public LinearRgb Convert(in Rgb input) { - var vector = input.ToVector3(); - vector.X = input.WorkingSpace.Expand(vector.X); - vector.Y = input.WorkingSpace.Expand(vector.Y); - vector.Z = input.WorkingSpace.Expand(vector.Z); - - return new LinearRgb(vector, input.WorkingSpace); + return new LinearRgb( + r: input.WorkingSpace.Expand(input.R), + g: input.WorkingSpace.Expand(input.G), + b: input.WorkingSpace.Expand(input.B), + workingSpace: input.WorkingSpace); } } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs index 4ac3ad3cf..ee15ffa50 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// Performs the conversion from the input to an instance of type. /// /// The input color instance. - /// The converted result + /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] public Rgb Convert(in YCbCr input) { @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// Performs the conversion from the input to an instance of type. /// /// The input color instance. - /// The converted result + /// The converted result. [MethodImpl(InliningOptions.ShortMethod)] public YCbCr Convert(in Rgb input) { diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs index 639d0b293..c45dea317 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// /// The gamma working space. /// - public class GammaWorkingSpace : RgbWorkingSpaceBase + public sealed class GammaWorkingSpace : RgbWorkingSpaceBase { /// /// Initializes a new instance of the class. diff --git a/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs b/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs index b2ee03048..e1386e1a0 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; using System.Numerics; using SixLabors.ImageSharp.ColorSpaces.Companding; using Xunit; @@ -10,9 +9,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Colorspaces.Companding { /// - /// Tests various companding algorithms. Numbers are hand calculated from formulas online. - /// TODO: Oddly the formula for converting to/from Rec 2020 and 709 from Wikipedia seems to cause the value to - /// fail a round trip. They're large spaces so this is a surprise. More reading required!! + /// Tests various companding algorithms. Expanded numbers are hand calculated from formulas online. /// public class CompandingTests { @@ -24,7 +21,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Companding const float input = .667F; float e = Rec2020Companding.Expand(input); float c = Rec2020Companding.Compress(e); - CompandingIsCorrectImpl(e, c, .4484759F, .3937096F); + CompandingIsCorrectImpl(e, c, .4484759F, input); } [Fact] @@ -33,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Companding const float input = .667F; float e = Rec709Companding.Expand(input); float c = Rec709Companding.Compress(e); - CompandingIsCorrectImpl(e, c, .4483577F, .3937451F); + CompandingIsCorrectImpl(e, c, .4483577F, input); } [Fact] @@ -42,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Companding const float input = .667F; float e = SRgbCompanding.Expand(input); float c = SRgbCompanding.Compress(e); - CompandingIsCorrectImpl(e, c, .40242353F, .667F); + CompandingIsCorrectImpl(e, c, .40242353F, input); } [Theory] @@ -98,7 +95,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Companding const float input = .667F; float e = GammaCompanding.Expand(input, gamma); float c = GammaCompanding.Compress(e, gamma); - CompandingIsCorrectImpl(e, c, .41027668F, .667F); + CompandingIsCorrectImpl(e, c, .41027668F, input); } [Fact] @@ -107,7 +104,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Companding const float input = .667F; float e = LCompanding.Expand(input); float c = LCompanding.Compress(e); - CompandingIsCorrectImpl(e, c, .36236193F, .58908917F); + CompandingIsCorrectImpl(e, c, .36236193F, input); } private static void CompandingIsCorrectImpl(float e, float c, float expanded, float compressed) From 45edceb0bc8ca6781d77409779cc95a7da813b6a Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 14 Apr 2019 08:01:38 +1000 Subject: [PATCH 055/223] Use more accuracy when calculating variance. Fix #866 (#874) * Use more accuracy when calculating variance. Fix #866 * Add unit tests * Add test that fails with old image. * Make IFrameQuantizer IDisposable * Update GifEncoderCore.cs --- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 24 +- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 7 +- .../FrameQuantizerBase{TPixel}.cs | 5 + .../Quantization/IFrameQuantizer{TPixel}.cs | 3 +- .../Quantization/QuantizeProcessor.cs | 2 +- .../Quantization/WuFrameQuantizer{TPixel}.cs | 416 ++++++++++-------- .../Quantization/WuQuantizerTests.cs | 168 +++++++ tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Png/low-variance.png | Bin 0 -> 7844 bytes 9 files changed, 422 insertions(+), 204 deletions(-) create mode 100644 tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs create mode 100644 tests/Images/Input/Png/low-variance.png diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index e5a5463eb..12a515cca 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -95,8 +95,11 @@ namespace SixLabors.ImageSharp.Formats.Gif bool useGlobalTable = this.colorTableMode == GifColorTableMode.Global; // Quantize the image returning a palette. - QuantizedFrame quantized = - this.quantizer.CreateFrameQuantizer(image.GetConfiguration()).QuantizeFrame(image.Frames.RootFrame); + QuantizedFrame quantized = null; + using (IFrameQuantizer frameQuantizer = this.quantizer.CreateFrameQuantizer(image.GetConfiguration())) + { + quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame); + } // Get the number of bits. this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8); @@ -133,7 +136,6 @@ namespace SixLabors.ImageSharp.Formats.Gif // Clean up. quantized?.Dispose(); - quantized = null; // TODO: Write extension etc stream.WriteByte(GifConstants.EndIntroducer); @@ -158,7 +160,8 @@ namespace SixLabors.ImageSharp.Formats.Gif } else { - using (QuantizedFrame paletteQuantized = palleteQuantizer.CreateFrameQuantizer(image.GetConfiguration()).QuantizeFrame(frame)) + using (IFrameQuantizer palleteFrameQuantizer = palleteQuantizer.CreateFrameQuantizer(image.GetConfiguration())) + using (QuantizedFrame paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame)) { this.WriteImageData(paletteQuantized, stream); } @@ -181,14 +184,17 @@ namespace SixLabors.ImageSharp.Formats.Gif if (previousFrame != null && previousMeta.ColorTableLength != frameMetadata.ColorTableLength && frameMetadata.ColorTableLength > 0) { - quantized = this.quantizer.CreateFrameQuantizer( - image.GetConfiguration(), - frameMetadata.ColorTableLength).QuantizeFrame(frame); + using (IFrameQuantizer frameQuantizer = this.quantizer.CreateFrameQuantizer(image.GetConfiguration(), frameMetadata.ColorTableLength)) + { + quantized = frameQuantizer.QuantizeFrame(frame); + } } else { - quantized = this.quantizer.CreateFrameQuantizer(image.GetConfiguration()) - .QuantizeFrame(frame); + using (IFrameQuantizer frameQuantizer = this.quantizer.CreateFrameQuantizer(image.GetConfiguration())) + { + quantized = frameQuantizer.QuantizeFrame(frame); + } } } diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 9818e6cf1..7415b0753 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -243,8 +243,11 @@ namespace SixLabors.ImageSharp.Formats.Png } // Create quantized frame returning the palette and set the bit depth. - quantized = this.quantizer.CreateFrameQuantizer(image.GetConfiguration()) - .QuantizeFrame(image.Frames.RootFrame); + using (IFrameQuantizer frameQuantizer = this.quantizer.CreateFrameQuantizer(image.GetConfiguration())) + { + quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame); + } + byte quantizedBits = (byte)ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8); bits = Math.Max(bits, quantizedBits); diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs index a70cfb660..f23343f6d 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs @@ -98,6 +98,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization return quantizedFrame; } + /// + public virtual void Dispose() + { + } + /// /// Execute the first pass through the pixels in the image to create the palette. /// diff --git a/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs index 50fdb5b58..f0b68b3a0 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Dithering; @@ -10,7 +11,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// Provides methods to allow the execution of the quantization process on an image frame. /// /// The pixel format. - public interface IFrameQuantizer + public interface IFrameQuantizer : IDisposable where TPixel : struct, IPixel { /// diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs index 8da89bf94..e99f504b4 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { - IFrameQuantizer executor = this.Quantizer.CreateFrameQuantizer(configuration); + using (IFrameQuantizer executor = this.Quantizer.CreateFrameQuantizer(configuration)) using (QuantizedFrame quantized = executor.QuantizeFrame(source)) { int paletteCount = quantized.Palette.Length - 1; diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs index 44df226cf..1f1513adf 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs @@ -11,6 +11,8 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; +// TODO: Isn't an AOS ("array of structures") layout more efficient & more readable than SOA ("structure of arrays") for this particular use case? +// (T, R, G, B, A, M2) could be grouped together! Investigate a ColorMoment struct. namespace SixLabors.ImageSharp.Processing.Processors.Quantization { /// @@ -36,20 +38,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization internal sealed class WuFrameQuantizer : FrameQuantizerBase where TPixel : struct, IPixel { - // TODO: The WuFrameQuantizer code is rising several questions: - // - Do we really need to ALWAYS allocate the whole table of size TableLength? (~ 2471625 * sizeof(long) * 5 bytes ) JS. I'm afraid so. - // - Isn't an AOS ("array of structures") layout more efficient & more readable than SOA ("structure of arrays") for this particular use case? - // (T, R, G, B, A, M2) could be grouped together! - // - It's a frequently used class, we need tests! (So we can optimize safely.) There are tests in the original!!! We should just adopt them! - // https://github.com/JeremyAnsel/JeremyAnsel.ColorQuant/blob/master/JeremyAnsel.ColorQuant/JeremyAnsel.ColorQuant.Tests/WuColorQuantizerTests.cs + // The following two variables determine the amount of bits to preserve when calculating the histogram. + // Reducing the value of these numbers the granularity of the color maps produced, making it much faster + // and using much less memory but potentially less accurate. Current results are very good though! /// - /// The index bits. + /// The index bits. 6 in original code. /// private const int IndexBits = 5; /// - /// The index alpha bits. Keep separate for now to allow easy adjustment. + /// The index alpha bits. 3 in original code. /// private const int IndexAlphaBits = 5; @@ -64,7 +63,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization private const int IndexAlphaCount = (1 << IndexAlphaBits) + 1; /// - /// The table length. Now 1185921. + /// The table length. Now 1185921. originally 2471625. /// private const int TableLength = IndexCount * IndexCount * IndexCount * IndexAlphaCount; @@ -96,7 +95,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Moment of c^2*P(c). /// - private IMemoryOwner m2; + private IMemoryOwner m2; /// /// Color space tag. @@ -149,28 +148,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization Guard.NotNull(image, nameof(image)); MemoryAllocator memoryAllocator = image.MemoryAllocator; - try - { - this.vwt = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); - this.vmr = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); - this.vmg = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); - this.vmb = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); - this.vma = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); - this.m2 = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); - this.tag = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); - - return base.QuantizeFrame(image); - } - finally - { - this.vwt?.Dispose(); - this.vmr?.Dispose(); - this.vmg?.Dispose(); - this.vmb?.Dispose(); - this.vma?.Dispose(); - this.m2?.Dispose(); - this.tag?.Dispose(); - } + this.vwt = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); + this.vmr = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); + this.vmg = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); + this.vmb = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); + this.vma = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); + this.m2 = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); + this.tag = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); + + return base.QuantizeFrame(image); + } + + /// + public override void Dispose() + { + this.vwt?.Dispose(); + this.vmr?.Dispose(); + this.vmg?.Dispose(); + this.vmb?.Dispose(); + this.vma?.Dispose(); + this.m2?.Dispose(); + this.tag?.Dispose(); } internal TPixel[] AotGetPalette() => this.GetPalette(); @@ -275,9 +273,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int GetPaletteIndex(int r, int g, int b, int a) { - return (r << ((IndexBits * 2) + IndexAlphaBits)) + (r << (IndexBits + IndexAlphaBits + 1)) - + (g << (IndexBits + IndexAlphaBits)) + (r << (IndexBits * 2)) + (r << (IndexBits + 1)) - + (g << IndexBits) + ((r + g + b) << IndexAlphaBits) + r + g + b + a; + return (r << ((IndexBits * 2) + IndexAlphaBits)) + + (r << (IndexBits + IndexAlphaBits + 1)) + + (g << (IndexBits + IndexAlphaBits)) + + (r << (IndexBits * 2)) + + (r << (IndexBits + 1)) + + (g << IndexBits) + + ((r + g + b) << IndexAlphaBits) + + r + g + b + a; } /// @@ -288,26 +291,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The result. private static float Volume(ref Box cube, Span moment) { - return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] - - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + return moment[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMax, cube.AMax)] + - moment[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMax, cube.AMin)] + - moment[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMax)] + + moment[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMin)] + - moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMax)] + + moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMin)] + + moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMax)] + - moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] + - moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMax)] + + moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMin)] + + moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMax)] + - moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] + + moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMax)] + - moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] + - moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] + + moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; } /// - /// Computes part of Volume(cube, moment) that doesn't depend on r1, g1, or b1 (depending on direction). + /// Computes part of Volume(cube, moment) that doesn't depend on RMax, GMax, BMax, or AMax (depending on direction). /// /// The cube. /// The direction. @@ -319,47 +322,47 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization { // Red case 3: - return -moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMax)] + + moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMin)] + + moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMax)] + - moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] + + moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMax)] + - moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] + - moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] + + moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; // Green case 2: - return -moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMax)] + + moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMin)] + + moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMax)] + - moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] + + moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMax)] + - moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] + - moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] + + moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; // Blue case 1: - return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMax)] + + moment[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMin)] + + moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMax)] + - moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] + + moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMax)] + - moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] + - moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] + + moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; // Alpha case 0: - return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMax, cube.AMin)] + + moment[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMin)] + + moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMin)] + - moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] + + moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMin)] + - moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] + - moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] + + moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; default: throw new ArgumentOutOfRangeException(nameof(direction)); @@ -367,7 +370,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } /// - /// Computes remainder of Volume(cube, moment), substituting position for r1, g1, or b1 (depending on direction). + /// Computes remainder of Volume(cube, moment), substituting position for RMax, GMax, BMax, or AMax (depending on direction). /// /// The cube. /// The direction. @@ -380,47 +383,47 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization { // Red case 3: - return moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A1)] - - moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A0)] - - moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A1)] - + moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A0)] - - moment[GetPaletteIndex(position, cube.G0, cube.B1, cube.A1)] - + moment[GetPaletteIndex(position, cube.G0, cube.B1, cube.A0)] - + moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A1)] - - moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A0)]; + return moment[GetPaletteIndex(position, cube.GMax, cube.BMax, cube.AMax)] + - moment[GetPaletteIndex(position, cube.GMax, cube.BMax, cube.AMin)] + - moment[GetPaletteIndex(position, cube.GMax, cube.BMin, cube.AMax)] + + moment[GetPaletteIndex(position, cube.GMax, cube.BMin, cube.AMin)] + - moment[GetPaletteIndex(position, cube.GMin, cube.BMax, cube.AMax)] + + moment[GetPaletteIndex(position, cube.GMin, cube.BMax, cube.AMin)] + + moment[GetPaletteIndex(position, cube.GMin, cube.BMin, cube.AMax)] + - moment[GetPaletteIndex(position, cube.GMin, cube.BMin, cube.AMin)]; // Green case 2: - return moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A1)] - - moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A0)] - - moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A1)] - + moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A0)] - - moment[GetPaletteIndex(cube.R0, position, cube.B1, cube.A1)] - + moment[GetPaletteIndex(cube.R0, position, cube.B1, cube.A0)] - + moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A1)] - - moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A0)]; + return moment[GetPaletteIndex(cube.RMax, position, cube.BMax, cube.AMax)] + - moment[GetPaletteIndex(cube.RMax, position, cube.BMax, cube.AMin)] + - moment[GetPaletteIndex(cube.RMax, position, cube.BMin, cube.AMax)] + + moment[GetPaletteIndex(cube.RMax, position, cube.BMin, cube.AMin)] + - moment[GetPaletteIndex(cube.RMin, position, cube.BMax, cube.AMax)] + + moment[GetPaletteIndex(cube.RMin, position, cube.BMax, cube.AMin)] + + moment[GetPaletteIndex(cube.RMin, position, cube.BMin, cube.AMax)] + - moment[GetPaletteIndex(cube.RMin, position, cube.BMin, cube.AMin)]; // Blue case 1: - return moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A1)] - - moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A0)] - - moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A1)] - + moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A0)] - - moment[GetPaletteIndex(cube.R0, cube.G1, position, cube.A1)] - + moment[GetPaletteIndex(cube.R0, cube.G1, position, cube.A0)] - + moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A1)] - - moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A0)]; + return moment[GetPaletteIndex(cube.RMax, cube.GMax, position, cube.AMax)] + - moment[GetPaletteIndex(cube.RMax, cube.GMax, position, cube.AMin)] + - moment[GetPaletteIndex(cube.RMax, cube.GMin, position, cube.AMax)] + + moment[GetPaletteIndex(cube.RMax, cube.GMin, position, cube.AMin)] + - moment[GetPaletteIndex(cube.RMin, cube.GMax, position, cube.AMax)] + + moment[GetPaletteIndex(cube.RMin, cube.GMax, position, cube.AMin)] + + moment[GetPaletteIndex(cube.RMin, cube.GMin, position, cube.AMax)] + - moment[GetPaletteIndex(cube.RMin, cube.GMin, position, cube.AMin)]; // Alpha case 0: - return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, position)] - - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, position)] - - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, position)] - + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, position)] - - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, position)] - + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, position)] - + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, position)] - - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, position)]; + return moment[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMax, position)] + - moment[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, position)] + - moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, position)] + + moment[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, position)] + - moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, position)] + + moment[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, position)] + + moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, position)] + - moment[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, position)]; default: throw new ArgumentOutOfRangeException(nameof(direction)); @@ -440,7 +443,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization Span vmgSpan = this.vmg.GetSpan(); Span vmbSpan = this.vmb.GetSpan(); Span vmaSpan = this.vma.GetSpan(); - Span m2Span = this.m2.GetSpan(); + Span m2Span = this.m2.GetSpan(); // Build up the 3-D color histogram // Loop through each row @@ -489,34 +492,34 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization Span vmgSpan = this.vmg.GetSpan(); Span vmbSpan = this.vmb.GetSpan(); Span vmaSpan = this.vma.GetSpan(); - Span m2Span = this.m2.GetSpan(); + Span m2Span = this.m2.GetSpan(); using (IMemoryOwner volume = memoryAllocator.Allocate(IndexCount * IndexAlphaCount)) using (IMemoryOwner volumeR = memoryAllocator.Allocate(IndexCount * IndexAlphaCount)) using (IMemoryOwner volumeG = memoryAllocator.Allocate(IndexCount * IndexAlphaCount)) using (IMemoryOwner volumeB = memoryAllocator.Allocate(IndexCount * IndexAlphaCount)) using (IMemoryOwner volumeA = memoryAllocator.Allocate(IndexCount * IndexAlphaCount)) - using (IMemoryOwner volume2 = memoryAllocator.Allocate(IndexCount * IndexAlphaCount)) + using (IMemoryOwner volume2 = memoryAllocator.Allocate(IndexCount * IndexAlphaCount)) using (IMemoryOwner area = memoryAllocator.Allocate(IndexAlphaCount)) using (IMemoryOwner areaR = memoryAllocator.Allocate(IndexAlphaCount)) using (IMemoryOwner areaG = memoryAllocator.Allocate(IndexAlphaCount)) using (IMemoryOwner areaB = memoryAllocator.Allocate(IndexAlphaCount)) using (IMemoryOwner areaA = memoryAllocator.Allocate(IndexAlphaCount)) - using (IMemoryOwner area2 = memoryAllocator.Allocate(IndexAlphaCount)) + using (IMemoryOwner area2 = memoryAllocator.Allocate(IndexAlphaCount)) { Span volumeSpan = volume.GetSpan(); Span volumeRSpan = volumeR.GetSpan(); Span volumeGSpan = volumeG.GetSpan(); Span volumeBSpan = volumeB.GetSpan(); Span volumeASpan = volumeA.GetSpan(); - Span volume2Span = volume2.GetSpan(); + Span volume2Span = volume2.GetSpan(); Span areaSpan = area.GetSpan(); Span areaRSpan = areaR.GetSpan(); Span areaGSpan = areaG.GetSpan(); Span areaBSpan = areaB.GetSpan(); Span areaASpan = areaA.GetSpan(); - Span area2Span = area2.GetSpan(); + Span area2Span = area2.GetSpan(); for (int r = 1; r < IndexCount; r++) { @@ -543,7 +546,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization long lineG = 0; long lineB = 0; long lineA = 0; - float line2 = 0; + double line2 = 0; for (int a = 1; a < IndexAlphaCount; a++) { @@ -592,35 +595,35 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// The cube. /// The . - private float Variance(ref Box cube) + private double Variance(ref Box cube) { float dr = Volume(ref cube, this.vmr.GetSpan()); float dg = Volume(ref cube, this.vmg.GetSpan()); float db = Volume(ref cube, this.vmb.GetSpan()); float da = Volume(ref cube, this.vma.GetSpan()); - Span m2Span = this.m2.GetSpan(); - - float xx = - m2Span[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] - - m2Span[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] - - m2Span[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] - + m2Span[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - - m2Span[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] - + m2Span[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - + m2Span[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - m2Span[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - - m2Span[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] - + m2Span[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - + m2Span[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - m2Span[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - + m2Span[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - m2Span[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - m2Span[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + m2Span[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + Span m2Span = this.m2.GetSpan(); + + double moment = + m2Span[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMax, cube.AMax)] + - m2Span[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMax, cube.AMin)] + - m2Span[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMax)] + + m2Span[GetPaletteIndex(cube.RMax, cube.GMax, cube.BMin, cube.AMin)] + - m2Span[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMax)] + + m2Span[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMax, cube.AMin)] + + m2Span[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMax)] + - m2Span[GetPaletteIndex(cube.RMax, cube.GMin, cube.BMin, cube.AMin)] + - m2Span[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMax)] + + m2Span[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMax, cube.AMin)] + + m2Span[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMax)] + - m2Span[GetPaletteIndex(cube.RMin, cube.GMax, cube.BMin, cube.AMin)] + + m2Span[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMax)] + - m2Span[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMax, cube.AMin)] + - m2Span[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMax)] + + m2Span[GetPaletteIndex(cube.RMin, cube.GMin, cube.BMin, cube.AMin)]; var vector = new Vector4(dr, dg, db, da); - return xx - (Vector4.Dot(vector, vector) / Volume(ref cube, this.vwt.GetSpan())); + return moment - (Vector4.Dot(vector, vector) / Volume(ref cube, this.vwt.GetSpan())); } /// @@ -714,10 +717,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization float wholeA = Volume(ref set1, this.vma.GetSpan()); float wholeW = Volume(ref set1, this.vwt.GetSpan()); - float maxr = this.Maximize(ref set1, 3, set1.R0 + 1, set1.R1, out int cutr, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxg = this.Maximize(ref set1, 2, set1.G0 + 1, set1.G1, out int cutg, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxb = this.Maximize(ref set1, 1, set1.B0 + 1, set1.B1, out int cutb, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxa = this.Maximize(ref set1, 0, set1.A0 + 1, set1.A1, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxr = this.Maximize(ref set1, 3, set1.RMin + 1, set1.RMax, out int cutr, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxg = this.Maximize(ref set1, 2, set1.GMin + 1, set1.GMax, out int cutg, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxb = this.Maximize(ref set1, 1, set1.BMin + 1, set1.BMax, out int cutb, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxa = this.Maximize(ref set1, 0, set1.AMin + 1, set1.AMax, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW); int dir; @@ -743,48 +746,48 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization dir = 0; } - set2.R1 = set1.R1; - set2.G1 = set1.G1; - set2.B1 = set1.B1; - set2.A1 = set1.A1; + set2.RMax = set1.RMax; + set2.GMax = set1.GMax; + set2.BMax = set1.BMax; + set2.AMax = set1.AMax; switch (dir) { // Red case 3: - set2.R0 = set1.R1 = cutr; - set2.G0 = set1.G0; - set2.B0 = set1.B0; - set2.A0 = set1.A0; + set2.RMin = set1.RMax = cutr; + set2.GMin = set1.GMin; + set2.BMin = set1.BMin; + set2.AMin = set1.AMin; break; // Green case 2: - set2.G0 = set1.G1 = cutg; - set2.R0 = set1.R0; - set2.B0 = set1.B0; - set2.A0 = set1.A0; + set2.GMin = set1.GMax = cutg; + set2.RMin = set1.RMin; + set2.BMin = set1.BMin; + set2.AMin = set1.AMin; break; // Blue case 1: - set2.B0 = set1.B1 = cutb; - set2.R0 = set1.R0; - set2.G0 = set1.G0; - set2.A0 = set1.A0; + set2.BMin = set1.BMax = cutb; + set2.RMin = set1.RMin; + set2.GMin = set1.GMin; + set2.AMin = set1.AMin; break; // Alpha case 0: - set2.A0 = set1.A1 = cuta; - set2.R0 = set1.R0; - set2.G0 = set1.G0; - set2.B0 = set1.B0; + set2.AMin = set1.AMax = cuta; + set2.RMin = set1.RMin; + set2.GMin = set1.GMin; + set2.BMin = set1.BMin; break; } - set1.Volume = (set1.R1 - set1.R0) * (set1.G1 - set1.G0) * (set1.B1 - set1.B0) * (set1.A1 - set1.A0); - set2.Volume = (set2.R1 - set2.R0) * (set2.G1 - set2.G0) * (set2.B1 - set2.B0) * (set2.A1 - set2.A0); + set1.Volume = (set1.RMax - set1.RMin) * (set1.GMax - set1.GMin) * (set1.BMax - set1.BMin) * (set1.AMax - set1.AMin); + set2.Volume = (set2.RMax - set2.RMin) * (set2.GMax - set2.GMin) * (set2.BMax - set2.BMin) * (set2.AMax - set2.AMin); return true; } @@ -798,13 +801,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization { Span tagSpan = this.tag.GetSpan(); - for (int r = cube.R0 + 1; r <= cube.R1; r++) + for (int r = cube.RMin + 1; r <= cube.RMax; r++) { - for (int g = cube.G0 + 1; g <= cube.G1; g++) + for (int g = cube.GMin + 1; g <= cube.GMax; g++) { - for (int b = cube.B0 + 1; b <= cube.B1; b++) + for (int b = cube.BMin + 1; b <= cube.BMax; b++) { - for (int a = cube.A0 + 1; a <= cube.A1; a++) + for (int a = cube.AMin + 1; a <= cube.AMax; a++) { tagSpan[GetPaletteIndex(r, g, b, a)] = label; } @@ -819,12 +822,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization private void BuildCube() { this.colorCube = new Box[this.colors]; - float[] vv = new float[this.colors]; + double[] vv = new double[this.colors]; ref Box cube = ref this.colorCube[0]; - cube.R0 = cube.G0 = cube.B0 = cube.A0 = 0; - cube.R1 = cube.G1 = cube.B1 = IndexCount - 1; - cube.A1 = IndexAlphaCount - 1; + cube.RMin = cube.GMin = cube.BMin = cube.AMin = 0; + cube.RMax = cube.GMax = cube.BMax = IndexCount - 1; + cube.AMax = IndexAlphaCount - 1; int next = 0; @@ -839,13 +842,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } else { - vv[next] = 0F; + vv[next] = 0D; i--; } next = 0; - float temp = vv[0]; + double temp = vv[0]; for (int k = 1; k <= i; k++) { if (vv[k] > temp) @@ -855,7 +858,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } } - if (temp <= 0F) + if (temp <= 0D) { this.colors = i + 1; break; @@ -897,52 +900,83 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Represents a box color cube. /// - private struct Box + private struct Box : IEquatable { /// /// Gets or sets the min red value, exclusive. /// - public int R0; + public int RMin; /// /// Gets or sets the max red value, inclusive. /// - public int R1; + public int RMax; /// /// Gets or sets the min green value, exclusive. /// - public int G0; + public int GMin; /// /// Gets or sets the max green value, inclusive. /// - public int G1; + public int GMax; /// /// Gets or sets the min blue value, exclusive. /// - public int B0; + public int BMin; /// /// Gets or sets the max blue value, inclusive. /// - public int B1; + public int BMax; /// /// Gets or sets the min alpha value, exclusive. /// - public int A0; + public int AMin; /// /// Gets or sets the max alpha value, inclusive. /// - public int A1; + public int AMax; /// /// Gets or sets the volume. /// public int Volume; + + /// + public override bool Equals(object obj) => obj is Box box && this.Equals(box); + + /// + public bool Equals(Box other) => + this.RMin == other.RMin + && this.RMax == other.RMax + && this.GMin == other.GMin + && this.GMax == other.GMax + && this.BMin == other.BMin + && this.BMax == other.BMax + && this.AMin == other.AMin + && this.AMax == other.AMax + && this.Volume == other.Volume; + + /// + public override int GetHashCode() + { + HashCode hash = default; + hash.Add(this.RMin); + hash.Add(this.RMax); + hash.Add(this.GMin); + hash.Add(this.GMax); + hash.Add(this.BMin); + hash.Add(this.BMax); + hash.Add(this.AMin); + hash.Add(this.AMax); + hash.Add(this.Volume); + return hash.ToHashCode(); + } } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs b/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs new file mode 100644 index 000000000..3eacd74ea --- /dev/null +++ b/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs @@ -0,0 +1,168 @@ +using System; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Quantization; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Quantization +{ + public class WuQuantizerTests + { + [Fact] + public void SinglePixelOpaque() + { + Configuration config = Configuration.Default; + var quantizer = new WuQuantizer(false); + + using (var image = new Image(config, 1, 1, Rgba32.Black)) + using (QuantizedFrame result = quantizer.CreateFrameQuantizer(config).QuantizeFrame(image.Frames[0])) + { + Assert.Equal(1, result.Palette.Length); + Assert.Equal(1, result.GetPixelSpan().Length); + + Assert.Equal(Rgba32.Black, result.Palette[0]); + Assert.Equal(0, result.GetPixelSpan()[0]); + } + } + + [Fact] + public void SinglePixelTransparent() + { + Configuration config = Configuration.Default; + var quantizer = new WuQuantizer(false); + + using (var image = new Image(config, 1, 1, default(Rgba32))) + using (QuantizedFrame result = quantizer.CreateFrameQuantizer(config).QuantizeFrame(image.Frames[0])) + { + Assert.Equal(1, result.Palette.Length); + Assert.Equal(1, result.GetPixelSpan().Length); + + Assert.Equal(default, result.Palette[0]); + Assert.Equal(0, result.GetPixelSpan()[0]); + } + } + + [Fact] + public void GrayScale() => TestScale(c => new Rgba32(c, c, c, 128)); + + [Fact] + public void RedScale() => TestScale(c => new Rgba32(c, 0, 0, 128)); + + [Fact] + public void GreenScale() => TestScale(c => new Rgba32(0, c, 0, 128)); + + [Fact] + public void BlueScale() => TestScale(c => new Rgba32(0, 0, c, 128)); + + [Fact] + public void AlphaScale() => TestScale(c => new Rgba32(0, 0, 0, c)); + + [Fact] + public void Palette256() + { + using (var image = new Image(1, 256)) + { + for (int i = 0; i < 256; i++) + { + byte r = (byte)((i % 4) * 85); + byte g = (byte)(((i / 4) % 4) * 85); + byte b = (byte)(((i / 16) % 4) * 85); + byte a = (byte)((i / 64) * 85); + + image[0, i] = new Rgba32(r, g, b, a); + } + + Configuration config = Configuration.Default; + var quantizer = new WuQuantizer(false); + using (IFrameQuantizer frameQuantizer = quantizer.CreateFrameQuantizer(config)) + using (QuantizedFrame result = frameQuantizer.QuantizeFrame(image.Frames[0])) + { + Assert.Equal(256, result.Palette.Length); + Assert.Equal(256, result.GetPixelSpan().Length); + + var actualImage = new Image(1, 256); + + int paletteCount = result.Palette.Length - 1; + for (int y = 0; y < actualImage.Height; y++) + { + Span row = actualImage.GetPixelRowSpan(y); + ReadOnlySpan quantizedPixelSpan = result.GetPixelSpan(); + int yy = y * actualImage.Width; + + for (int x = 0; x < actualImage.Width; x++) + { + int i = x + yy; + row[x] = result.Palette[Math.Min(paletteCount, quantizedPixelSpan[i])]; + } + } + + Assert.True(image.GetPixelSpan().SequenceEqual(actualImage.GetPixelSpan())); + } + } + } + + [Theory] + [WithFile(TestImages.Png.LowColorVariance, PixelTypes.Rgba32)] + public void LowVariance(TestImageProvider provider) + where TPixel : struct, IPixel + { + // See https://github.com/SixLabors/ImageSharp/issues/866 + using (Image image = provider.GetImage()) + { + Configuration config = Configuration.Default; + var quantizer = new WuQuantizer(false); + using (IFrameQuantizer frameQuantizer = quantizer.CreateFrameQuantizer(config)) + using (QuantizedFrame result = frameQuantizer.QuantizeFrame(image.Frames[0])) + { + Assert.Equal(48, result.Palette.Length); + } + } + } + + private static void TestScale(Func pixelBuilder) + { + using (var image = new Image(1, 256)) + using (var expectedImage = new Image(1, 256)) + using (var actualImage = new Image(1, 256)) + { + for (int i = 0; i < 256; i++) + { + byte c = (byte)i; + image[0, i] = pixelBuilder.Invoke(c); + } + + for (int i = 0; i < 256; i++) + { + byte c = (byte)((i & ~7) + 4); + expectedImage[0, i] = pixelBuilder.Invoke(c); + } + + Configuration config = Configuration.Default; + var quantizer = new WuQuantizer(false); + + using (IFrameQuantizer frameQuantizer = quantizer.CreateFrameQuantizer(config)) + using (QuantizedFrame result = frameQuantizer.QuantizeFrame(image.Frames[0])) + { + Assert.Equal(4 * 8, result.Palette.Length); + Assert.Equal(256, result.GetPixelSpan().Length); + + int paletteCount = result.Palette.Length - 1; + for (int y = 0; y < actualImage.Height; y++) + { + Span row = actualImage.GetPixelRowSpan(y); + ReadOnlySpan quantizedPixelSpan = result.GetPixelSpan(); + int yy = y * actualImage.Width; + + for (int x = 0; x < actualImage.Width; x++) + { + int i = x + yy; + row[x] = result.Palette[Math.Min(paletteCount, quantizedPixelSpan[i])]; + } + } + } + + Assert.True(expectedImage.GetPixelSpan().SequenceEqual(actualImage.GetPixelSpan())); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 909969624..1efb9e35f 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -53,6 +53,7 @@ namespace SixLabors.ImageSharp.Tests public const string Gray2BitTrans = "Png/gray-2-tRNS.png"; public const string Gray4BitTrans = "Png/gray-4-tRNS.png"; public const string Gray8BitTrans = "Png/gray-8-tRNS.png"; + public const string LowColorVariance = "Png/low-variance.png"; // Filtered test images from http://www.schaik.com/pngsuite/pngsuite_fil_png.html public const string Filter0 = "Png/filter0.png"; diff --git a/tests/Images/Input/Png/low-variance.png b/tests/Images/Input/Png/low-variance.png new file mode 100644 index 0000000000000000000000000000000000000000..5b6c19bace8ef66d02b0fec96e2f06b9f2534701 GIT binary patch literal 7844 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 Date: Sat, 13 Apr 2019 21:01:04 -0500 Subject: [PATCH 056/223] Nits - Benchmarks (#884) * Update metadata names * Use WithIterationCount * Format Benchmark documents * Update copyright assignment to Six Labors & Contributors * Update deps * React to Benchmark library update --- tests/ImageSharp.Benchmarks/BenchmarkBase.cs | 9 ++-- .../ImageSharp.Benchmarks/Codecs/DecodeBmp.cs | 2 +- .../Codecs/DecodeFilteredPng.cs | 4 +- .../ImageSharp.Benchmarks/Codecs/DecodePng.cs | 1 - .../Codecs/ImageBenchmarkTests.cs | 4 +- .../BlockOperations/Block8x8F_CopyTo2x2.cs | 40 +++++++++------ .../Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs | 8 +-- .../Codecs/Jpeg/EncodeJpeg.cs | 18 +++---- .../Codecs/MultiImageBenchmarkBase.cs | 18 +++---- .../Color/ColorEquality.cs | 12 ++--- .../Color/ColorspaceCieXyzToCieLabConvert.cs | 14 ++--- .../ColorspaceCieXyzToHunterLabConvert.cs | 15 +++--- .../Color/ColorspaceCieXyzToLmsConvert.cs | 15 +++--- .../Color/ColorspaceCieXyzToRgbConvert.cs | 14 ++--- .../ImageSharp.Benchmarks/Color/RgbToYCbCr.cs | 32 ++++++------ .../Color/RgbWorkingSpaceAdapt.cs | 15 +++--- tests/ImageSharp.Benchmarks/Config.cs | 17 +++---- .../Drawing/DrawBeziers.cs | 38 +++++++------- .../Drawing/DrawLines.cs | 51 +++++++++---------- .../Drawing/DrawPolygon.cs | 35 ++++++------- .../ImageSharp.Benchmarks/Drawing/DrawText.cs | 26 ++++------ .../Drawing/DrawTextOutline.cs | 32 +++++------- .../Drawing/FillPolygon.cs | 49 +++++++++--------- .../Drawing/FillRectangle.cs | 24 ++++----- .../Drawing/FillWithPattern.cs | 28 +++++----- .../ImageSharp.Benchmarks/General/Array2D.cs | 14 +++-- .../General/ArrayCopy.cs | 19 ++++--- .../General/ArrayReverse.cs | 14 +++-- .../General/BasicMath/ClampInt32IntoByte.cs | 4 +- .../PixelConversion_ConvertToRgba32.cs | 5 +- .../PixelConversion_ConvertToVector4.cs | 2 - .../General/Vector4Constants.cs | 10 ++-- .../General/Vectorization/BitwiseOrUint32.cs | 8 +-- .../General/Vectorization/DivFloat.cs | 12 ++--- .../General/Vectorization/DivUInt32.cs | 14 ++--- .../General/Vectorization/Divide.cs | 9 ++-- .../General/Vectorization/MulFloat.cs | 8 +-- .../General/Vectorization/MulUInt32.cs | 10 ++-- .../General/Vectorization/Multiply.cs | 6 +-- .../Vectorization/ReinterpretUInt32AsFloat.cs | 12 ++--- .../Vectorization/SIMDBenchmarkBase.cs | 11 ++-- .../ImageSharp.Benchmarks.csproj | 6 +-- tests/ImageSharp.Benchmarks/Program.cs | 13 ++--- tests/ImageSharp.Benchmarks/Samplers/Crop.cs | 42 +++++++-------- .../Samplers/DetectEdges.cs | 6 +-- tests/ImageSharp.Benchmarks/Samplers/Glow.cs | 13 +++-- .../ImageSharp.Benchmarks/Samplers/Resize.cs | 1 - .../ImageSharp.Benchmarks/Samplers/Rotate.cs | 5 +- tests/ImageSharp.Benchmarks/Samplers/Skew.cs | 5 +- 49 files changed, 352 insertions(+), 418 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/BenchmarkBase.cs b/tests/ImageSharp.Benchmarks/BenchmarkBase.cs index 6db03a448..87ed8fa42 100644 --- a/tests/ImageSharp.Benchmarks/BenchmarkBase.cs +++ b/tests/ImageSharp.Benchmarks/BenchmarkBase.cs @@ -1,7 +1,8 @@ -namespace SixLabors.ImageSharp.Benchmarks -{ - using SixLabors.ImageSharp.Formats; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. +namespace SixLabors.ImageSharp.Benchmarks +{ /// /// The image benchmark base class. /// @@ -15,4 +16,4 @@ // Add Image Formats } } -} +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Codecs/DecodeBmp.cs b/tests/ImageSharp.Benchmarks/Codecs/DecodeBmp.cs index 30799aabf..1ab5ed309 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/DecodeBmp.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/DecodeBmp.cs @@ -54,4 +54,4 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs } } } -} +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Codecs/DecodeFilteredPng.cs b/tests/ImageSharp.Benchmarks/Codecs/DecodeFilteredPng.cs index ff378c75c..cc946e05a 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/DecodeFilteredPng.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/DecodeFilteredPng.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System.IO; using System.Runtime.CompilerServices; diff --git a/tests/ImageSharp.Benchmarks/Codecs/DecodePng.cs b/tests/ImageSharp.Benchmarks/Codecs/DecodePng.cs index 39f09b6b6..a19d8fa91 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/DecodePng.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/DecodePng.cs @@ -11,7 +11,6 @@ using SDImage = System.Drawing.Image; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] public class DecodePng : BenchmarkBase { diff --git a/tests/ImageSharp.Benchmarks/Codecs/ImageBenchmarkTests.cs b/tests/ImageSharp.Benchmarks/Codecs/ImageBenchmarkTests.cs index ee77a2b6b..7c3da90db 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/ImageBenchmarkTests.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/ImageBenchmarkTests.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// // This file contains small, cheap and "unit test" benchmarks to test MultiImageBenchmarkBase. // Need this because there are no real test cases for the common benchmark utility stuff. diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_CopyTo2x2.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_CopyTo2x2.cs index 65176af5b..3d9b54dff 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_CopyTo2x2.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_CopyTo2x2.cs @@ -364,22 +364,30 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations ref Vector4 dTopLeft = ref Unsafe.As(ref Unsafe.Add(ref destBase, offset)); ref Vector4 dBottomLeft = ref Unsafe.As(ref Unsafe.Add(ref destBase, offset + destStride)); - var xyLeft = new Vector4(sLeft.X); - xyLeft.Z = sLeft.Y; - xyLeft.W = sLeft.Y; - - var zwLeft = new Vector4(sLeft.Z); - zwLeft.Z = sLeft.W; - zwLeft.W = sLeft.W; - - var xyRight = new Vector4(sRight.X); - xyRight.Z = sRight.Y; - xyRight.W = sRight.Y; - - var zwRight = new Vector4(sRight.Z); - zwRight.Z = sRight.W; - zwRight.W = sRight.W; - + var xyLeft = new Vector4(sLeft.X) + { + Z = sLeft.Y, + W = sLeft.Y + }; + + var zwLeft = new Vector4(sLeft.Z) + { + Z = sLeft.W, + W = sLeft.W + }; + + var xyRight = new Vector4(sRight.X) + { + Z = sRight.Y, + W = sRight.Y + }; + + var zwRight = new Vector4(sRight.Z) + { + Z = sRight.W, + W = sRight.W + }; + dTopLeft = xyLeft; Unsafe.Add(ref dTopLeft, 1) = zwLeft; Unsafe.Add(ref dTopLeft, 2) = xyRight; diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs index fe112042e..8247ba42b 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs @@ -5,6 +5,7 @@ using System.Drawing; using System.IO; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Diagnosers; using BenchmarkDotNet.Jobs; using SixLabors.ImageSharp.Formats.Jpeg; @@ -26,8 +27,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { public Config() { - // Uncomment if you want to use any of the diagnoser - this.Add(new BenchmarkDotNet.Diagnosers.MemoryDiagnoser()); + this.Add(MemoryDiagnoser.Default); } public class ShortClr : Benchmarks.Config @@ -35,8 +35,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg public ShortClr() { this.Add( - //Job.Clr.WithLaunchCount(1).WithWarmupCount(2).WithTargetCount(3), - Job.Core.WithLaunchCount(1).WithWarmupCount(2).WithTargetCount(3) + //Job.Clr.WithLaunchCount(1).WithWarmupCount(2).WithIterationCount(3), + Job.Core.WithLaunchCount(1).WithWarmupCount(2).WithIterationCount(3) ); } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs index d934a1d6d..c617d25c0 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs @@ -1,18 +1,16 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using SixLabors.ImageSharp.PixelFormats; +using BenchmarkDotNet.Attributes; + namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { using System.Drawing; using System.Drawing.Imaging; using System.IO; - using BenchmarkDotNet.Attributes; - using CoreImage = SixLabors.ImageSharp.Image; public class EncodeJpeg : BenchmarkBase @@ -45,19 +43,19 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg [Benchmark(Baseline = true, Description = "System.Drawing Jpeg")] public void JpegSystemDrawing() { - using (var memoryStream = new MemoryStream()) + using (var stream = new MemoryStream()) { - this.bmpDrawing.Save(memoryStream, ImageFormat.Jpeg); + this.bmpDrawing.Save(stream, ImageFormat.Jpeg); } } [Benchmark(Description = "ImageSharp Jpeg")] public void JpegCore() { - using (var memoryStream = new MemoryStream()) + using (var stream = new MemoryStream()) { - this.bmpCore.SaveAsJpeg(memoryStream); + this.bmpCore.SaveAsJpeg(stream); } } } -} +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs b/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs index 446c03859..75bbf21a3 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using BenchmarkDotNet.Configs; using BenchmarkDotNet.Jobs; @@ -18,7 +16,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs using System.Numerics; using BenchmarkDotNet.Attributes; - + using BenchmarkDotNet.Diagnosers; using SixLabors.ImageSharp.Tests; using CoreImage = ImageSharp.Image; @@ -30,7 +28,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs public Config() { // Uncomment if you want to use any of the diagnoser - this.Add(new BenchmarkDotNet.Diagnosers.MemoryDiagnoser()); + this.Add(MemoryDiagnoser.Default); } public class ShortClr : Benchmarks.Config @@ -38,7 +36,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs public ShortClr() { this.Add( - Job.Core.WithLaunchCount(1).WithWarmupCount(1).WithTargetCount(2) + Job.Core.WithLaunchCount(1).WithWarmupCount(1).WithIterationCount(2) ); } } @@ -47,7 +45,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs protected Dictionary FileNamesToBytes = new Dictionary(); protected Dictionary> FileNamesToImageSharpImages = new Dictionary>(); - protected Dictionary FileNamesToSystemDrawingImages = new Dictionary(); + protected Dictionary FileNamesToSystemDrawingImages = new Dictionary(); /// /// The values of this enum separate input files into categories @@ -152,7 +150,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs { foreach (KeyValuePair kv in this.FileNames2Bytes) { - using (MemoryStream memoryStream = new MemoryStream(kv.Value)) + using (var memoryStream = new MemoryStream(kv.Value)) { try { @@ -179,7 +177,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs byte[] bytes = kv.Value; string fn = kv.Key; - using (MemoryStream ms1 = new MemoryStream(bytes)) + using (var ms1 = new MemoryStream(bytes)) { this.FileNamesToImageSharpImages[fn] = CoreImage.Load(ms1); @@ -223,7 +221,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs protected void ForEachImageSharpImage(Func, MemoryStream, object> operation) { - using (MemoryStream workStream = new MemoryStream()) + using (var workStream = new MemoryStream()) { this.ForEachImageSharpImage( diff --git a/tests/ImageSharp.Benchmarks/Color/ColorEquality.cs b/tests/ImageSharp.Benchmarks/Color/ColorEquality.cs index 02017cbb7..602e1137f 100644 --- a/tests/ImageSharp.Benchmarks/Color/ColorEquality.cs +++ b/tests/ImageSharp.Benchmarks/Color/ColorEquality.cs @@ -1,14 +1,12 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// -namespace SixLabors.ImageSharp.Benchmarks -{ - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.PixelFormats; +namespace SixLabors.ImageSharp.Benchmarks +{ using SystemColor = System.Drawing.Color; public class ColorEquality diff --git a/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToCieLabConvert.cs b/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToCieLabConvert.cs index cc3472e22..855f5b9b4 100644 --- a/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToCieLabConvert.cs +++ b/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToCieLabConvert.cs @@ -1,13 +1,13 @@ -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces -{ - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; - using Colourful; - using Colourful.Conversion; +using Colourful; +using Colourful.Conversion; - using SixLabors.ImageSharp.ColorSpaces; - using SixLabors.ImageSharp.ColorSpaces.Conversion; +using SixLabors.ImageSharp.ColorSpaces; +using SixLabors.ImageSharp.ColorSpaces.Conversion; +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces +{ public class ColorspaceCieXyzToCieLabConvert { private static readonly CieXyz CieXyz = new CieXyz(0.95047F, 1, 1.08883F); diff --git a/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToHunterLabConvert.cs b/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToHunterLabConvert.cs index d10999518..07870b3a8 100644 --- a/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToHunterLabConvert.cs +++ b/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToHunterLabConvert.cs @@ -1,13 +1,13 @@ -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces -{ - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; - using Colourful; - using Colourful.Conversion; +using Colourful; +using Colourful.Conversion; - using SixLabors.ImageSharp.ColorSpaces; - using SixLabors.ImageSharp.ColorSpaces.Conversion; +using SixLabors.ImageSharp.ColorSpaces; +using SixLabors.ImageSharp.ColorSpaces.Conversion; +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces +{ public class ColorspaceCieXyzToHunterLabConvert { private static readonly CieXyz CieXyz = new CieXyz(0.95047F, 1, 1.08883F); @@ -18,7 +18,6 @@ private static readonly ColourfulConverter ColourfulConverter = new ColourfulConverter(); - [Benchmark(Baseline = true, Description = "Colourful Convert")] public double ColourfulConvert() { diff --git a/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToLmsConvert.cs b/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToLmsConvert.cs index da7b9c3dd..4d9ba8928 100644 --- a/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToLmsConvert.cs +++ b/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToLmsConvert.cs @@ -1,13 +1,13 @@ -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces -{ - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; - using Colourful; - using Colourful.Conversion; +using Colourful; +using Colourful.Conversion; - using SixLabors.ImageSharp.ColorSpaces; - using SixLabors.ImageSharp.ColorSpaces.Conversion; +using SixLabors.ImageSharp.ColorSpaces; +using SixLabors.ImageSharp.ColorSpaces.Conversion; +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces +{ public class ColorspaceCieXyzToLmsConvert { private static readonly CieXyz CieXyz = new CieXyz(0.95047F, 1, 1.08883F); @@ -18,7 +18,6 @@ private static readonly ColourfulConverter ColourfulConverter = new ColourfulConverter(); - [Benchmark(Baseline = true, Description = "Colourful Convert")] public double ColourfulConvert() { diff --git a/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToRgbConvert.cs b/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToRgbConvert.cs index 2a5754ab0..f20ffdcab 100644 --- a/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToRgbConvert.cs +++ b/tests/ImageSharp.Benchmarks/Color/ColorspaceCieXyzToRgbConvert.cs @@ -1,13 +1,13 @@ -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces -{ - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; - using Colourful; - using Colourful.Conversion; +using Colourful; +using Colourful.Conversion; - using SixLabors.ImageSharp.ColorSpaces; - using SixLabors.ImageSharp.ColorSpaces.Conversion; +using SixLabors.ImageSharp.ColorSpaces; +using SixLabors.ImageSharp.ColorSpaces.Conversion; +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces +{ public class ColorspaceCieXyzToRgbConvert { private static readonly CieXyz CieXyz = new CieXyz(0.95047F, 1, 1.08883F); diff --git a/tests/ImageSharp.Benchmarks/Color/RgbToYCbCr.cs b/tests/ImageSharp.Benchmarks/Color/RgbToYCbCr.cs index 07ae17d75..b4e5ab380 100644 --- a/tests/ImageSharp.Benchmarks/Color/RgbToYCbCr.cs +++ b/tests/ImageSharp.Benchmarks/Color/RgbToYCbCr.cs @@ -136,7 +136,7 @@ namespace SixLabors.ImageSharp.Benchmarks OnStackInputCache.Byte input = OnStackInputCache.Byte.Create(this.inputSourceRGB); // On-stack output: - Result result = default(Result); + Result result = default; float* yPtr = (float*)&result.Y; float* cbPtr = (float*)&result.Cb; float* crPtr = (float*)&result.Cr; @@ -162,7 +162,7 @@ namespace SixLabors.ImageSharp.Benchmarks OnStackInputCache.Byte input = OnStackInputCache.Byte.Create(this.inputSourceRGB); // On-stack output: - Result result = default(Result); + Result result = default; float* yPtr = (float*)&result.Y; float* cbPtr = (float*)&result.Cb; float* crPtr = (float*)&result.Cr; @@ -194,15 +194,15 @@ namespace SixLabors.ImageSharp.Benchmarks // Copy the input to the stack: // On-stack output: - Result result = default(Result); + Result result = default; float* yPtr = (float*)&result.Y; float* cbPtr = (float*)&result.Cb; float* crPtr = (float*)&result.Cr; // end of code-bloat block :) - Vector yCoeffs = new Vector(ScaledCoeffs.Y); - Vector cbCoeffs = new Vector(ScaledCoeffs.Cb); - Vector crCoeffs = new Vector(ScaledCoeffs.Cr); + var yCoeffs = new Vector(ScaledCoeffs.Y); + var cbCoeffs = new Vector(ScaledCoeffs.Cb); + var crCoeffs = new Vector(ScaledCoeffs.Cr); for (int i = 0; i < this.inputSourceRGB.Length; i++) { @@ -240,23 +240,23 @@ namespace SixLabors.ImageSharp.Benchmarks // Copy the input to the stack: // On-stack output: - Result result = default(Result); + Result result = default; float* yPtr = (float*)&result.Y; float* cbPtr = (float*)&result.Cb; float* crPtr = (float*)&result.Cr; // end of code-bloat block :) - Vector yCoeffs = new Vector(ScaledCoeffs.Y); - Vector cbCoeffs = new Vector(ScaledCoeffs.Cb); - Vector crCoeffs = new Vector(ScaledCoeffs.Cr); + var yCoeffs = new Vector(ScaledCoeffs.Y); + var cbCoeffs = new Vector(ScaledCoeffs.Cb); + var crCoeffs = new Vector(ScaledCoeffs.Cr); - Vector leftY = new Vector(ScaledCoeffs.SelectLeft.Y); - Vector leftCb = new Vector(ScaledCoeffs.SelectLeft.Cb); - Vector leftCr = new Vector(ScaledCoeffs.SelectLeft.Cr); + var leftY = new Vector(ScaledCoeffs.SelectLeft.Y); + var leftCb = new Vector(ScaledCoeffs.SelectLeft.Cb); + var leftCr = new Vector(ScaledCoeffs.SelectLeft.Cr); - Vector rightY = new Vector(ScaledCoeffs.SelectRight.Y); - Vector rightCb = new Vector(ScaledCoeffs.SelectRight.Cb); - Vector rightCr = new Vector(ScaledCoeffs.SelectRight.Cr); + var rightY = new Vector(ScaledCoeffs.SelectRight.Y); + var rightCb = new Vector(ScaledCoeffs.SelectRight.Cb); + var rightCr = new Vector(ScaledCoeffs.SelectRight.Cr); for (int i = 0; i < this.inputSourceRGB.Length; i++) { diff --git a/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs b/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs index 92008f6e2..060a28550 100644 --- a/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs +++ b/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs @@ -1,13 +1,13 @@ -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces -{ - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; - using Colourful; - using Colourful.Conversion; +using Colourful; +using Colourful.Conversion; - using SixLabors.ImageSharp.ColorSpaces; - using SixLabors.ImageSharp.ColorSpaces.Conversion; +using SixLabors.ImageSharp.ColorSpaces; +using SixLabors.ImageSharp.ColorSpaces.Conversion; +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces +{ public class RgbWorkingSpaceAdapt { private static readonly Rgb Rgb = new Rgb(0.206162F, 0.260277F, 0.746717F, RgbWorkingSpaces.WideGamutRgb); @@ -18,7 +18,6 @@ private static readonly ColourfulConverter ColourfulConverter = new ColourfulConverter { TargetRGBWorkingSpace = RGBWorkingSpaces.sRGB }; - [Benchmark(Baseline = true, Description = "Colourful Adapt")] public RGBColor ColourfulConvert() { diff --git a/tests/ImageSharp.Benchmarks/Config.cs b/tests/ImageSharp.Benchmarks/Config.cs index b46757942..0543cbc50 100644 --- a/tests/ImageSharp.Benchmarks/Config.cs +++ b/tests/ImageSharp.Benchmarks/Config.cs @@ -1,20 +1,17 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Jobs; namespace SixLabors.ImageSharp.Benchmarks { - using BenchmarkDotNet.Jobs; - public class Config : ManualConfig { public Config() { - // Uncomment if you want to use any of the diagnoser - this.Add(new BenchmarkDotNet.Diagnosers.MemoryDiagnoser()); + this.Add(MemoryDiagnoser.Default); } public class ShortClr : Config @@ -22,9 +19,9 @@ namespace SixLabors.ImageSharp.Benchmarks public ShortClr() { this.Add( - Job.Clr.WithLaunchCount(1).WithWarmupCount(3).WithTargetCount(3), - Job.Core.WithLaunchCount(1).WithWarmupCount(3).WithTargetCount(3) - ); + Job.Clr.WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3), + Job.Core.WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3) + ); } } } diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs index 34dd9d4dc..bc9c1c96d 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System.Drawing; using System.Drawing.Drawing2D; @@ -19,27 +17,25 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Baseline = true, Description = "System.Drawing Draw Beziers")] public void DrawPathSystemDrawing() { - using (Bitmap destination = new Bitmap(800, 800)) + using (var destination = new Bitmap(800, 800)) + using (var graphics = Graphics.FromImage(destination)) { + graphics.InterpolationMode = InterpolationMode.Default; + graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (Graphics graphics = Graphics.FromImage(destination)) + using (var pen = new Pen(Color.HotPink, 10)) { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) - { - graphics.DrawBeziers(pen, new[] { - new PointF(10, 500), - new PointF(30, 10), - new PointF(240, 30), - new PointF(300, 500) - }); - } + graphics.DrawBeziers(pen, new[] { + new PointF(10, 500), + new PointF(30, 10), + new PointF(240, 30), + new PointF(300, 500) + }); } - using (MemoryStream ms = new MemoryStream()) + using (var stream = new MemoryStream()) { - destination.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); + destination.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); } } } @@ -47,7 +43,7 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Draw Beziers")] public void DrawLinesCore() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { image.Mutate(x => x.DrawBeziers( Rgba32.HotPink, @@ -59,9 +55,9 @@ namespace SixLabors.ImageSharp.Benchmarks new Vector2(300, 500) })); - using (MemoryStream ms = new MemoryStream()) + using (var stream = new MemoryStream()) { - image.SaveAsBmp(ms); + image.SaveAsBmp(stream); } } } diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs index 091f36762..4265525e5 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs @@ -1,44 +1,41 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// -namespace SixLabors.ImageSharp.Benchmarks -{ - using System.Drawing; - using System.Drawing.Drawing2D; - using System.IO; - using System.Numerics; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.IO; +using System.Numerics; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.PixelFormats; - using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +namespace SixLabors.ImageSharp.Benchmarks +{ public class DrawLines : BenchmarkBase { [Benchmark(Baseline = true, Description = "System.Drawing Draw Lines")] public void DrawPathSystemDrawing() { using (var destination = new Bitmap(800, 800)) + using (var graphics = Graphics.FromImage(destination)) { - using (var graphics = Graphics.FromImage(destination)) + graphics.InterpolationMode = InterpolationMode.Default; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + + using (var pen = new Pen(Color.HotPink, 10)) { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) - { - graphics.DrawLines(pen, new[] { - new PointF(10, 10), - new PointF(550, 50), - new PointF(200, 400) - }); - } + graphics.DrawLines(pen, new[] { + new PointF(10, 10), + new PointF(550, 50), + new PointF(200, 400) + }); } - using (var ms = new MemoryStream()) + using (var stream = new MemoryStream()) { - destination.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); + destination.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); } } } @@ -57,9 +54,9 @@ namespace SixLabors.ImageSharp.Benchmarks new Vector2(200, 400) })); - using (var ms = new MemoryStream()) + using (var stream = new MemoryStream()) { - image.SaveAsBmp(ms); + image.SaveAsBmp(stream); } } } diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs index ab8a7134e..4172b3c38 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System.Drawing; using System.Drawing.Drawing2D; @@ -19,26 +17,23 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Baseline = true, Description = "System.Drawing Draw Polygon")] public void DrawPolygonSystemDrawing() { - using (Bitmap destination = new Bitmap(800, 800)) + using (var destination = new Bitmap(800, 800)) + using (var graphics = Graphics.FromImage(destination)) { - - using (Graphics graphics = Graphics.FromImage(destination)) + graphics.InterpolationMode = InterpolationMode.Default; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + using (var pen = new Pen(Color.HotPink, 10)) { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) - { - graphics.DrawPolygon(pen, new[] { - new PointF(10, 10), - new PointF(550, 50), - new PointF(200, 400) - }); - } + graphics.DrawPolygon(pen, new[] { + new PointF(10, 10), + new PointF(550, 50), + new PointF(200, 400) + }); } - using (MemoryStream ms = new MemoryStream()) + using (var stream = new MemoryStream()) { - destination.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); + destination.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); } } } @@ -46,7 +41,7 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Draw Polygon")] public void DrawPolygonCore() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { image.Mutate(x => x.DrawPolygon( Rgba32.HotPink, @@ -57,7 +52,7 @@ namespace SixLabors.ImageSharp.Benchmarks new Vector2(200, 400) })); - using (MemoryStream ms = new MemoryStream()) + using (var ms = new MemoryStream()) { image.SaveAsBmp(ms); } diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs index 60c58dadc..8c840d8c3 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System.Drawing; using System.Drawing.Drawing2D; @@ -14,11 +12,9 @@ using SixLabors.ImageSharp.Processing.Processors.Text; namespace SixLabors.ImageSharp.Benchmarks { - [MemoryDiagnoser] public class DrawText : BenchmarkBase { - [Params(10, 100)] public int TextIterations { get; set; } public string TextPhrase { get; set; } = "Hello World"; @@ -28,26 +24,22 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Baseline = true, Description = "System.Drawing Draw Text")] public void DrawTextSystemDrawing() { - using (Bitmap destination = new Bitmap(800, 800)) + using (var destination = new Bitmap(800, 800)) + using (var graphics = Graphics.FromImage(destination)) { - - using (Graphics graphics = Graphics.FromImage(destination)) + graphics.InterpolationMode = InterpolationMode.Default; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + using (var font = new Font("Arial", 12, GraphicsUnit.Point)) { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var font = new Font("Arial", 12, GraphicsUnit.Point)) - { - graphics.DrawString(TextToRender, font, System.Drawing.Brushes.HotPink, new RectangleF(10, 10, 780, 780)); - } + graphics.DrawString(TextToRender, font, System.Drawing.Brushes.HotPink, new RectangleF(10, 10, 780, 780)); } } } - [Benchmark(Description = "ImageSharp Draw Text - Cached Glyphs")] public void DrawTextCore() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10)))); @@ -57,7 +49,7 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Draw Text - Nieve")] public void DrawTextCoreOld() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); image.Mutate(x => DrawTextOldVersion(x, new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10))); diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs index 2d6505a91..b99c47960 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System.Drawing; using System.Drawing.Drawing2D; @@ -13,34 +11,28 @@ using SixLabors.ImageSharp.Processing.Processors.Text; namespace SixLabors.ImageSharp.Benchmarks { - [MemoryDiagnoser] public class DrawTextOutline : BenchmarkBase { - [Params(10, 100)] public int TextIterations { get; set; } public string TextPhrase { get; set; } = "Hello World"; public string TextToRender => string.Join(" ", Enumerable.Repeat(TextPhrase, TextIterations)); - [Benchmark(Baseline = true, Description = "System.Drawing Draw Text Outline")] public void DrawTextSystemDrawing() { - using (Bitmap destination = new Bitmap(800, 800)) + using (var destination = new Bitmap(800, 800)) + using (var graphics = Graphics.FromImage(destination)) { - - using (Graphics graphics = Graphics.FromImage(destination)) + graphics.InterpolationMode = InterpolationMode.Default; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + using (var pen = new Pen(Color.HotPink, 10)) + using (var font = new Font("Arial", 12, GraphicsUnit.Point)) + using (var gp = new GraphicsPath()) { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) - using (var font = new Font("Arial", 12, GraphicsUnit.Point)) - using (var gp = new GraphicsPath()) - { - gp.AddString(TextToRender, font.FontFamily, (int)font.Style, font.Size, new RectangleF(10, 10, 780, 780), new StringFormat()); - graphics.DrawPath(pen, gp); - } + gp.AddString(TextToRender, font.FontFamily, (int)font.Style, font.Size, new RectangleF(10, 10, 780, 780), new StringFormat()); + graphics.DrawPath(pen, gp); } } } @@ -48,7 +40,7 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Draw Text Outline - Cached Glyphs")] public void DrawTextCore() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, null, Processing.Pens.Solid(Rgba32.HotPink, 10), new SixLabors.Primitives.PointF(10, 10)))); @@ -58,7 +50,7 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Draw Text Outline - Nieve")] public void DrawTextCoreOld() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); image.Mutate(x => DrawTextOldVersion(x, new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, null, Processing.Pens.Solid(Rgba32.HotPink, 10), new SixLabors.Primitives.PointF(10, 10))); diff --git a/tests/ImageSharp.Benchmarks/Drawing/FillPolygon.cs b/tests/ImageSharp.Benchmarks/Drawing/FillPolygon.cs index 8aadb85bf..396cc18d1 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/FillPolygon.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/FillPolygon.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System.Drawing; using System.Drawing.Drawing2D; @@ -21,31 +19,30 @@ namespace SixLabors.ImageSharp.Benchmarks public FillPolygon() { - this.shape = new Polygon(new LinearLineSegment(new Vector2(10, 10), - new Vector2(550, 50), - new Vector2(200, 400))); + this.shape = new Polygon(new LinearLineSegment( + new Vector2(10, 10), + new Vector2(550, 50), + new Vector2(200, 400))); } [Benchmark(Baseline = true, Description = "System.Drawing Fill Polygon")] public void DrawSolidPolygonSystemDrawing() { - using (Bitmap destination = new Bitmap(800, 800)) + using (var destination = new Bitmap(800, 800)) + + using (var graphics = Graphics.FromImage(destination)) { + graphics.SmoothingMode = SmoothingMode.AntiAlias; + graphics.FillPolygon(System.Drawing.Brushes.HotPink, + new[] { + new Point(10, 10), + new Point(550, 50), + new Point(200, 400) + }); - using (Graphics graphics = Graphics.FromImage(destination)) - { - graphics.SmoothingMode = SmoothingMode.AntiAlias; - graphics.FillPolygon(System.Drawing.Brushes.HotPink, - new[] - { - new Point(10, 10), - new Point(550, 50), - new Point(200, 400) - }); - } - using (MemoryStream ms = new MemoryStream()) + using (var stream = new MemoryStream()) { - destination.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); + destination.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); } } } @@ -53,7 +50,7 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Fill Polygon")] public void DrawSolidPolygonCore() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { image.Mutate(x => x.FillPolygon( Rgba32.HotPink, @@ -63,9 +60,9 @@ namespace SixLabors.ImageSharp.Benchmarks new Vector2(200, 400) })); - using (MemoryStream ms = new MemoryStream()) + using (var stream = new MemoryStream()) { - image.SaveAsBmp(ms); + image.SaveAsBmp(stream); } } } @@ -73,15 +70,15 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Fill Polygon - cached shape")] public void DrawSolidPolygonCoreCahced() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { image.Mutate(x => x.Fill( Rgba32.HotPink, this.shape)); - using (MemoryStream ms = new MemoryStream()) + using (var stream = new MemoryStream()) { - image.SaveAsBmp(ms); + image.SaveAsBmp(stream); } } } diff --git a/tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs b/tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs index 643e4ac9a..d45b791ae 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System.Drawing; using System.Drawing.Drawing2D; @@ -15,22 +13,18 @@ using CoreSize = SixLabors.Primitives.Size; namespace SixLabors.ImageSharp.Benchmarks { - - public class FillRectangle : BenchmarkBase { [Benchmark(Baseline = true, Description = "System.Drawing Fill Rectangle")] public Size FillRectangleSystemDrawing() { - using (Bitmap destination = new Bitmap(800, 800)) + using (var destination = new Bitmap(800, 800)) + using (var graphics = Graphics.FromImage(destination)) { - - using (Graphics graphics = Graphics.FromImage(destination)) - { - graphics.InterpolationMode = InterpolationMode.Default; - graphics.SmoothingMode = SmoothingMode.AntiAlias; - graphics.FillRectangle(System.Drawing.Brushes.HotPink, new Rectangle(10, 10, 190, 140)); - } + graphics.InterpolationMode = InterpolationMode.Default; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + graphics.FillRectangle(System.Drawing.Brushes.HotPink, new Rectangle(10, 10, 190, 140)); + return destination.Size; } } @@ -38,7 +32,7 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Fill Rectangle")] public CoreSize FillRactangleCore() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { image.Mutate(x => x.Fill(Rgba32.HotPink, new CoreRectangle(10, 10, 190, 140))); @@ -49,7 +43,7 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Fill Rectangle - As Polygon")] public CoreSize FillPolygonCore() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { image.Mutate(x => x.FillPolygon( Rgba32.HotPink, diff --git a/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs b/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs index 372361988..3c9cfd7e3 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System.Drawing; using System.Drawing.Drawing2D; @@ -21,19 +19,19 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Baseline = true, Description = "System.Drawing Fill with Pattern")] public void DrawPatternPolygonSystemDrawing() { - using (Bitmap destination = new Bitmap(800, 800)) + using (var destination = new Bitmap(800, 800)) + using (var graphics = Graphics.FromImage(destination)) { - using (Graphics graphics = Graphics.FromImage(destination)) + graphics.SmoothingMode = SmoothingMode.AntiAlias; + + using (var brush = new HatchBrush(HatchStyle.BackwardDiagonal, Color.HotPink)) { - graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var brush = new HatchBrush(HatchStyle.BackwardDiagonal, Color.HotPink)) - { - graphics.FillRectangle(brush, new Rectangle(0, 0, 800, 800)); // can't find a way to flood fill with a brush - } + graphics.FillRectangle(brush, new Rectangle(0, 0, 800, 800)); // can't find a way to flood fill with a brush } - using (MemoryStream ms = new MemoryStream()) + + using (var stream = new MemoryStream()) { - destination.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); + destination.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); } } } @@ -41,13 +39,13 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Fill with Pattern")] public void DrawPatternPolygon3Core() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { image.Mutate(x => x.Fill(CoreBrushes.BackwardDiagonal(Rgba32.HotPink))); - using (MemoryStream ms = new MemoryStream()) + using (var stream = new MemoryStream()) { - image.SaveAsBmp(ms); + image.SaveAsBmp(stream); } } } diff --git a/tests/ImageSharp.Benchmarks/General/Array2D.cs b/tests/ImageSharp.Benchmarks/General/Array2D.cs index 60d89847f..1f8961fcd 100644 --- a/tests/ImageSharp.Benchmarks/General/Array2D.cs +++ b/tests/ImageSharp.Benchmarks/General/Array2D.cs @@ -1,16 +1,14 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// -namespace SixLabors.ImageSharp.Benchmarks.General -{ - using System; +using System; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.Primitives; +using SixLabors.ImageSharp.Primitives; +namespace SixLabors.ImageSharp.Benchmarks.General +{ /** * Method | Count | Mean | Error | StdDev | Scaled | ScaledSD | -------------------------------------------- |------ |---------:|---------:|---------:|-------:|---------:| diff --git a/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs b/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs index ac6b3f93c..41c9ab6c7 100644 --- a/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs +++ b/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs @@ -1,15 +1,14 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// -namespace SixLabors.ImageSharp.Benchmarks.General -{ - using System; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - using BenchmarkDotNet.Attributes; - +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using BenchmarkDotNet.Attributes; + +namespace SixLabors.ImageSharp.Benchmarks.General +{ [Config(typeof(Config.ShortClr))] public class ArrayCopy { diff --git a/tests/ImageSharp.Benchmarks/General/ArrayReverse.cs b/tests/ImageSharp.Benchmarks/General/ArrayReverse.cs index 45a8519a9..c49c383eb 100644 --- a/tests/ImageSharp.Benchmarks/General/ArrayReverse.cs +++ b/tests/ImageSharp.Benchmarks/General/ArrayReverse.cs @@ -1,14 +1,12 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// -namespace SixLabors.ImageSharp.Benchmarks.General -{ - using System; +using System; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +namespace SixLabors.ImageSharp.Benchmarks.General +{ public class ArrayReverse { [Params(4, 16, 32)] @@ -58,4 +56,4 @@ namespace SixLabors.ImageSharp.Benchmarks.General } } } -} +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/BasicMath/ClampInt32IntoByte.cs b/tests/ImageSharp.Benchmarks/General/BasicMath/ClampInt32IntoByte.cs index 6ce82ba11..a8686fc18 100644 --- a/tests/ImageSharp.Benchmarks/General/BasicMath/ClampInt32IntoByte.cs +++ b/tests/ImageSharp.Benchmarks/General/BasicMath/ClampInt32IntoByte.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System; using System.Runtime.CompilerServices; diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToRgba32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToRgba32.cs index d205e1e63..ea8b34c24 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToRgba32.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToRgba32.cs @@ -1,7 +1,4 @@ -// ReSharper disable InconsistentNaming - -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; using BenchmarkDotNet.Attributes; diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToVector4.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToVector4.cs index 2bc3ee971..68a16b791 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToVector4.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToVector4.cs @@ -3,8 +3,6 @@ using System.Runtime.CompilerServices; using BenchmarkDotNet.Attributes; -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion { public class PixelConversion_ConvertToVector4 diff --git a/tests/ImageSharp.Benchmarks/General/Vector4Constants.cs b/tests/ImageSharp.Benchmarks/General/Vector4Constants.cs index ae11806f3..3597207ee 100644 --- a/tests/ImageSharp.Benchmarks/General/Vector4Constants.cs +++ b/tests/ImageSharp.Benchmarks/General/Vector4Constants.cs @@ -1,10 +1,10 @@ -namespace SixLabors.ImageSharp.Benchmarks.General -{ - using System; - using System.Numerics; +using System; +using System.Numerics; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +namespace SixLabors.ImageSharp.Benchmarks.General +{ /// /// Has it any effect on performance to store SIMD constants as static readonly fields? Is it OK to always inline them? /// Spoiler: the difference seems to be statistically insignificant! diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/BitwiseOrUint32.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/BitwiseOrUint32.cs index d189411b5..3afb796a7 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/BitwiseOrUint32.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/BitwiseOrUint32.cs @@ -1,9 +1,9 @@ -namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization -{ - using System.Numerics; +using System.Numerics; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization +{ public class BitwiseOrUInt32 { private uint[] input; diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/DivFloat.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/DivFloat.cs index 637846747..be9534f7d 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/DivFloat.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/DivFloat.cs @@ -1,9 +1,9 @@ -namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization -{ - using System.Numerics; +using System.Numerics; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization +{ public class DivFloat { private float[] input; @@ -41,11 +41,11 @@ namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization [Benchmark] public void Simd() { - Vector v = new Vector(this.testValue); + var v = new Vector(this.testValue); for (int i = 0; i < this.input.Length; i += Vector.Count) { - Vector a = new Vector(this.input, i); + var a = new Vector(this.input, i); a = a / v; a.CopyTo(this.result, i); } diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/DivUInt32.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/DivUInt32.cs index 49ada2f36..bfc8d3de3 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/DivUInt32.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/DivUInt32.cs @@ -1,9 +1,9 @@ -namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization -{ - using System.Numerics; +using System.Numerics; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization +{ public class DivUInt32 { private uint[] input; @@ -32,6 +32,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization public void Standard() { uint v = this.testValue; + for (int i = 0; i < this.input.Length; i++) { this.result[i] = this.input[i] / v; @@ -41,11 +42,12 @@ namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization [Benchmark] public void Simd() { - Vector v = new Vector(this.testValue); + var v = new Vector(this.testValue); for (int i = 0; i < this.input.Length; i += Vector.Count) { - Vector a = new Vector(this.input, i); + var a = new Vector(this.input, i); + a = a / v; a.CopyTo(this.result, i); } diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/Divide.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/Divide.cs index b38429557..df09aa569 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/Divide.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/Divide.cs @@ -1,10 +1,9 @@ -namespace ImageSharp.Benchmarks.General.Vectorization -{ - using System; - using System.Numerics; +using System.Numerics; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +namespace ImageSharp.Benchmarks.General.Vectorization +{ public class DivFloat : SIMDBenchmarkBase.Divide { protected override float GetTestValue() => 42; diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/MulFloat.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/MulFloat.cs index 8c5f56818..418209cbc 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/MulFloat.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/MulFloat.cs @@ -1,9 +1,9 @@ -namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization -{ - using System.Numerics; +using System.Numerics; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization +{ public class MulFloat { private float[] input; diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/MulUInt32.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/MulUInt32.cs index 913d4ce3c..7253dbd6a 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/MulUInt32.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/MulUInt32.cs @@ -1,9 +1,9 @@ -namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization -{ - using System.Numerics; +using System.Numerics; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization +{ public class MulUInt32 { private uint[] input; @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization [Benchmark] public void Simd() { - Vector v = new Vector(this.testValue); + var v = new Vector(this.testValue); for (int i = 0; i < this.input.Length; i += Vector.Count) { diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/Multiply.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/Multiply.cs index d1b70f21b..7a679c000 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/Multiply.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/Multiply.cs @@ -1,8 +1,8 @@ +using System.Numerics; +using BenchmarkDotNet.Attributes; + namespace ImageSharp.Benchmarks.General.Vectorization { - using System.Numerics; - using BenchmarkDotNet.Attributes; - public class MulUInt32 : SIMDBenchmarkBase.Multiply { protected override uint GetTestValue() => 42u; diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/ReinterpretUInt32AsFloat.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/ReinterpretUInt32AsFloat.cs index f3853a8b1..67a8a9f39 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/ReinterpretUInt32AsFloat.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/ReinterpretUInt32AsFloat.cs @@ -1,10 +1,10 @@ -namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization -{ - using System.Numerics; - using System.Runtime.InteropServices; +using System.Numerics; +using System.Runtime.InteropServices; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization +{ public class ReinterpretUInt32AsFloat { private uint[] input; @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization [Benchmark(Baseline = true)] public void Standard() { - UIntFloatUnion u = default(UIntFloatUnion); + UIntFloatUnion u = default; for (int i = 0; i < this.input.Length; i++) { u.i = this.input[i]; diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/SIMDBenchmarkBase.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/SIMDBenchmarkBase.cs index 76987dbd2..8fc9d9977 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/SIMDBenchmarkBase.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/SIMDBenchmarkBase.cs @@ -1,10 +1,10 @@ -namespace ImageSharp.Benchmarks.General.Vectorization -{ - using System.Numerics; - using System.Runtime.CompilerServices; +using System.Numerics; +using System.Runtime.CompilerServices; - using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; +namespace ImageSharp.Benchmarks.General.Vectorization +{ public abstract class SIMDBenchmarkBase where T : struct { @@ -19,7 +19,6 @@ namespace ImageSharp.Benchmarks.General.Vectorization protected virtual T GetTestValue() => default(T); protected virtual Vector GetTestVector() => new Vector(this.GetTestValue()); - [Params(32)] public int InputSize { get; set; } diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index f941203db..e600af785 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -16,10 +16,10 @@ - - + + - + diff --git a/tests/ImageSharp.Benchmarks/Program.cs b/tests/ImageSharp.Benchmarks/Program.cs index 4dd63067a..5caf238fb 100644 --- a/tests/ImageSharp.Benchmarks/Program.cs +++ b/tests/ImageSharp.Benchmarks/Program.cs @@ -1,15 +1,12 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// + +using System.Reflection; + +using BenchmarkDotNet.Running; namespace SixLabors.ImageSharp.Benchmarks { - using BenchmarkDotNet.Running; - - using SixLabors.ImageSharp.Formats; - using System.Reflection; - public class Program { /// diff --git a/tests/ImageSharp.Benchmarks/Samplers/Crop.cs b/tests/ImageSharp.Benchmarks/Samplers/Crop.cs index 240a277cf..4fe7a365f 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Crop.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Crop.cs @@ -1,46 +1,40 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using SixLabors.ImageSharp.PixelFormats; -namespace SixLabors.ImageSharp.Benchmarks -{ - using System.Drawing; - using System.Drawing.Drawing2D; +using System.Drawing; +using System.Drawing.Drawing2D; - using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.Processing; +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Processing; - using CoreSize = SixLabors.Primitives.Size; +using CoreSize = SixLabors.Primitives.Size; +namespace SixLabors.ImageSharp.Benchmarks +{ public class Crop : BenchmarkBase { [Benchmark(Baseline = true, Description = "System.Drawing Crop")] public Size CropSystemDrawing() { - using (Bitmap source = new Bitmap(800, 800)) + using (var source = new Bitmap(800, 800)) + using (var destination = new Bitmap(100, 100)) + using (var graphics = Graphics.FromImage(destination)) { - using (Bitmap destination = new Bitmap(100, 100)) - { - using (Graphics graphics = Graphics.FromImage(destination)) - { - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.DrawImage(source, new Rectangle(0, 0, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel); - } - - return destination.Size; - } + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.DrawImage(source, new Rectangle(0, 0, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel); + + return destination.Size; } } [Benchmark(Description = "ImageSharp Crop")] public CoreSize CropResizeCore() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { image.Mutate(x => x.Crop(100, 100)); return new CoreSize(image.Width, image.Height); diff --git a/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs b/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs index 006d1b639..b36b28ef3 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using SixLabors.ImageSharp.PixelFormats; @@ -53,4 +51,4 @@ namespace SixLabors.ImageSharp.Benchmarks this.image.Mutate(x => x.DetectEdges(EdgeDetectionOperators.Sobel)); } } -} +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs index 729971548..15b82e022 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs @@ -4,7 +4,6 @@ using System; using System.Buffers; using System.Numerics; -using System.Threading.Tasks; using BenchmarkDotNet.Attributes; @@ -35,7 +34,7 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Glow - Bulk")] public CoreSize GlowBulk() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { this.bulk.Apply(image, image.Bounds()); return new CoreSize(image.Width, image.Height); @@ -45,7 +44,7 @@ namespace SixLabors.ImageSharp.Benchmarks [Benchmark(Description = "ImageSharp Glow - Parallel")] public CoreSize GLowSimple() { - using (Image image = new Image(800, 800)) + using (var image = new Image(800, 800)) { this.parallel.Apply(image, image.Bounds()); return new CoreSize(image.Width, image.Height); @@ -128,7 +127,7 @@ namespace SixLabors.ImageSharp.Benchmarks int offsetX = x - startX; float distance = Vector2.Distance(centre, new Vector2(offsetX, offsetY)); Vector4 sourceColor = sourcePixels[offsetX, offsetY].ToVector4(); - TPixel packed = default(TPixel); + TPixel packed = default; packed.FromVector4( PremultipliedLerp( sourceColor, @@ -166,9 +165,9 @@ namespace SixLabors.ImageSharp.Benchmarks // https://en.wikipedia.org/wiki/Alpha_compositing // Vout = Vs + Vb (1 - Vsa) // Aout = Vsa + Vsb (1 - Vsa) - Vector3 inverseW = new Vector3(1 - source.W); - Vector3 xyzB = new Vector3(backdrop.X, backdrop.Y, backdrop.Z); - Vector3 xyzS = new Vector3(source.X, source.Y, source.Z); + var inverseW = new Vector3(1 - source.W); + var xyzB = new Vector3(backdrop.X, backdrop.Y, backdrop.Z); + var xyzS = new Vector3(source.X, source.Y, source.Z); return new Vector4(xyzS + (xyzB * inverseW), source.W + (backdrop.W * (1 - source.W))); } diff --git a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs index 51f3a5653..e99163f8b 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Drawing; using System.Drawing.Drawing2D; diff --git a/tests/ImageSharp.Benchmarks/Samplers/Rotate.cs b/tests/ImageSharp.Benchmarks/Samplers/Rotate.cs index f898576af..69ff1549b 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Rotate.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Rotate.cs @@ -1,4 +1,7 @@ -using BenchmarkDotNet.Attributes; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.Primitives; diff --git a/tests/ImageSharp.Benchmarks/Samplers/Skew.cs b/tests/ImageSharp.Benchmarks/Samplers/Skew.cs index 84819750a..559e49704 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Skew.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Skew.cs @@ -1,4 +1,7 @@ -using BenchmarkDotNet.Attributes; +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.Primitives; From 4d38d7c426f4b6135230c052ce20c0a22d79862a Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 14 Apr 2019 17:51:30 +0200 Subject: [PATCH 057/223] ResizeWindowOld --- .../Transforms/Resize/ResizeProcessor.cs | 122 +++++++++++++++--- .../Transforms/ResizeKernelMapTests.cs | 7 +- .../Processors/Transforms/ResizeTests.cs | 13 +- 3 files changed, 119 insertions(+), 23 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 8c911cbfa..429b709ee 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -244,26 +244,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm // First process the columns. Since we are not using multiple threads startY and endY // are the upper and lower bounds of the source rectangle. - using (Buffer2D firstPassPixelsTransposed = source.MemoryAllocator.Allocate2D(sourceHeight, width)) + //using (Buffer2D firstPassPixelsTransposed = source.MemoryAllocator.Allocate2D(sourceHeight, width)) + + using (var resizeWindow = new ResizeWindowOld( + configuration, + sourceRectangle, + conversionModifiers, + this.horizontalKernelMap, + this.verticalKernelMap, + sourceHeight, + width, + minX, + maxX, + startX)) using (IMemoryOwner tempBuffer = source.MemoryAllocator.Allocate(Math.Max(source.Width, width))) { - firstPassPixelsTransposed.MemorySource.Clear(); + Span tempRowSpan = tempBuffer.GetSpan().Slice(sourceX, source.Width - sourceX); - for (int y = 0; y < sourceRectangle.Bottom; y++) - { - Span sourceRow = source.GetPixelRowSpan(y).Slice(sourceX); - Span tempRowSpan = tempBuffer.GetSpan().Slice(sourceX, source.Width - sourceX); - - PixelOperations.Instance.ToVector4(configuration, sourceRow, tempRowSpan, conversionModifiers); - - ref Vector4 firstPassBaseRef = ref firstPassPixelsTransposed.Span[y]; - - for (int x = minX; x < maxX; x++) - { - ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - startX); - Unsafe.Add(ref firstPassBaseRef, x * sourceHeight) = kernel.Convolve(tempRowSpan); - } - } + resizeWindow.Initialize(source.PixelBuffer, tempRowSpan); // Now process the rows. Span tempColSpan = tempBuffer.GetSpan().Slice(0, width); @@ -277,7 +275,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = 0; x < width; x++) { - Span firstPassColumn = firstPassPixelsTransposed.GetRowSpan(x).Slice(sourceY); + Span firstPassColumn = resizeWindow.GetColumnSpan(x); // Destination color components Unsafe.Add(ref tempRowBase, x) = kernel.Convolve(firstPassColumn); @@ -301,4 +299,92 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.verticalKernelMap = null; } } + + class ResizeWindowOld : IDisposable + { + private readonly Buffer2D buffer; + + private readonly Configuration configuration; + + private readonly Rectangle sourceRectangle; + + private readonly PixelConversionModifiers conversionModifiers; + + private readonly ResizeKernelMap horizontalKernelMap; + + private readonly ResizeKernelMap verticalKernelMap; + + private readonly int minX; + + private readonly int maxX; + + private readonly int startX; + + public ResizeWindowOld( + Configuration configuration, + Rectangle sourceRectangle, + PixelConversionModifiers conversionModifiers, + ResizeKernelMap horizontalKernelMap, + ResizeKernelMap verticalKernelMap, + int sourceHeight, + int destWidth, + int minX, + int maxX, + int startX) + { + this.configuration = configuration; + this.sourceRectangle = sourceRectangle; + this.conversionModifiers = conversionModifiers; + this.horizontalKernelMap = horizontalKernelMap; + this.verticalKernelMap = verticalKernelMap; + this.minX = minX; + this.maxX = maxX; + this.startX = startX; + this.buffer = configuration.MemoryAllocator.Allocate2D(sourceRectangle.Height, destWidth, AllocationOptions.Clean); + + this.Top = sourceRectangle.Top; + + this.Bottom = sourceRectangle.Bottom; + } + + public int Top { get; private set; } + + public int Bottom { get; private set; } + + public void Initialize( + Buffer2D source, + Span tempRowSpan) + where TPixel : struct, IPixel + { + for (int y = this.sourceRectangle.Top; y < this.sourceRectangle.Bottom; y++) + { + Span sourceRow = source.GetRowSpan(y).Slice(this.sourceRectangle.X); + + PixelOperations.Instance.ToVector4( + this.configuration, + sourceRow, + tempRowSpan, + this.conversionModifiers); + + ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - this.sourceRectangle.Y]; + + for (int x = this.minX; x < this.maxX; x++) + { + ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); + Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Span GetColumnSpan(int x) + { + return this.buffer.GetRowSpan(x); + } + + public void Dispose() + { + this.buffer.Dispose(); + } + } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs index 5d3790f07..9de866586 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs @@ -93,7 +93,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms GenerateImageResizeData(); - [Theory(Skip = "Only for debugging and development")] + [Theory( + Skip = "Only for debugging and development" + )] [MemberData(nameof(KernelMapData))] public void PrintNonNormalizedKernelMap(string resamplerName, int srcSize, int destSize) { @@ -130,7 +132,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms var referenceMap = ReferenceKernelMap.Calculate(resampler, destSize, srcSize); var kernelMap = ResizeKernelMap.Calculate(resampler, destSize, srcSize, Configuration.Default.MemoryAllocator); + + #if DEBUG + this.Output.WriteLine(kernelMap.Info); this.Output.WriteLine($"Expected KernelMap:\n{PrintKernelMap(referenceMap)}\n"); this.Output.WriteLine($"Actual KernelMap:\n{PrintKernelMap(kernelMap)}\n"); #endif diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 7f1f5a26a..5cea8ddae 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -5,6 +5,7 @@ using System; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; @@ -37,19 +38,23 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; [Theory] - [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32)] - public void Resize_BasicSmall(TestImageProvider provider) + [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32, 2, 3, 1, 2)] + [WithBasicTestPatternImages(2, 256, PixelTypes.Rgba32, 1, 1, 1, 8)] + [WithBasicTestPatternImages(2, 32, PixelTypes.Rgba32, 1, 1, 1, 2)] + public void Resize_BasicSmall(TestImageProvider provider, int wN, int wD, int hN, int hD) where TPixel : struct, IPixel { // Basic test case, very helpful for debugging + // [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32, 2, 3, 1, 2)] means: // resizing: (15, 12) -> (10, 6) // kernel dimensions: (3, 4) using (Image image = provider.GetImage()) { - var destSize = new Size(image.Width * 2 / 3, image.Height / 2); + var destSize = new Size(image.Width * wN / wD, image.Height * hN / hD); image.Mutate(x => x.Resize(destSize, KnownResamplers.Bicubic, false)); - image.DebugSave(provider); + FormattableString outputInfo = $"({wN}÷{wD},{hN}÷{hD})"; + image.DebugSave(provider, outputInfo); } } From f81939e79177ba571dc429806ed96c4c11d49fbb Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 14 Apr 2019 18:37:16 +0200 Subject: [PATCH 058/223] ResizeWindow refactor 1 --- .../Transforms/Resize/ResizeProcessor.cs | 115 ++---------------- .../Transforms/Resize/ResizeWindow.cs | 97 +++++++++++++++ 2 files changed, 106 insertions(+), 106 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 429b709ee..707be1ec9 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -195,19 +195,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int sourceX = sourceRectangle.X; int sourceY = sourceRectangle.Y; int startY = this.TargetRectangle.Y; - int endY = this.TargetRectangle.Bottom; int startX = this.TargetRectangle.X; - int endX = this.TargetRectangle.Right; - int minX = Math.Max(0, startX); - int maxX = Math.Min(width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(height, endY); + var workingRect = Rectangle.Intersect( + this.TargetRectangle, + new Rectangle(0, 0, width, height)); if (this.Sampler is NearestNeighborResampler) { - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); - // Scaling factors float widthFactor = sourceRectangle.Width / (float)this.TargetRectangle.Width; float heightFactor = sourceRectangle.Height / (float)this.TargetRectangle.Height; @@ -224,7 +219,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); Span targetRow = destination.GetPixelRowSpan(y); - for (int x = minX; x < maxX; x++) + for (int x = workingRect.Left; x < workingRect.Right; x++) { // X coordinates of source points targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; @@ -244,29 +239,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm // First process the columns. Since we are not using multiple threads startY and endY // are the upper and lower bounds of the source rectangle. - //using (Buffer2D firstPassPixelsTransposed = source.MemoryAllocator.Allocate2D(sourceHeight, width)) - - using (var resizeWindow = new ResizeWindowOld( + using (var resizeWindow = new ResizeWindow( configuration, sourceRectangle, conversionModifiers, this.horizontalKernelMap, this.verticalKernelMap, - sourceHeight, width, - minX, - maxX, + workingRect, startX)) - using (IMemoryOwner tempBuffer = source.MemoryAllocator.Allocate(Math.Max(source.Width, width))) + using (IMemoryOwner tempBuffer = source.MemoryAllocator.Allocate(Math.Max(sourceRectangle.Width, width))) { - Span tempRowSpan = tempBuffer.GetSpan().Slice(sourceX, source.Width - sourceX); + Span tempRowSpan = tempBuffer.GetSpan(); resizeWindow.Initialize(source.PixelBuffer, tempRowSpan); // Now process the rows. Span tempColSpan = tempBuffer.GetSpan().Slice(0, width); - for (int y = minY; y < maxY; y++) + for (int y = workingRect.Top; y < workingRect.Bottom; y++) { // Ensure offsets are normalized for cropping and padding. ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); @@ -299,92 +290,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.verticalKernelMap = null; } } - - class ResizeWindowOld : IDisposable - { - private readonly Buffer2D buffer; - - private readonly Configuration configuration; - - private readonly Rectangle sourceRectangle; - - private readonly PixelConversionModifiers conversionModifiers; - - private readonly ResizeKernelMap horizontalKernelMap; - - private readonly ResizeKernelMap verticalKernelMap; - - private readonly int minX; - - private readonly int maxX; - - private readonly int startX; - - public ResizeWindowOld( - Configuration configuration, - Rectangle sourceRectangle, - PixelConversionModifiers conversionModifiers, - ResizeKernelMap horizontalKernelMap, - ResizeKernelMap verticalKernelMap, - int sourceHeight, - int destWidth, - int minX, - int maxX, - int startX) - { - this.configuration = configuration; - this.sourceRectangle = sourceRectangle; - this.conversionModifiers = conversionModifiers; - this.horizontalKernelMap = horizontalKernelMap; - this.verticalKernelMap = verticalKernelMap; - this.minX = minX; - this.maxX = maxX; - this.startX = startX; - this.buffer = configuration.MemoryAllocator.Allocate2D(sourceRectangle.Height, destWidth, AllocationOptions.Clean); - - this.Top = sourceRectangle.Top; - - this.Bottom = sourceRectangle.Bottom; - } - - public int Top { get; private set; } - - public int Bottom { get; private set; } - - public void Initialize( - Buffer2D source, - Span tempRowSpan) - where TPixel : struct, IPixel - { - for (int y = this.sourceRectangle.Top; y < this.sourceRectangle.Bottom; y++) - { - Span sourceRow = source.GetRowSpan(y).Slice(this.sourceRectangle.X); - - PixelOperations.Instance.ToVector4( - this.configuration, - sourceRow, - tempRowSpan, - this.conversionModifiers); - - ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - this.sourceRectangle.Y]; - - for (int x = this.minX; x < this.maxX; x++) - { - ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); - Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span GetColumnSpan(int x) - { - return this.buffer.GetRowSpan(x); - } - - public void Dispose() - { - this.buffer.Dispose(); - } - } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs new file mode 100644 index 000000000..130dd93a4 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs @@ -0,0 +1,97 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + class ResizeWindow : IDisposable + { + private readonly Buffer2D buffer; + + private readonly Configuration configuration; + + private readonly Rectangle sourceRectangle; + + private readonly PixelConversionModifiers conversionModifiers; + + private readonly ResizeKernelMap horizontalKernelMap; + + private readonly ResizeKernelMap verticalKernelMap; + + private readonly Rectangle workingRectangle; + + private readonly int startX; + + public ResizeWindow( + Configuration configuration, + Rectangle sourceRectangle, + PixelConversionModifiers conversionModifiers, + ResizeKernelMap horizontalKernelMap, + ResizeKernelMap verticalKernelMap, + int destWidth, + Rectangle workingRectangle, + int startX) + { + this.configuration = configuration; + this.sourceRectangle = sourceRectangle; + this.conversionModifiers = conversionModifiers; + this.horizontalKernelMap = horizontalKernelMap; + this.verticalKernelMap = verticalKernelMap; + this.workingRectangle = workingRectangle; + this.startX = startX; + this.buffer = configuration.MemoryAllocator.Allocate2D(sourceRectangle.Height, destWidth, AllocationOptions.Clean); + + this.Top = sourceRectangle.Top; + + this.Bottom = sourceRectangle.Bottom; + } + + public int Top { get; private set; } + + public int Bottom { get; private set; } + + public void Initialize( + Buffer2D source, + Span tempRowSpan) + where TPixel : struct, IPixel + { + for (int y = this.sourceRectangle.Top; y < this.sourceRectangle.Bottom; y++) + { + Span sourceRow = source.GetRowSpan(y).Slice(this.sourceRectangle.X); + + PixelOperations.Instance.ToVector4( + this.configuration, + sourceRow, + tempRowSpan, + this.conversionModifiers); + + ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - this.sourceRectangle.Y]; + + for (int x = this.workingRectangle.Left; x < this.workingRectangle.Right; x++) + { + ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); + Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Span GetColumnSpan(int x) + { + return this.buffer.GetRowSpan(x); + } + + public void Dispose() + { + this.buffer.Dispose(); + } + } +} \ No newline at end of file From 7079410229079411250a9cbeed9307dae5e3bad7 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 14 Apr 2019 21:19:43 +0200 Subject: [PATCH 059/223] ResizeWindow refactor 2 --- .../Transforms/Resize/ResizeProcessor.cs | 14 ++-- .../Transforms/Resize/ResizeWindow.cs | 67 +++++++++++-------- 2 files changed, 45 insertions(+), 36 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 707be1ec9..b4b537e20 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -235,27 +235,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms PixelConversionModifiers conversionModifiers = PixelConversionModifiers.Premultiply.ApplyCompanding(this.Compand); + BufferArea sourceArea = source.PixelBuffer.GetArea(sourceRectangle); + // Interpolate the image using the calculated weights. // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm // First process the columns. Since we are not using multiple threads startY and endY // are the upper and lower bounds of the source rectangle. - using (var resizeWindow = new ResizeWindow( + using (var resizeWindow = new ResizeWindow( configuration, - sourceRectangle, + sourceArea, conversionModifiers, this.horizontalKernelMap, this.verticalKernelMap, width, workingRect, startX)) - using (IMemoryOwner tempBuffer = source.MemoryAllocator.Allocate(Math.Max(sourceRectangle.Width, width))) + using (IMemoryOwner tempBuffer = source.MemoryAllocator.Allocate(width)) { - Span tempRowSpan = tempBuffer.GetSpan(); - - resizeWindow.Initialize(source.PixelBuffer, tempRowSpan); + resizeWindow.Initialize(); // Now process the rows. - Span tempColSpan = tempBuffer.GetSpan().Slice(0, width); + Span tempColSpan = tempBuffer.GetSpan(); for (int y = workingRect.Top; y < workingRect.Bottom; y++) { diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs index 130dd93a4..bd68fdba7 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; @@ -12,27 +13,32 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { - class ResizeWindow : IDisposable + class ResizeWindow : IDisposable + where TPixel : struct, IPixel { private readonly Buffer2D buffer; private readonly Configuration configuration; - private readonly Rectangle sourceRectangle; - private readonly PixelConversionModifiers conversionModifiers; private readonly ResizeKernelMap horizontalKernelMap; - private readonly ResizeKernelMap verticalKernelMap; + private readonly BufferArea source; - private readonly Rectangle workingRectangle; + private readonly Rectangle sourceRectangle; private readonly int startX; + private readonly IMemoryOwner tempRowBuffer; + + private readonly ResizeKernelMap verticalKernelMap; + + private readonly Rectangle workingRectangle; + public ResizeWindow( Configuration configuration, - Rectangle sourceRectangle, + BufferArea source, PixelConversionModifiers conversionModifiers, ResizeKernelMap horizontalKernelMap, ResizeKernelMap verticalKernelMap, @@ -41,31 +47,45 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int startX) { this.configuration = configuration; - this.sourceRectangle = sourceRectangle; + this.source = source; + this.sourceRectangle = source.Rectangle; this.conversionModifiers = conversionModifiers; this.horizontalKernelMap = horizontalKernelMap; this.verticalKernelMap = verticalKernelMap; this.workingRectangle = workingRectangle; this.startX = startX; - this.buffer = configuration.MemoryAllocator.Allocate2D(sourceRectangle.Height, destWidth, AllocationOptions.Clean); + this.buffer = configuration.MemoryAllocator.Allocate2D( + this.sourceRectangle.Height, + destWidth, + AllocationOptions.Clean); + this.tempRowBuffer = configuration.MemoryAllocator.Allocate(this.sourceRectangle.Width); - this.Top = sourceRectangle.Top; + this.Top = this.sourceRectangle.Top; - this.Bottom = sourceRectangle.Bottom; + this.Bottom = this.sourceRectangle.Bottom; } + public int Bottom { get; private set; } + public int Top { get; private set; } - public int Bottom { get; private set; } + public void Dispose() + { + this.buffer.Dispose(); + } - public void Initialize( - Buffer2D source, - Span tempRowSpan) - where TPixel : struct, IPixel + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Span GetColumnSpan(int x) { - for (int y = this.sourceRectangle.Top; y < this.sourceRectangle.Bottom; y++) + return this.buffer.GetRowSpan(x); + } + + public void Initialize() + { + Span tempRowSpan = this.tempRowBuffer.GetSpan(); + for (int y = 0; y < this.sourceRectangle.Height; y++) { - Span sourceRow = source.GetRowSpan(y).Slice(this.sourceRectangle.X); + Span sourceRow = this.source.GetRowSpan(y); PixelOperations.Instance.ToVector4( this.configuration, @@ -73,7 +93,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms tempRowSpan, this.conversionModifiers); - ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - this.sourceRectangle.Y]; + ref Vector4 firstPassBaseRef = ref this.buffer.Span[y]; for (int x = this.workingRectangle.Left; x < this.workingRectangle.Right; x++) { @@ -82,16 +102,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } } } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span GetColumnSpan(int x) - { - return this.buffer.GetRowSpan(x); - } - - public void Dispose() - { - this.buffer.Dispose(); - } } } \ No newline at end of file From 545abf2d0614437ad7cdab827b89f4d67bcb00be Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 14 Apr 2019 21:59:06 +0200 Subject: [PATCH 060/223] ResizeWindow refactor 3 --- .../Transforms/Resize/ResizeKernelMap.cs | 11 +- .../Transforms/Resize/ResizeProcessor.cs | 5 + .../Transforms/Resize/ResizeWindow.cs | 12 +- .../Processors/Transforms/ResizeTests.cs | 433 +++++++++--------- 4 files changed, 245 insertions(+), 216 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs index 2ab574df2..9abbb66e3 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs @@ -54,11 +54,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.radius = radius; this.sourceLength = sourceLength; this.DestinationLength = destinationLength; - int maxWidth = (radius * 2) + 1; - this.data = memoryAllocator.Allocate2D(maxWidth, bufferHeight, AllocationOptions.Clean); + this.MaxDiameter = (radius * 2) + 1; + this.data = memoryAllocator.Allocate2D(this.MaxDiameter, bufferHeight, AllocationOptions.Clean); this.pinHandle = this.data.Memory.Pin(); this.kernels = new ResizeKernel[destinationLength]; - this.tempValues = new double[maxWidth]; + this.tempValues = new double[this.MaxDiameter]; } /// @@ -66,6 +66,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public int DestinationLength { get; } + /// + /// Gets the maximum diameter of the kernels. + /// + public int MaxDiameter { get; } + /// /// Gets a string of information to help debugging /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index b4b537e20..38419b5dd 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -262,6 +262,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Ensure offsets are normalized for cropping and padding. ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); + if (kernel.Left + kernel.Length > resizeWindow.Bottom) + { + resizeWindow.Slide(); + } + ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempColSpan); for (int x = 0; x < width; x++) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs index bd68fdba7..05015dee2 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs @@ -13,7 +13,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { - class ResizeWindow : IDisposable + internal class ResizeWindow : IDisposable where TPixel : struct, IPixel { private readonly Buffer2D buffer; @@ -36,6 +36,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly Rectangle workingRectangle; + private readonly int diameter; + public ResizeWindow( Configuration configuration, BufferArea source, @@ -54,6 +56,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.verticalKernelMap = verticalKernelMap; this.workingRectangle = workingRectangle; this.startX = startX; + + this.diameter = verticalKernelMap.MaxDiameter; + this.buffer = configuration.MemoryAllocator.Allocate2D( this.sourceRectangle.Height, destWidth, @@ -102,5 +107,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } } } + + public void Slide() + { + throw new InvalidOperationException("Shouldn't happen yet!"); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 5cea8ddae..8c59fff26 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -5,38 +5,92 @@ using System; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.Primitives; using Xunit; + // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { public class ResizeTests { - public static readonly string[] CommonTestImages = { TestImages.Png.CalliphoraPartial }; + private const PixelTypes CommonNonDefaultPixelTypes = + PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; - private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.07F); + private const PixelTypes DefaultPixelType = PixelTypes.Rgba32; public static readonly string[] AllResamplerNames = TestUtils.GetAllResamplerNames(); + public static readonly string[] CommonTestImages = { TestImages.Png.CalliphoraPartial }; + public static readonly string[] SmokeTestResamplerNames = { - nameof(KnownResamplers.NearestNeighbor), - nameof(KnownResamplers.Bicubic), - nameof(KnownResamplers.Box), + nameof(KnownResamplers.NearestNeighbor), nameof(KnownResamplers.Bicubic), nameof(KnownResamplers.Box), nameof(KnownResamplers.Lanczos5), }; - private const PixelTypes DefaultPixelType = PixelTypes.Rgba32; + private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.07F); + + [Theory] + [InlineData(-2, 0)] + [InlineData(-1, 0)] + [InlineData(0, 1)] + [InlineData(1, 0)] + [InlineData(2, 0)] + public static void BicubicWindowOscillatesCorrectly(float x, float expected) + { + IResampler sampler = KnownResamplers.Bicubic; + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + + [Theory] + [InlineData(-2, 0)] + [InlineData(-1, 0)] + [InlineData(0, 1)] + [InlineData(1, 0)] + [InlineData(2, 0)] + public static void Lanczos3WindowOscillatesCorrectly(float x, float expected) + { + IResampler sampler = KnownResamplers.Lanczos3; + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + + [Theory] + [InlineData(-4, 0)] + [InlineData(-2, 0)] + [InlineData(0, 1)] + [InlineData(2, 0)] + [InlineData(4, 0)] + public static void Lanczos5WindowOscillatesCorrectly(float x, float expected) + { + IResampler sampler = KnownResamplers.Lanczos5; + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + + [Theory] + [InlineData(-2, 0)] + [InlineData(-1, 0)] + [InlineData(0, 1)] + [InlineData(1, 0)] + [InlineData(2, 0)] + public static void TriangleWindowOscillatesCorrectly(float x, float expected) + { + IResampler sampler = KnownResamplers.Triangle; + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } - private const PixelTypes CommonNonDefaultPixelTypes = - PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; - [Theory] [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32, 2, 3, 1, 2)] [WithBasicTestPatternImages(2, 256, PixelTypes.Rgba32, 1, 1, 1, 8)] @@ -54,14 +108,117 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms var destSize = new Size(image.Width * wN / wD, image.Height * hN / hD); image.Mutate(x => x.Resize(destSize, KnownResamplers.Bicubic, false)); FormattableString outputInfo = $"({wN}÷{wD},{hN}÷{hD})"; - image.DebugSave(provider, outputInfo); + image.DebugSave(provider, outputInfo, appendPixelTypeToFileName: false); + image.CompareToReferenceOutput(provider, outputInfo, appendPixelTypeToFileName: false); + } + } + + [Theory] + [WithTestPatternImages(100, 100, DefaultPixelType)] + public void Resize_Compand(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Mutate(x => x.Resize(image.Size() / 2, true)); + + image.DebugSave(provider); + image.CompareToReferenceOutput(ValidatorComparer, provider); + } + } + + [Theory] + [WithFile(TestImages.Png.Kaboom, DefaultPixelType, false)] + [WithFile(TestImages.Png.Kaboom, DefaultPixelType, true)] + public void Resize_DoesNotBleedAlphaPixels(TestImageProvider provider, bool compand) + where TPixel : struct, IPixel + { + string details = compand ? "Compand" : ""; + + provider.RunValidatingProcessorTest( + x => x.Resize(x.GetCurrentSize() / 2, compand), + details, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + + [Theory] + [WithFile(TestImages.Gif.Giphy, DefaultPixelType)] + public void Resize_IsAppliedToAllFrames(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2, KnownResamplers.Bicubic)); + + // Comparer fights decoder with gif-s. Could not use CompareToReferenceOutput here :( + image.DebugSave(provider, extension: "gif"); + } + } + + [Theory] + [WithTestPatternImages(50, 50, CommonNonDefaultPixelTypes)] + public void Resize_IsNotBoundToSinglePixelType(TestImageProvider provider) + where TPixel : struct, IPixel + { + provider.RunValidatingProcessorTest(x => x.Resize(x.GetCurrentSize() / 2), comparer: ValidatorComparer); + } + + [Theory] + [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + public void Resize_ThrowsForWrappedMemoryImage(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image0 = provider.GetImage()) + { + var mmg = TestMemoryManager.CreateAsCopyOf(image0.GetPixelSpan()); + + using (var image1 = Image.WrapMemory(mmg.Memory, image0.Width, image0.Height)) + { + Assert.ThrowsAny( + () => { image1.Mutate(x => x.Resize(image0.Width / 2, image0.Height / 2, true)); }); + } } } + [Theory] + [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, 1)] + [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, 4)] + [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, 8)] + [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, -1)] + public void Resize_WorksWithAllParallelismLevels( + TestImageProvider provider, + int maxDegreeOfParallelism) + where TPixel : struct, IPixel + { + provider.Configuration.MaxDegreeOfParallelism = + maxDegreeOfParallelism > 0 ? maxDegreeOfParallelism : Environment.ProcessorCount; + + FormattableString details = $"MDP{maxDegreeOfParallelism}"; + + provider.RunValidatingProcessorTest( + x => x.Resize(x.GetCurrentSize() / 2), + details, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + [Theory] [WithFileCollection(nameof(CommonTestImages), nameof(AllResamplerNames), DefaultPixelType, 0.5f, null, null)] - [WithFileCollection(nameof(CommonTestImages), nameof(SmokeTestResamplerNames), DefaultPixelType, 0.3f, null, null)] - [WithFileCollection(nameof(CommonTestImages), nameof(SmokeTestResamplerNames), DefaultPixelType, 1.8f, null, null)] + [WithFileCollection( + nameof(CommonTestImages), + nameof(SmokeTestResamplerNames), + DefaultPixelType, + 0.3f, + null, + null)] + [WithFileCollection( + nameof(CommonTestImages), + nameof(SmokeTestResamplerNames), + DefaultPixelType, + 1.8f, + null, + null)] [WithTestPatternImages(nameof(SmokeTestResamplerNames), 100, 100, DefaultPixelType, 0.5f, null, null)] [WithTestPatternImages(nameof(SmokeTestResamplerNames), 100, 100, DefaultPixelType, 1f, null, null)] [WithTestPatternImages(nameof(SmokeTestResamplerNames), 50, 50, DefaultPixelType, 8f, null, null)] @@ -84,15 +241,14 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms // Resize_WorksWithAllResamplers_TestPattern301x1180_NearestNeighbor-300x480.png // TODO: Should we investigate this? bool allowHigherInaccuracy = !TestEnvironment.Is64BitProcess - && string.IsNullOrEmpty(TestEnvironment.NetCoreVersion) - && sampler is NearestNeighborResampler; + && string.IsNullOrEmpty(TestEnvironment.NetCoreVersion) + && sampler is NearestNeighborResampler; var comparer = ImageComparer.TolerantPercentage(allowHigherInaccuracy ? 0.3f : 0.017f); provider.RunValidatingProcessorTest( ctx => { - SizeF newSize; string destSizeInfo; if (ratio.HasValue) @@ -126,107 +282,41 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, 1)] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, 4)] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, 8)] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, -1)] - public void Resize_WorksWithAllParallelismLevels(TestImageProvider provider, int maxDegreeOfParallelism) - where TPixel : struct, IPixel - { - provider.Configuration.MaxDegreeOfParallelism = - maxDegreeOfParallelism > 0 ? maxDegreeOfParallelism : Environment.ProcessorCount; - - FormattableString details = $"MDP{maxDegreeOfParallelism}"; - - provider.RunValidatingProcessorTest( - x => x.Resize(x.GetCurrentSize() / 2), - details, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - - [Theory] - [WithTestPatternImages(100, 100, DefaultPixelType)] - public void Resize_Compand(TestImageProvider provider) + [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + public void ResizeFromSourceRectangle(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { - image.Mutate(x => x.Resize(image.Size() / 2, true)); + var sourceRectangle = new Rectangle( + image.Width / 8, + image.Height / 8, + image.Width / 4, + image.Height / 4); + var destRectangle = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); + + image.Mutate( + x => x.Resize( + image.Width, + image.Height, + KnownResamplers.Bicubic, + sourceRectangle, + destRectangle, + false)); image.DebugSave(provider); image.CompareToReferenceOutput(ValidatorComparer, provider); } } - [Theory] - [WithTestPatternImages(50, 50, CommonNonDefaultPixelTypes)] - public void Resize_IsNotBoundToSinglePixelType(TestImageProvider provider) - where TPixel : struct, IPixel - { - provider.RunValidatingProcessorTest(x => x.Resize(x.GetCurrentSize() / 2), comparer: ValidatorComparer); - } - - [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] - public void Resize_ThrowsForWrappedMemoryImage(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image0 = provider.GetImage()) - { - var mmg = TestMemoryManager.CreateAsCopyOf(image0.GetPixelSpan()); - - using (var image1 = Image.WrapMemory(mmg.Memory, image0.Width, image0.Height)) - { - Assert.ThrowsAny( - () => - { - image1.Mutate(x => x.Resize(image0.Width / 2, image0.Height / 2, true)); - }); - } - } - } - - [Theory] - [WithFile(TestImages.Png.Kaboom, DefaultPixelType, false)] - [WithFile(TestImages.Png.Kaboom, DefaultPixelType, true)] - public void Resize_DoesNotBleedAlphaPixels(TestImageProvider provider, bool compand) - where TPixel : struct, IPixel - { - string details = compand ? "Compand" : ""; - - provider.RunValidatingProcessorTest( - x => x.Resize(x.GetCurrentSize() / 2, compand), - details, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - - [Theory] - [WithFile(TestImages.Gif.Giphy, DefaultPixelType)] - public void Resize_IsAppliedToAllFrames(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Resize(image.Width / 2, image.Height / 2, KnownResamplers.Bicubic)); - - // Comparer fights decoder with gif-s. Could not use CompareToReferenceOutput here :( - image.DebugSave(provider, extension: "gif"); - } - } - [Theory] [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] - public void ResizeFromSourceRectangle(TestImageProvider provider) + public void ResizeHeightAndKeepAspect(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { - var sourceRectangle = new Rectangle(image.Width / 8, image.Height / 8, image.Width / 4, image.Height / 4); - var destRectangle = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.Resize(image.Width, image.Height, KnownResamplers.Bicubic, sourceRectangle, destRectangle, false)); + image.Mutate(x => x.Resize(0, image.Height / 3, false)); image.DebugSave(provider); image.CompareToReferenceOutput(ValidatorComparer, provider); @@ -234,27 +324,26 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] - public void ResizeWidthAndKeepAspect(TestImageProvider provider) + [WithTestPatternImages(10, 100, DefaultPixelType)] + public void ResizeHeightCannotKeepAspectKeepsOnePixel(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { - image.Mutate(x => x.Resize(image.Width / 3, 0, false)); - - image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.Mutate(x => x.Resize(0, 5)); + Assert.Equal(1, image.Width); + Assert.Equal(5, image.Height); } } [Theory] [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] - public void ResizeHeightAndKeepAspect(TestImageProvider provider) + public void ResizeWidthAndKeepAspect(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { - image.Mutate(x => x.Resize(0, image.Height / 3, false)); + image.Mutate(x => x.Resize(image.Width / 3, 0, false)); image.DebugSave(provider); image.CompareToReferenceOutput(ValidatorComparer, provider); @@ -274,30 +363,17 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms } } - [Theory] - [WithTestPatternImages(10, 100, DefaultPixelType)] - public void ResizeHeightCannotKeepAspectKeepsOnePixel(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Resize(0, 5)); - Assert.Equal(1, image.Width); - Assert.Equal(5, image.Height); - } - } - [Theory] [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] - public void ResizeWithCropWidthMode(TestImageProvider provider) + public void ResizeWithBoxPadMode(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { var options = new ResizeOptions - { - Size = new Size(image.Width / 2, image.Height) - }; + { + Size = new Size(image.Width + 200, image.Height + 200), Mode = ResizeMode.BoxPad + }; image.Mutate(x => x.Resize(options)); @@ -313,10 +389,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { using (Image image = provider.GetImage()) { - var options = new ResizeOptions - { - Size = new Size(image.Width, image.Height / 2) - }; + var options = new ResizeOptions { Size = new Size(image.Width, image.Height / 2) }; image.Mutate(x => x.Resize(options)); @@ -327,16 +400,12 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms [Theory] [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] - public void ResizeWithPadMode(TestImageProvider provider) + public void ResizeWithCropWidthMode(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { - var options = new ResizeOptions - { - Size = new Size(image.Width + 200, image.Height), - Mode = ResizeMode.Pad - }; + var options = new ResizeOptions { Size = new Size(image.Width / 2, image.Height) }; image.Mutate(x => x.Resize(options)); @@ -347,16 +416,12 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms [Theory] [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] - public void ResizeWithBoxPadMode(TestImageProvider provider) + public void ResizeWithMaxMode(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { - var options = new ResizeOptions - { - Size = new Size(image.Width + 200, image.Height + 200), - Mode = ResizeMode.BoxPad - }; + var options = new ResizeOptions { Size = new Size(300, 300), Mode = ResizeMode.Max }; image.Mutate(x => x.Resize(options)); @@ -367,16 +432,18 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms [Theory] [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] - public void ResizeWithMaxMode(TestImageProvider provider) + public void ResizeWithMinMode(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { var options = new ResizeOptions - { - Size = new Size(300, 300), - Mode = ResizeMode.Max - }; + { + Size = new Size( + (int)Math.Round(image.Width * .75F), + (int)Math.Round(image.Height * .95F)), + Mode = ResizeMode.Min + }; image.Mutate(x => x.Resize(options)); @@ -387,16 +454,15 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms [Theory] [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] - public void ResizeWithMinMode(TestImageProvider provider) + public void ResizeWithPadMode(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { var options = new ResizeOptions - { - Size = new Size((int)Math.Round(image.Width * .75F), (int)Math.Round(image.Height * .95F)), - Mode = ResizeMode.Min - }; + { + Size = new Size(image.Width + 200, image.Height), Mode = ResizeMode.Pad + }; image.Mutate(x => x.Resize(options)); @@ -413,10 +479,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms using (Image image = provider.GetImage()) { var options = new ResizeOptions - { - Size = new Size(image.Width / 2, image.Height), - Mode = ResizeMode.Stretch - }; + { + Size = new Size(image.Width / 2, image.Height), Mode = ResizeMode.Stretch + }; image.Mutate(x => x.Resize(options)); @@ -424,61 +489,5 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms image.CompareToReferenceOutput(ValidatorComparer, provider); } } - - [Theory] - [InlineData(-2, 0)] - [InlineData(-1, 0)] - [InlineData(0, 1)] - [InlineData(1, 0)] - [InlineData(2, 0)] - public static void BicubicWindowOscillatesCorrectly(float x, float expected) - { - IResampler sampler = KnownResamplers.Bicubic; - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - - [Theory] - [InlineData(-2, 0)] - [InlineData(-1, 0)] - [InlineData(0, 1)] - [InlineData(1, 0)] - [InlineData(2, 0)] - public static void TriangleWindowOscillatesCorrectly(float x, float expected) - { - IResampler sampler = KnownResamplers.Triangle; - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - - [Theory] - [InlineData(-2, 0)] - [InlineData(-1, 0)] - [InlineData(0, 1)] - [InlineData(1, 0)] - [InlineData(2, 0)] - public static void Lanczos3WindowOscillatesCorrectly(float x, float expected) - { - IResampler sampler = KnownResamplers.Lanczos3; - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - - [Theory] - [InlineData(-4, 0)] - [InlineData(-2, 0)] - [InlineData(0, 1)] - [InlineData(2, 0)] - [InlineData(4, 0)] - public static void Lanczos5WindowOscillatesCorrectly(float x, float expected) - { - IResampler sampler = KnownResamplers.Lanczos5; - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } } } \ No newline at end of file From 20ddd11e5fe5c6ef09a26e675fc595af42d1fdb7 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 14 Apr 2019 22:13:51 +0200 Subject: [PATCH 061/223] ResizeWindow refactor 4 --- .../Transforms/Resize/ResizeKernel.cs | 29 +++++++++------- .../Transforms/Resize/ResizeProcessor.cs | 17 +++++----- .../Transforms/Resize/ResizeWindow.cs | 33 +++++++++++-------- ...ResizeKernelMapTests.ReferenceKernelMap.cs | 2 +- .../Transforms/ResizeKernelMapTests.cs | 4 +-- 5 files changed, 48 insertions(+), 37 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs index f349634ac..28b3d3a4d 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs @@ -19,27 +19,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// Initializes a new instance of the struct. /// [MethodImpl(InliningOptions.ShortMethod)] - internal ResizeKernel(int left, float* bufferPtr, int length) + internal ResizeKernel(int startIndex, float* bufferPtr, int length) { - this.Left = left; + this.StartIndex = startIndex; this.bufferPtr = bufferPtr; this.Length = length; } /// - /// Gets the left index for the destination row + /// Gets the start index for the destination row. /// - public int Left { get; } + public int StartIndex { get; } /// - /// Gets the the length of the kernel + /// Gets the the length of the kernel. /// public int Length { get; } /// - /// Gets the span representing the portion of the that this window covers + /// Gets the span representing the portion of the that this window covers. /// - /// The + /// The . /// public Span Values { @@ -55,17 +55,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public Vector4 Convolve(Span rowSpan) { - ref float horizontalValues = ref Unsafe.AsRef(this.bufferPtr); - int left = this.Left; - ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), left); + ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), this.StartIndex); + + return this.ConvolveCore(ref vecPtr); + } + [MethodImpl(InliningOptions.ShortMethod)] + public Vector4 ConvolveCore(ref Vector4 rowStartRef) + { + ref float horizontalValues = ref Unsafe.AsRef(this.bufferPtr); // Destination color components Vector4 result = Vector4.Zero; for (int i = 0; i < this.Length; i++) { float weight = Unsafe.Add(ref horizontalValues, i); - Vector4 v = Unsafe.Add(ref vecPtr, i); + Vector4 v = Unsafe.Add(ref rowStartRef, i); result += v * weight; } @@ -73,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } /// - /// Copy the contents of altering + /// Copy the contents of altering /// to the value . /// internal ResizeKernel AlterLeftValue(int left) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 38419b5dd..73f9b4241 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int startY = this.TargetRectangle.Y; int startX = this.TargetRectangle.X; - var workingRect = Rectangle.Intersect( + var destWorkingRect = Rectangle.Intersect( this.TargetRectangle, new Rectangle(0, 0, width, height)); @@ -208,7 +208,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms float heightFactor = sourceRectangle.Height / (float)this.TargetRectangle.Height; ParallelHelper.IterateRows( - workingRect, + destWorkingRect, configuration, rows => { @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); Span targetRow = destination.GetPixelRowSpan(y); - for (int x = workingRect.Left; x < workingRect.Right; x++) + for (int x = destWorkingRect.Left; x < destWorkingRect.Right; x++) { // X coordinates of source points targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; @@ -248,7 +248,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.horizontalKernelMap, this.verticalKernelMap, width, - workingRect, + destWorkingRect, startX)) using (IMemoryOwner tempBuffer = source.MemoryAllocator.Allocate(width)) { @@ -257,12 +257,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Now process the rows. Span tempColSpan = tempBuffer.GetSpan(); - for (int y = workingRect.Top; y < workingRect.Bottom; y++) + for (int y = destWorkingRect.Top; y < destWorkingRect.Bottom; y++) { // Ensure offsets are normalized for cropping and padding. ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); - if (kernel.Left + kernel.Length > resizeWindow.Bottom) + if (kernel.StartIndex + kernel.Length > resizeWindow.Bottom) { resizeWindow.Slide(); } @@ -271,10 +271,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = 0; x < width; x++) { - Span firstPassColumn = resizeWindow.GetColumnSpan(x); + Span firstPassColumn = resizeWindow.GetColumnSpan(x, kernel.StartIndex); + ref Vector4 rowStartReference = ref MemoryMarshal.GetReference(firstPassColumn); // Destination color components - Unsafe.Add(ref tempRowBase, x) = kernel.Convolve(firstPassColumn); + Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(ref rowStartReference); } Span targetRowSpan = destination.GetPixelRowSpan(y); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs index 05015dee2..ba5f9a984 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly ResizeKernelMap verticalKernelMap; - private readonly Rectangle workingRectangle; + private readonly Rectangle destWorkingRect; private readonly int diameter; @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms ResizeKernelMap horizontalKernelMap, ResizeKernelMap verticalKernelMap, int destWidth, - Rectangle workingRectangle, + Rectangle destWorkingRect, int startX) { this.configuration = configuration; @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.conversionModifiers = conversionModifiers; this.horizontalKernelMap = horizontalKernelMap; this.verticalKernelMap = verticalKernelMap; - this.workingRectangle = workingRectangle; + this.destWorkingRect = destWorkingRect; this.startX = startX; this.diameter = verticalKernelMap.MaxDiameter; @@ -65,9 +65,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms AllocationOptions.Clean); this.tempRowBuffer = configuration.MemoryAllocator.Allocate(this.sourceRectangle.Width); - this.Top = this.sourceRectangle.Top; + this.Top = 0; - this.Bottom = this.sourceRectangle.Bottom; + this.Bottom = this.sourceRectangle.Height; } public int Bottom { get; private set; } @@ -80,15 +80,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span GetColumnSpan(int x) + public Span GetColumnSpan(int x, int startY) { - return this.buffer.GetRowSpan(x); + return this.buffer.GetRowSpan(x).Slice(startY); } public void Initialize() + { + this.Initialize(0, this.sourceRectangle.Height); + } + + public void Slide() + { + throw new InvalidOperationException("Shouldn't happen yet!"); + } + + private void Initialize(int top, int bottom) { Span tempRowSpan = this.tempRowBuffer.GetSpan(); - for (int y = 0; y < this.sourceRectangle.Height; y++) + for (int y = top; y < bottom; y++) { Span sourceRow = this.source.GetRowSpan(y); @@ -100,17 +110,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms ref Vector4 firstPassBaseRef = ref this.buffer.Span[y]; - for (int x = this.workingRectangle.Left; x < this.workingRectangle.Right; x++) + for (int x = this.destWorkingRect.Left; x < this.destWorkingRect.Right; x++) { ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); } } } - - public void Slide() - { - throw new InvalidOperationException("Shouldn't happen yet!"); - } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs index 7d842c4e1..2c5914253 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs @@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms public static implicit operator ReferenceKernel(ResizeKernel orig) { - return new ReferenceKernel(orig.Left, orig.Values.ToArray()); + return new ReferenceKernel(orig.StartIndex, orig.Values.ToArray()); } } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs index 9de866586..1bd909e7e 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs @@ -151,8 +151,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms referenceKernel.Length == kernel.Length, $"referenceKernel.Length != kernel.Length: {referenceKernel.Length} != {kernel.Length}"); Assert.True( - referenceKernel.Left == kernel.Left, - $"referenceKernel.Left != kernel.Left: {referenceKernel.Left} != {kernel.Left}"); + referenceKernel.Left == kernel.StartIndex, + $"referenceKernel.Left != kernel.Left: {referenceKernel.Left} != {kernel.StartIndex}"); float[] expectedValues = referenceKernel.Values; Span actualValues = kernel.Values; From 86cc83d7eaaccfde7d53002828a4856af4e368a4 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 14 Apr 2019 23:29:43 +0200 Subject: [PATCH 062/223] basic sliding window implementation (semi-stable state) --- .../Transforms/Resize/ResizeKernel.cs | 9 +++---- .../Transforms/Resize/ResizeProcessor.cs | 3 +-- .../Transforms/Resize/ResizeWindow.cs | 27 ++++++++++++------- .../Processors/Transforms/ResizeTests.cs | 1 + 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs index 28b3d3a4d..4606f482c 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs @@ -55,13 +55,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public Vector4 Convolve(Span rowSpan) { - ref Vector4 vecPtr = ref Unsafe.Add(ref MemoryMarshal.GetReference(rowSpan), this.StartIndex); - - return this.ConvolveCore(ref vecPtr); + return this.ConvolveCore(rowSpan.Slice(this.StartIndex)); } [MethodImpl(InliningOptions.ShortMethod)] - public Vector4 ConvolveCore(ref Vector4 rowStartRef) + public Vector4 ConvolveCore(Span offsetedRowSpan) { ref float horizontalValues = ref Unsafe.AsRef(this.bufferPtr); // Destination color components @@ -70,7 +68,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int i = 0; i < this.Length; i++) { float weight = Unsafe.Add(ref horizontalValues, i); - Vector4 v = Unsafe.Add(ref rowStartRef, i); + //Vector4 v = Unsafe.Add(ref rowStartRef, i); + Vector4 v = offsetedRowSpan[i]; result += v * weight; } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 73f9b4241..abbe5908e 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -272,10 +272,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = 0; x < width; x++) { Span firstPassColumn = resizeWindow.GetColumnSpan(x, kernel.StartIndex); - ref Vector4 rowStartReference = ref MemoryMarshal.GetReference(firstPassColumn); // Destination color components - Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(ref rowStartReference); + Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(firstPassColumn); } Span targetRowSpan = destination.GetPixelRowSpan(y); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs index ba5f9a984..8221a9cc4 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs @@ -38,6 +38,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly int diameter; + private readonly int windowHeight; + public ResizeWindow( Configuration configuration, BufferArea source, @@ -59,15 +61,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.diameter = verticalKernelMap.MaxDiameter; + this.windowHeight = Math.Min(this.sourceRectangle.Height, 2 * this.diameter); + this.buffer = configuration.MemoryAllocator.Allocate2D( - this.sourceRectangle.Height, + this.windowHeight, destWidth, AllocationOptions.Clean); this.tempRowBuffer = configuration.MemoryAllocator.Allocate(this.sourceRectangle.Width); - - this.Top = 0; - - this.Bottom = this.sourceRectangle.Height; } public int Bottom { get; private set; } @@ -82,21 +82,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span GetColumnSpan(int x, int startY) { - return this.buffer.GetRowSpan(x).Slice(startY); + return this.buffer.GetRowSpan(x).Slice(startY - this.Top); } public void Initialize() { - this.Initialize(0, this.sourceRectangle.Height); + this.Initialize(0, this.windowHeight); } public void Slide() { - throw new InvalidOperationException("Shouldn't happen yet!"); + int top = this.Top + this.diameter; + int bottom = Math.Min(this.Bottom + this.diameter, this.sourceRectangle.Height); + this.Initialize(top, bottom); } private void Initialize(int top, int bottom) { + this.Top = top; + this.Bottom = bottom; + Span tempRowSpan = this.tempRowBuffer.GetSpan(); for (int y = top; y < bottom; y++) { @@ -108,12 +113,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms tempRowSpan, this.conversionModifiers); - ref Vector4 firstPassBaseRef = ref this.buffer.Span[y]; + //ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top]; + Span firstPassSpan = this.buffer.Span.Slice(y - top); for (int x = this.destWorkingRect.Left; x < this.destWorkingRect.Right; x++) { ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); - Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); + firstPassSpan[x * this.windowHeight] = kernel.Convolve(tempRowSpan); + //Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); } } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 8c59fff26..3d6f08a15 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -102,6 +102,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms // [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32, 2, 3, 1, 2)] means: // resizing: (15, 12) -> (10, 6) // kernel dimensions: (3, 4) + using (Image image = provider.GetImage()) { From 56de415c949d6573170cb611cbaee6fc50e42e75 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 14 Apr 2019 23:51:08 +0200 Subject: [PATCH 063/223] fix ResizeWithCropHeightMode --- .../Processing/Processors/Transforms/Resize/ResizeProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index abbe5908e..9508d7c00 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -262,7 +262,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Ensure offsets are normalized for cropping and padding. ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); - if (kernel.StartIndex + kernel.Length > resizeWindow.Bottom) + while (kernel.StartIndex + kernel.Length > resizeWindow.Bottom) { resizeWindow.Slide(); } From 8e607aeaf16a8c7f165a3ad5560715e1e3f8b79e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 15 Apr 2019 01:24:22 +0200 Subject: [PATCH 064/223] reference output for Resize_BasicSmall --- tests/Images/External | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Images/External b/tests/Images/External index 94b5a8e11..c7333d2a8 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 94b5a8e11b33ba62c15d1d03f1b8b721468764f1 +Subproject commit c7333d2a81a74d1936bd202bcb6b16cbfe6bcdce From 682e5214590424d0e94c33874de1ac7f7e1888dd Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 15 Apr 2019 01:46:21 +0200 Subject: [PATCH 065/223] minor optimization --- .../Processors/Transforms/Resize/ResizeProcessor.cs | 4 +++- .../Processing/Processors/Transforms/Resize/ResizeWindow.cs | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 9508d7c00..d61cc5e89 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -269,9 +269,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempColSpan); + int top = kernel.StartIndex - resizeWindow.Top; + for (int x = 0; x < width; x++) { - Span firstPassColumn = resizeWindow.GetColumnSpan(x, kernel.StartIndex); + Span firstPassColumn = resizeWindow.GetColumnSpan(x).Slice(top); // Destination color components Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(firstPassColumn); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs index 8221a9cc4..afa9dac2d 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs @@ -85,6 +85,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms return this.buffer.GetRowSpan(x).Slice(startY - this.Top); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Span GetColumnSpan(int x) + { + return this.buffer.GetRowSpan(x); + } + public void Initialize() { this.Initialize(0, this.windowHeight); From 5a85ea72b55255c80ffbec94ea703937759aaf2f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 15 Apr 2019 18:02:39 +1000 Subject: [PATCH 066/223] Handle incorrect colorspace metadata. Fix #882 (#885) --- src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs | 13 ++++++------- .../Formats/Jpg/JpegDecoderTests.Images.cs | 5 ++++- tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/External | 2 +- .../issues/issue855-incorrect-colorspace.jpg | Bin 0 -> 142656 bytes 5 files changed, 12 insertions(+), 9 deletions(-) create mode 100644 tests/Images/Input/Jpg/issues/issue855-incorrect-colorspace.jpg diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 9852b36e4..6d6983f19 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -401,15 +401,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg if (this.ComponentCount == 3) { - if (this.adobe.Equals(default) || this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformYCbCr) - { - return JpegColorSpace.YCbCr; - } - - if (this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformUnknown) + if (!this.adobe.Equals(default) && this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformUnknown) { return JpegColorSpace.RGB; } + + // Some images are poorly encoded and contain incorrect colorspace transform metadata. + // We ignore that and always fall back to the default colorspace. + return JpegColorSpace.YCbCr; } if (this.ComponentCount == 4) @@ -419,7 +418,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg : JpegColorSpace.Cmyk; } - JpegThrowHelper.ThrowImageFormatException($"Unsupported color mode. Max components 4; found {this.ComponentCount}"); + JpegThrowHelper.ThrowImageFormatException($"Unsupported color mode. Supported component counts 1, 3, and 4; found {this.ComponentCount}"); return default; } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index 8a9482607..442fcb3d1 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -31,9 +31,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Issues.ExifGetString750Load, TestImages.Jpeg.Issues.ExifGetString750Transform, - // LibJpeg can open this despite the invalid desity units. + // LibJpeg can open this despite the invalid density units. TestImages.Jpeg.Issues.Fuzz.ArgumentOutOfRangeException825B, + // LibJpeg can open this despite incorrect colorspace metadata. + TestImages.Jpeg.Issues.IncorrectColorspace855, + // High depth images TestImages.Jpeg.Baseline.Testorig12bit, }; diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 1efb9e35f..8b2fd2e7f 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -175,6 +175,7 @@ namespace SixLabors.ImageSharp.Tests public const string ExifGetString750Transform = "Jpg/issues/issue750-exif-tranform.jpg"; public const string ExifGetString750Load = "Jpg/issues/issue750-exif-load.jpg"; public const string IncorrectQuality845 = "Jpg/issues/Issue845-Incorrect-Quality99.jpg"; + public const string IncorrectColorspace855 = "Jpg/issues/issue855-incorrect-colorspace.jpg"; public static class Fuzz { diff --git a/tests/Images/External b/tests/Images/External index 94b5a8e11..802725dec 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 94b5a8e11b33ba62c15d1d03f1b8b721468764f1 +Subproject commit 802725dec2a6b1ca02f9e2f9a4c3f625583d0696 diff --git a/tests/Images/Input/Jpg/issues/issue855-incorrect-colorspace.jpg b/tests/Images/Input/Jpg/issues/issue855-incorrect-colorspace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..54db7982c563d319d12de9f31270efd43f7a9244 GIT binary patch literal 142656 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

vM$WA_rF7sredq`ggY; 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 CPOC8h literal 0 HcmV?d00001 From 4a0839abd0ead5ea0a298e0d4a5b531787f91409 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 18 Apr 2019 23:43:44 +0200 Subject: [PATCH 067/223] refactor - ResizeWindow -> ResizeWorker - Most logic moved to ResizeWorker --- .../Transforms/Resize/ResizeProcessor.cs | 42 ++--------- .../{ResizeWindow.cs => ResizeWorker.cs} | 72 +++++++++++++++---- 2 files changed, 62 insertions(+), 52 deletions(-) rename src/ImageSharp/Processing/Processors/Transforms/Resize/{ResizeWindow.cs => ResizeWorker.cs} (61%) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index d61cc5e89..63dd5efca 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -237,11 +237,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms BufferArea sourceArea = source.PixelBuffer.GetArea(sourceRectangle); - // Interpolate the image using the calculated weights. - // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm - // First process the columns. Since we are not using multiple threads startY and endY - // are the upper and lower bounds of the source rectangle. - using (var resizeWindow = new ResizeWindow( + // If we want to reintroduce processing: + // it's possible to launch multiple workers for different regions of the image + using (var worker = new ResizeWorker( configuration, sourceArea, conversionModifiers, @@ -250,39 +248,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms width, destWorkingRect, startX)) - using (IMemoryOwner tempBuffer = source.MemoryAllocator.Allocate(width)) { - resizeWindow.Initialize(); - - // Now process the rows. - Span tempColSpan = tempBuffer.GetSpan(); - - for (int y = destWorkingRect.Top; y < destWorkingRect.Bottom; y++) - { - // Ensure offsets are normalized for cropping and padding. - ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); - - while (kernel.StartIndex + kernel.Length > resizeWindow.Bottom) - { - resizeWindow.Slide(); - } - - ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempColSpan); - - int top = kernel.StartIndex - resizeWindow.Top; - - for (int x = 0; x < width; x++) - { - Span firstPassColumn = resizeWindow.GetColumnSpan(x).Slice(top); - - // Destination color components - Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(firstPassColumn); - } - - Span targetRowSpan = destination.GetPixelRowSpan(y); - - PixelOperations.Instance.FromVector4Destructive(configuration, tempColSpan, targetRowSpan, conversionModifiers); - } + worker.Initialize(); + worker.FillDestinationPixels(destWorkingRect.Top, destWorkingRect.Bottom, startY, destination.PixelBuffer); } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs similarity index 61% rename from src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs rename to src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index afa9dac2d..11b49b863 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWindow.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -5,6 +5,7 @@ using System; using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -13,7 +14,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { - internal class ResizeWindow : IDisposable + internal class ResizeWorker : IDisposable where TPixel : struct, IPixel { private readonly Buffer2D buffer; @@ -32,15 +33,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly IMemoryOwner tempRowBuffer; + private readonly IMemoryOwner tempColumnBuffer; + private readonly ResizeKernelMap verticalKernelMap; + private readonly int destWidth; + private readonly Rectangle destWorkingRect; private readonly int diameter; private readonly int windowHeight; - public ResizeWindow( + public ResizeWorker( Configuration configuration, BufferArea source, PixelConversionModifiers conversionModifiers, @@ -56,6 +61,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.conversionModifiers = conversionModifiers; this.horizontalKernelMap = horizontalKernelMap; this.verticalKernelMap = verticalKernelMap; + this.destWidth = destWidth; this.destWorkingRect = destWorkingRect; this.startX = startX; @@ -67,22 +73,29 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.windowHeight, destWidth, AllocationOptions.Clean); + this.tempRowBuffer = configuration.MemoryAllocator.Allocate(this.sourceRectangle.Width); + this.tempColumnBuffer = configuration.MemoryAllocator.Allocate(destWidth); + + this.CurrentMinY = 0; + this.CurrentMaxY = this.windowHeight; } - public int Bottom { get; private set; } + public int CurrentMaxY { get; private set; } - public int Top { get; private set; } + public int CurrentMinY { get; private set; } public void Dispose() { this.buffer.Dispose(); + this.tempRowBuffer.Dispose(); + this.tempColumnBuffer.Dispose(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span GetColumnSpan(int x, int startY) { - return this.buffer.GetRowSpan(x).Slice(startY - this.Top); + return this.buffer.GetRowSpan(x).Slice(startY - this.CurrentMinY); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -93,23 +106,52 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public void Initialize() { - this.Initialize(0, this.windowHeight); + this.CalculateFirstPassValues(0, this.windowHeight); } - public void Slide() + public void FillDestinationPixels(int minY, int maxY, int startY, Buffer2D destination) { - int top = this.Top + this.diameter; - int bottom = Math.Min(this.Bottom + this.diameter, this.sourceRectangle.Height); - this.Initialize(top, bottom); + Span tempColSpan = this.tempColumnBuffer.GetSpan(); + + for (int y = minY; y < maxY; y++) + { + // Ensure offsets are normalized for cropping and padding. + ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); + + while (kernel.StartIndex + kernel.Length > this.CurrentMaxY) + { + this.Slide(); + } + + ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempColSpan); + + int top = kernel.StartIndex - this.CurrentMinY; + + for (int x = 0; x < this.destWidth; x++) + { + Span firstPassColumn = this.GetColumnSpan(x).Slice(top); + + // Destination color components + Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(firstPassColumn); + } + + Span targetRowSpan = destination.GetRowSpan(y); + + PixelOperations.Instance.FromVector4Destructive(configuration, tempColSpan, targetRowSpan, conversionModifiers); + } } - private void Initialize(int top, int bottom) + public void Slide() { - this.Top = top; - this.Bottom = bottom; + this.CurrentMinY = this.CurrentMinY + this.diameter; + this.CurrentMaxY = Math.Min(this.CurrentMaxY + this.diameter, this.sourceRectangle.Height); + this.CalculateFirstPassValues(this.CurrentMinY, this.CurrentMaxY); + } + private void CalculateFirstPassValues(int minY, int maxY) + { Span tempRowSpan = this.tempRowBuffer.GetSpan(); - for (int y = top; y < bottom; y++) + for (int y = minY; y < maxY; y++) { Span sourceRow = this.source.GetRowSpan(y); @@ -120,7 +162,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.conversionModifiers); //ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top]; - Span firstPassSpan = this.buffer.Span.Slice(y - top); + Span firstPassSpan = this.buffer.Span.Slice(y - minY); for (int x = this.destWorkingRect.Left; x < this.destWorkingRect.Right; x++) { From b3495e8f715017af5d22d24fec845b5961c96947 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 00:23:06 +0200 Subject: [PATCH 068/223] refactor stuff + implement CalculateResizeWorkerWindowCount() --- src/ImageSharp/Configuration.cs | 13 +- .../Transforms/Resize}/ResizeHelper.cs | 339 ++++++++++-------- tests/ImageSharp.Tests/ConfigurationTests.cs | 17 +- .../Processors/Transforms/ResizeTests.cs | 19 + 4 files changed, 232 insertions(+), 156 deletions(-) rename src/ImageSharp/Processing/{ => Processors/Transforms/Resize}/ResizeHelper.cs (88%) diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index c0064d187..b1767101d 100644 --- a/src/ImageSharp/Configuration.cs +++ b/src/ImageSharp/Configuration.cs @@ -10,6 +10,7 @@ using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.Memory; namespace SixLabors.ImageSharp @@ -102,6 +103,15 @@ namespace SixLabors.ImageSharp ///

internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); + /// + /// Gets or sets the working buffer size hint for image processors. + /// The default value is 1MB. + /// + /// + /// Currently only used by . + /// + internal int WorkingBufferSizeHintInBytes { get; set; } = 1 * 1024 * 1024; + /// /// Gets or sets the image operations provider factory. /// @@ -130,7 +140,8 @@ namespace SixLabors.ImageSharp MemoryAllocator = this.MemoryAllocator, ImageOperationsProvider = this.ImageOperationsProvider, ReadOrigin = this.ReadOrigin, - FileSystem = this.FileSystem + FileSystem = this.FileSystem, + WorkingBufferSizeHintInBytes = this.WorkingBufferSizeHintInBytes, }; } diff --git a/src/ImageSharp/Processing/ResizeHelper.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs similarity index 88% rename from src/ImageSharp/Processing/ResizeHelper.cs rename to src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs index 3ae632162..0bc8cfda0 100644 --- a/src/ImageSharp/Processing/ResizeHelper.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs @@ -1,11 +1,13 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using System.Linq; +using System.Numerics; + using SixLabors.Primitives; -namespace SixLabors.ImageSharp.Processing +namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// /// Provides methods to help calculate the target rectangle when resizing using the @@ -13,6 +15,16 @@ namespace SixLabors.ImageSharp.Processing /// internal static class ResizeHelper { + public static unsafe int CalculateResizeWorkerWindowCount( + int windowDiameter, + int width, + int sizeLimitHintInBytes) + { + int sizeLimitHint = sizeLimitHintInBytes / sizeof(Vector4); + int sizeOfOneWindow = windowDiameter * width; + return Math.Max(2, sizeLimitHint / sizeOfOneWindow); + } + /// /// Calculates the target location and bounds to perform the resize operation against. /// @@ -21,9 +33,13 @@ namespace SixLabors.ImageSharp.Processing /// The target width /// The target height /// - /// The . + /// The tuple representing the location and the bounds /// - public static (Size, Rectangle) CalculateTargetLocationAndBounds(Size sourceSize, ResizeOptions options, int width, int height) + public static (Size, Rectangle) CalculateTargetLocationAndBounds( + Size sourceSize, + ResizeOptions options, + int width, + int height) { switch (options.Mode) { @@ -44,7 +60,90 @@ namespace SixLabors.ImageSharp.Processing } } - private static (Size, Rectangle) CalculateCropRectangle(Size source, ResizeOptions options, int width, int height) + private static (Size, Rectangle) CalculateBoxPadRectangle( + Size source, + ResizeOptions options, + int width, + int height) + { + if (width <= 0 || height <= 0) + { + return (new Size(source.Width, source.Height), new Rectangle(0, 0, source.Width, source.Height)); + } + + int sourceWidth = source.Width; + int sourceHeight = source.Height; + + // Fractional variants for preserving aspect ratio. + float percentHeight = MathF.Abs(height / (float)sourceHeight); + float percentWidth = MathF.Abs(width / (float)sourceWidth); + + int boxPadHeight = height > 0 ? height : (int)MathF.Round(sourceHeight * percentWidth); + int boxPadWidth = width > 0 ? width : (int)MathF.Round(sourceWidth * percentHeight); + + // Only calculate if upscaling. + if (sourceWidth < boxPadWidth && sourceHeight < boxPadHeight) + { + int destinationX; + int destinationY; + int destinationWidth = sourceWidth; + int destinationHeight = sourceHeight; + width = boxPadWidth; + height = boxPadHeight; + + switch (options.Position) + { + case AnchorPositionMode.Left: + destinationY = (height - sourceHeight) / 2; + destinationX = 0; + break; + case AnchorPositionMode.Right: + destinationY = (height - sourceHeight) / 2; + destinationX = width - sourceWidth; + break; + case AnchorPositionMode.TopRight: + destinationY = 0; + destinationX = width - sourceWidth; + break; + case AnchorPositionMode.Top: + destinationY = 0; + destinationX = (width - sourceWidth) / 2; + break; + case AnchorPositionMode.TopLeft: + destinationY = 0; + destinationX = 0; + break; + case AnchorPositionMode.BottomRight: + destinationY = height - sourceHeight; + destinationX = width - sourceWidth; + break; + case AnchorPositionMode.Bottom: + destinationY = height - sourceHeight; + destinationX = (width - sourceWidth) / 2; + break; + case AnchorPositionMode.BottomLeft: + destinationY = height - sourceHeight; + destinationX = 0; + break; + default: + destinationY = (height - sourceHeight) / 2; + destinationX = (width - sourceWidth) / 2; + break; + } + + return (new Size(width, height), + new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight)); + } + + // Switch to pad mode to downscale and calculate from there. + return CalculatePadRectangle(source, options, width, height); + } + + private static (Size, Rectangle) CalculateCropRectangle( + Size source, + ResizeOptions options, + int width, + int height) { if (width <= 0 || height <= 0) { @@ -147,152 +246,15 @@ namespace SixLabors.ImageSharp.Processing destinationWidth = (int)MathF.Ceiling(sourceWidth * percentHeight); } - return (new Size(width, height), new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight)); - } - - private static (Size, Rectangle) CalculatePadRectangle(Size source, ResizeOptions options, int width, int height) - { - if (width <= 0 || height <= 0) - { - return (new Size(source.Width, source.Height), new Rectangle(0, 0, source.Width, source.Height)); - } - - float ratio; - int sourceWidth = source.Width; - int sourceHeight = source.Height; - - int destinationX = 0; - int destinationY = 0; - int destinationWidth = width; - int destinationHeight = height; - - // Fractional variants for preserving aspect ratio. - float percentHeight = MathF.Abs(height / (float)sourceHeight); - float percentWidth = MathF.Abs(width / (float)sourceWidth); - - if (percentHeight < percentWidth) - { - ratio = percentHeight; - destinationWidth = (int)MathF.Round(sourceWidth * percentHeight); - - switch (options.Position) - { - case AnchorPositionMode.Left: - case AnchorPositionMode.TopLeft: - case AnchorPositionMode.BottomLeft: - destinationX = 0; - break; - case AnchorPositionMode.Right: - case AnchorPositionMode.TopRight: - case AnchorPositionMode.BottomRight: - destinationX = (int)MathF.Round(width - (sourceWidth * ratio)); - break; - default: - destinationX = (int)MathF.Round((width - (sourceWidth * ratio)) / 2F); - break; - } - } - else - { - ratio = percentWidth; - destinationHeight = (int)MathF.Round(sourceHeight * percentWidth); - - switch (options.Position) - { - case AnchorPositionMode.Top: - case AnchorPositionMode.TopLeft: - case AnchorPositionMode.TopRight: - destinationY = 0; - break; - case AnchorPositionMode.Bottom: - case AnchorPositionMode.BottomLeft: - case AnchorPositionMode.BottomRight: - destinationY = (int)MathF.Round(height - (sourceHeight * ratio)); - break; - default: - destinationY = (int)MathF.Round((height - (sourceHeight * ratio)) / 2F); - break; - } - } - - return (new Size(width, height), new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight)); - } - - private static (Size, Rectangle) CalculateBoxPadRectangle(Size source, ResizeOptions options, int width, int height) - { - if (width <= 0 || height <= 0) - { - return (new Size(source.Width, source.Height), new Rectangle(0, 0, source.Width, source.Height)); - } - - int sourceWidth = source.Width; - int sourceHeight = source.Height; - - // Fractional variants for preserving aspect ratio. - float percentHeight = MathF.Abs(height / (float)sourceHeight); - float percentWidth = MathF.Abs(width / (float)sourceWidth); - - int boxPadHeight = height > 0 ? height : (int)MathF.Round(sourceHeight * percentWidth); - int boxPadWidth = width > 0 ? width : (int)MathF.Round(sourceWidth * percentHeight); - - // Only calculate if upscaling. - if (sourceWidth < boxPadWidth && sourceHeight < boxPadHeight) - { - int destinationX; - int destinationY; - int destinationWidth = sourceWidth; - int destinationHeight = sourceHeight; - width = boxPadWidth; - height = boxPadHeight; - - switch (options.Position) - { - case AnchorPositionMode.Left: - destinationY = (height - sourceHeight) / 2; - destinationX = 0; - break; - case AnchorPositionMode.Right: - destinationY = (height - sourceHeight) / 2; - destinationX = width - sourceWidth; - break; - case AnchorPositionMode.TopRight: - destinationY = 0; - destinationX = width - sourceWidth; - break; - case AnchorPositionMode.Top: - destinationY = 0; - destinationX = (width - sourceWidth) / 2; - break; - case AnchorPositionMode.TopLeft: - destinationY = 0; - destinationX = 0; - break; - case AnchorPositionMode.BottomRight: - destinationY = height - sourceHeight; - destinationX = width - sourceWidth; - break; - case AnchorPositionMode.Bottom: - destinationY = height - sourceHeight; - destinationX = (width - sourceWidth) / 2; - break; - case AnchorPositionMode.BottomLeft: - destinationY = height - sourceHeight; - destinationX = 0; - break; - default: - destinationY = (height - sourceHeight) / 2; - destinationX = (width - sourceWidth) / 2; - break; - } - - return (new Size(width, height), new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight)); - } - - // Switch to pad mode to downscale and calculate from there. - return CalculatePadRectangle(source, options, width, height); + return (new Size(width, height), + new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight)); } - private static (Size, Rectangle) CalculateMaxRectangle(Size source, ResizeOptions options, int width, int height) + private static (Size, Rectangle) CalculateMaxRectangle( + Size source, + ResizeOptions options, + int width, + int height) { int destinationWidth = width; int destinationHeight = height; @@ -320,7 +282,11 @@ namespace SixLabors.ImageSharp.Processing return (new Size(width, height), new Rectangle(0, 0, destinationWidth, destinationHeight)); } - private static (Size, Rectangle) CalculateMinRectangle(Size source, ResizeOptions options, int width, int height) + private static (Size, Rectangle) CalculateMinRectangle( + Size source, + ResizeOptions options, + int width, + int height) { int sourceWidth = source.Width; int sourceHeight = source.Height; @@ -372,5 +338,78 @@ namespace SixLabors.ImageSharp.Processing // Replace the size to match the rectangle. return (new Size(width, height), new Rectangle(0, 0, destinationWidth, destinationHeight)); } + + private static (Size, Rectangle) CalculatePadRectangle( + Size source, + ResizeOptions options, + int width, + int height) + { + if (width <= 0 || height <= 0) + { + return (new Size(source.Width, source.Height), new Rectangle(0, 0, source.Width, source.Height)); + } + + float ratio; + int sourceWidth = source.Width; + int sourceHeight = source.Height; + + int destinationX = 0; + int destinationY = 0; + int destinationWidth = width; + int destinationHeight = height; + + // Fractional variants for preserving aspect ratio. + float percentHeight = MathF.Abs(height / (float)sourceHeight); + float percentWidth = MathF.Abs(width / (float)sourceWidth); + + if (percentHeight < percentWidth) + { + ratio = percentHeight; + destinationWidth = (int)MathF.Round(sourceWidth * percentHeight); + + switch (options.Position) + { + case AnchorPositionMode.Left: + case AnchorPositionMode.TopLeft: + case AnchorPositionMode.BottomLeft: + destinationX = 0; + break; + case AnchorPositionMode.Right: + case AnchorPositionMode.TopRight: + case AnchorPositionMode.BottomRight: + destinationX = (int)MathF.Round(width - (sourceWidth * ratio)); + break; + default: + destinationX = (int)MathF.Round((width - (sourceWidth * ratio)) / 2F); + break; + } + } + else + { + ratio = percentWidth; + destinationHeight = (int)MathF.Round(sourceHeight * percentWidth); + + switch (options.Position) + { + case AnchorPositionMode.Top: + case AnchorPositionMode.TopLeft: + case AnchorPositionMode.TopRight: + destinationY = 0; + break; + case AnchorPositionMode.Bottom: + case AnchorPositionMode.BottomLeft: + case AnchorPositionMode.BottomRight: + destinationY = (int)MathF.Round(height - (sourceHeight * ratio)); + break; + default: + destinationY = (int)MathF.Round((height - (sourceHeight * ratio)) / 2F); + break; + } + } + + return (new Size(width, height), + new Rectangle(destinationX, destinationY, destinationWidth, destinationHeight)); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs index 208387e6d..6f68d0428 100644 --- a/tests/ImageSharp.Tests/ConfigurationTests.cs +++ b/tests/ImageSharp.Tests/ConfigurationTests.cs @@ -39,13 +39,13 @@ namespace SixLabors.ImageSharp.Tests /// Test that the default configuration is not null. ///
[Fact] - public void TestDefaultConfigurationIsNotNull() => Assert.True(Configuration.Default != null); + public void TestDefaultConfigurationIsNotNull() => Assert.True(this.DefaultConfiguration != null); /// /// Test that the default configuration read origin options is set to begin. /// [Fact] - public void TestDefaultConfigurationReadOriginIsCurrent() => Assert.True(Configuration.Default.ReadOrigin == ReadOrigin.Current); + public void TestDefaultConfigurationReadOriginIsCurrent() => Assert.True(this.DefaultConfiguration.ReadOrigin == ReadOrigin.Current); /// /// Test that the default configuration parallel options max degrees of parallelism matches the @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void TestDefaultConfigurationMaxDegreeOfParallelism() { - Assert.True(Configuration.Default.MaxDegreeOfParallelism == Environment.ProcessorCount); + Assert.True(this.DefaultConfiguration.MaxDegreeOfParallelism == Environment.ProcessorCount); var cfg = new Configuration(); Assert.True(cfg.MaxDegreeOfParallelism == Environment.ProcessorCount); @@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Tests public void ConfigurationCannotAddDuplicates() { const int count = 4; - Configuration config = Configuration.Default; + Configuration config = this.DefaultConfiguration; Assert.Equal(count, config.ImageFormats.Count()); @@ -105,9 +105,16 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void DefaultConfigurationHasCorrectFormatCount() { - Configuration config = Configuration.Default; + Configuration config = Configuration.CreateDefaultInstance(); Assert.Equal(4, config.ImageFormats.Count()); } + + [Fact] + public void WorkingBufferSizeHint_DefaultIsCorrect() + { + Configuration config = this.DefaultConfiguration; + Assert.True(config.WorkingBufferSizeHintInBytes > 1024); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 3d6f08a15..ec0092f34 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -35,6 +35,25 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.07F); + [Theory] + [InlineData(20, 100, 1, 2)] + [InlineData(20, 100, 20*100*16, 2)] + [InlineData(20, 100, 40*100*16, 2)] + [InlineData(20, 100, 59*100*16, 2)] + [InlineData(20, 100, 60*100*16, 3)] + [InlineData(17, 63, 5*17*63*16, 5)] + [InlineData(17, 63, 5*17*63*16+1, 5)] + [InlineData(17, 63, 6*17*63*16-1, 5)] + public void CalculateResizeWorkerWindowCount( + int windowDiameter, + int width, + int sizeLimitHintInBytes, + int expectedCount) + { + int actualCount = ResizeHelper.CalculateResizeWorkerWindowCount(windowDiameter, width, sizeLimitHintInBytes); + Assert.Equal(expectedCount, actualCount); + } + [Theory] [InlineData(-2, 0)] [InlineData(-1, 0)] From 40aea16633ef084c5424e9c682e67485ea2f7676 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 15:02:58 +0200 Subject: [PATCH 069/223] utilize CalculateResizeWorkerHeightInWindowBands() which has been renamed from CalculateResizeWorkerWindowCount() --- src/ImageSharp/Configuration.cs | 14 +++++++------- .../Processors/Transforms/Resize/ResizeHelper.cs | 6 +++--- .../Processors/Transforms/Resize/ResizeWorker.cs | 15 ++++++++++----- .../Processors/Transforms/ResizeKernelMapTests.cs | 1 + .../Processors/Transforms/ResizeTests.cs | 7 +++++-- 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index b1767101d..7cb014563 100644 --- a/src/ImageSharp/Configuration.cs +++ b/src/ImageSharp/Configuration.cs @@ -128,9 +128,9 @@ namespace SixLabors.ImageSharp } /// - /// Creates a shallow copy of the + /// Creates a shallow copy of the . /// - /// A new configuration instance + /// A new configuration instance. public Configuration Clone() { return new Configuration @@ -147,12 +147,12 @@ namespace SixLabors.ImageSharp /// /// Creates the default instance with the following s preregistered: - /// - /// - /// - /// + /// + /// + /// + /// . /// - /// The default configuration of + /// The default configuration of . internal static Configuration CreateDefaultInstance() { return new Configuration( diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs index 0bc8cfda0..595a7e852 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs @@ -15,13 +15,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// internal static class ResizeHelper { - public static unsafe int CalculateResizeWorkerWindowCount( - int windowDiameter, + public static unsafe int CalculateResizeWorkerHeightInWindowBands( + int windowBandDiameter, int width, int sizeLimitHintInBytes) { int sizeLimitHint = sizeLimitHintInBytes / sizeof(Vector4); - int sizeOfOneWindow = windowDiameter * width; + int sizeOfOneWindow = windowBandDiameter * width; return Math.Max(2, sizeLimitHint / sizeOfOneWindow); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index 11b49b863..73dcce58b 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly Rectangle destWorkingRect; - private readonly int diameter; + private readonly int windowBandDiameter; private readonly int windowHeight; @@ -65,9 +65,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.destWorkingRect = destWorkingRect; this.startX = startX; - this.diameter = verticalKernelMap.MaxDiameter; + this.windowBandDiameter = verticalKernelMap.MaxDiameter; - this.windowHeight = Math.Min(this.sourceRectangle.Height, 2 * this.diameter); + int numberOfWindowBands = ResizeHelper.CalculateResizeWorkerHeightInWindowBands( + this.windowBandDiameter, + destWidth, + configuration.WorkingBufferSizeHintInBytes); + + this.windowHeight = Math.Min(this.sourceRectangle.Height, numberOfWindowBands * this.windowBandDiameter); this.buffer = configuration.MemoryAllocator.Allocate2D( this.windowHeight, @@ -143,8 +148,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public void Slide() { - this.CurrentMinY = this.CurrentMinY + this.diameter; - this.CurrentMaxY = Math.Min(this.CurrentMaxY + this.diameter, this.sourceRectangle.Height); + this.CurrentMinY = this.CurrentMinY + this.windowBandDiameter; + this.CurrentMaxY = Math.Min(this.CurrentMaxY + this.windowBandDiameter, this.sourceRectangle.Height); this.CalculateFirstPassValues(this.CurrentMinY, this.CurrentMaxY); } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs index 1bd909e7e..51680eee0 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs @@ -36,6 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { nameof(KnownResamplers.Bicubic), 40, 50 }, { nameof(KnownResamplers.Bicubic), 500, 200 }, { nameof(KnownResamplers.Bicubic), 200, 500 }, + { nameof(KnownResamplers.Bicubic), 3032, 400 }, { nameof(KnownResamplers.Bicubic), 10, 25 }, diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index ec0092f34..532558166 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -44,13 +44,16 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms [InlineData(17, 63, 5*17*63*16, 5)] [InlineData(17, 63, 5*17*63*16+1, 5)] [InlineData(17, 63, 6*17*63*16-1, 5)] - public void CalculateResizeWorkerWindowCount( + [InlineData(33, 400, 1*1024*1024, 4)] + [InlineData(33, 400, 8*1024*1024, 39)] + [InlineData(50, 300, 1*1024*1024, 4)] + public void CalculateResizeWorkerHeightInWindowBands( int windowDiameter, int width, int sizeLimitHintInBytes, int expectedCount) { - int actualCount = ResizeHelper.CalculateResizeWorkerWindowCount(windowDiameter, width, sizeLimitHintInBytes); + int actualCount = ResizeHelper.CalculateResizeWorkerHeightInWindowBands(windowDiameter, width, sizeLimitHintInBytes); Assert.Equal(expectedCount, actualCount); } From 15b3b2a82d88ce0e44ffcc2b5a5e1a1ce72fe52f Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 16:23:01 +0200 Subject: [PATCH 070/223] improve benchmark: ArrayCopy -> CopyBuffers --- .../Transforms/Resize/ResizeKernel.cs | 4 +- .../Transforms/Resize/ResizeWorker.cs | 7 +- .../General/ArrayCopy.cs | 103 ---------- .../General/CopyBuffers.cs | 184 ++++++++++++++++++ 4 files changed, 191 insertions(+), 107 deletions(-) delete mode 100644 tests/ImageSharp.Benchmarks/General/ArrayCopy.cs create mode 100644 tests/ImageSharp.Benchmarks/General/CopyBuffers.cs diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs index 4606f482c..71cba9056 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs @@ -62,13 +62,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public Vector4 ConvolveCore(Span offsetedRowSpan) { ref float horizontalValues = ref Unsafe.AsRef(this.bufferPtr); + // Destination color components Vector4 result = Vector4.Zero; for (int i = 0; i < this.Length; i++) { float weight = Unsafe.Add(ref horizontalValues, i); - //Vector4 v = Unsafe.Add(ref rowStartRef, i); + + // Vector4 v = Unsafe.Add(ref rowStartRef, i); Vector4 v = offsetedRowSpan[i]; result += v * weight; } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index 73dcce58b..e9e39ef13 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Span targetRowSpan = destination.GetRowSpan(y); - PixelOperations.Instance.FromVector4Destructive(configuration, tempColSpan, targetRowSpan, conversionModifiers); + PixelOperations.Instance.FromVector4Destructive(this.configuration, tempColSpan, targetRowSpan, this.conversionModifiers); } } @@ -166,14 +166,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms tempRowSpan, this.conversionModifiers); - //ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top]; + // ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top]; Span firstPassSpan = this.buffer.Span.Slice(y - minY); for (int x = this.destWorkingRect.Left; x < this.destWorkingRect.Right; x++) { ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); firstPassSpan[x * this.windowHeight] = kernel.Convolve(tempRowSpan); - //Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); + + // Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); } } } diff --git a/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs b/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs deleted file mode 100644 index ac6b3f93c..000000000 --- a/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs +++ /dev/null @@ -1,103 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -namespace SixLabors.ImageSharp.Benchmarks.General -{ - using System; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - - using BenchmarkDotNet.Attributes; - - [Config(typeof(Config.ShortClr))] - public class ArrayCopy - { - [Params(10, 100, 1000, 10000)] - public int Count { get; set; } - - byte[] source; - - byte[] destination; - - [GlobalSetup] - public void SetUp() - { - this.source = new byte[this.Count]; - this.destination = new byte[this.Count]; - } - - [Benchmark(Baseline = true, Description = "Copy using Array.Copy()")] - public void CopyArray() - { - Array.Copy(this.source, this.destination, this.Count); - } - - [Benchmark(Description = "Copy using Unsafe")] - public unsafe void CopyUnsafe() - { - fixed (byte* pinnedDestination = this.destination) - fixed (byte* pinnedSource = this.source) - { - Unsafe.CopyBlock(pinnedSource, pinnedDestination, (uint)this.Count); - } - } - - [Benchmark(Description = "Copy using Buffer.BlockCopy()")] - public void CopyUsingBufferBlockCopy() - { - Buffer.BlockCopy(this.source, 0, this.destination, 0, this.Count); - } - - [Benchmark(Description = "Copy using Buffer.MemoryCopy")] - public unsafe void CopyUsingBufferMemoryCopy() - { - fixed (byte* pinnedDestination = this.destination) - fixed (byte* pinnedSource = this.source) - { - Buffer.MemoryCopy(pinnedSource, pinnedDestination, this.Count, this.Count); - } - } - - [Benchmark(Description = "Copy using Marshal.Copy")] - public unsafe void CopyUsingMarshalCopy() - { - fixed (byte* pinnedDestination = this.destination) - { - Marshal.Copy(this.source, 0, (IntPtr)pinnedDestination, this.Count); - } - } - - /***************************************************************************************************************** - *************** RESULTS on i7-4810MQ 2.80GHz + Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1085.0 ******************** - ***************************************************************************************************************** - * - * Method | Count | Mean | StdErr | StdDev | Scaled | Scaled-StdDev | - * ---------------------------------- |------ |------------ |----------- |----------- |------- |-------------- | - * 'Copy using Array.Copy()' | 10 | 20.3074 ns | 0.1194 ns | 0.2068 ns | 1.00 | 0.00 | - * 'Copy using Unsafe' | 10 | 6.1002 ns | 0.1981 ns | 0.3432 ns | 0.30 | 0.01 | - * 'Copy using Buffer.BlockCopy()' | 10 | 10.7879 ns | 0.0984 ns | 0.1705 ns | 0.53 | 0.01 | - * 'Copy using Buffer.MemoryCopy' | 10 | 4.9625 ns | 0.0200 ns | 0.0347 ns | 0.24 | 0.00 | - * 'Copy using Marshal.Copy' | 10 | 16.1782 ns | 0.0919 ns | 0.1592 ns | 0.80 | 0.01 | - * - * 'Copy using Array.Copy()' | 100 | 31.5945 ns | 0.2908 ns | 0.5037 ns | 1.00 | 0.00 | - * 'Copy using Unsafe' | 100 | 10.2722 ns | 0.5202 ns | 0.9010 ns | 0.33 | 0.02 | - * 'Copy using Buffer.BlockCopy()' | 100 | 22.0322 ns | 0.0284 ns | 0.0493 ns | 0.70 | 0.01 | - * 'Copy using Buffer.MemoryCopy' | 100 | 10.2472 ns | 0.0359 ns | 0.0622 ns | 0.32 | 0.00 | - * 'Copy using Marshal.Copy' | 100 | 34.3820 ns | 1.1868 ns | 2.0555 ns | 1.09 | 0.05 | - * - * 'Copy using Array.Copy()' | 1000 | 40.9743 ns | 0.0521 ns | 0.0902 ns | 1.00 | 0.00 | - * 'Copy using Unsafe' | 1000 | 42.7840 ns | 2.0139 ns | 3.4882 ns | 1.04 | 0.07 | - * 'Copy using Buffer.BlockCopy()' | 1000 | 33.7361 ns | 0.0751 ns | 0.1300 ns | 0.82 | 0.00 | - * 'Copy using Buffer.MemoryCopy' | 1000 | 35.7541 ns | 0.0480 ns | 0.0832 ns | 0.87 | 0.00 | - * 'Copy using Marshal.Copy' | 1000 | 42.2028 ns | 0.2769 ns | 0.4795 ns | 1.03 | 0.01 | - * - * 'Copy using Array.Copy()' | 10000 | 200.0438 ns | 0.2251 ns | 0.3899 ns | 1.00 | 0.00 | - * 'Copy using Unsafe' | 10000 | 389.6957 ns | 13.2770 ns | 22.9964 ns | 1.95 | 0.09 | - * 'Copy using Buffer.BlockCopy()' | 10000 | 191.3478 ns | 0.1557 ns | 0.2697 ns | 0.96 | 0.00 | - * 'Copy using Buffer.MemoryCopy' | 10000 | 196.4679 ns | 0.2731 ns | 0.4730 ns | 0.98 | 0.00 | - * 'Copy using Marshal.Copy' | 10000 | 202.5392 ns | 0.5561 ns | 0.9631 ns | 1.01 | 0.00 | - * - */ - } -} diff --git a/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs b/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs new file mode 100644 index 000000000..117cdba41 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs @@ -0,0 +1,184 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +using System; +using System.Buffers; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using BenchmarkDotNet.Attributes; + +namespace SixLabors.ImageSharp.Benchmarks.General +{ + /// + /// Compare different methods for copying native and/or managed buffers. + /// Conclusions: + /// - Span.CopyTo() has terrible performance on classic .NET Framework + /// - Buffer.MemoryCopy() performance is good enough for all sizes (but needs pinning) + /// + [Config(typeof(Config.ShortClr))] + public class CopyBuffers + { + private byte[] destArray; + + private MemoryHandle destHandle; + + private Memory destMemory; + + private byte[] sourceArray; + + private MemoryHandle sourceHandle; + + private Memory sourceMemory; + + [Params(10, 50, 100, 1000, 10000)] + public int Count { get; set; } + + + [GlobalSetup] + public void Setup() + { + this.sourceArray = new byte[this.Count]; + this.sourceMemory = new Memory(this.sourceArray); + this.sourceHandle = this.sourceMemory.Pin(); + + this.destArray = new byte[this.Count]; + this.destMemory = new Memory(this.destArray); + this.destHandle = this.destMemory.Pin(); + } + + [GlobalCleanup] + public void Cleanup() + { + this.sourceHandle.Dispose(); + this.destHandle.Dispose(); + } + + [Benchmark(Baseline = true, Description = "Array.Copy()")] + public void ArrayCopy() + { + Array.Copy(this.sourceArray, this.destArray, this.Count); + } + + [Benchmark(Description = "Buffer.BlockCopy()")] + public void BufferBlockCopy() + { + Buffer.BlockCopy(this.sourceArray, 0, this.destArray, 0, this.Count); + } + + [Benchmark(Description = "Buffer.MemoryCopy()")] + public unsafe void BufferMemoryCopy() + { + void* pinnedDestination = this.destHandle.Pointer; + void* pinnedSource = this.sourceHandle.Pointer; + Buffer.MemoryCopy(pinnedSource, pinnedDestination, this.Count, this.Count); + } + + + [Benchmark(Description = "Marshal.Copy()")] + public unsafe void MarshalCopy() + { + void* pinnedDestination = this.destHandle.Pointer; + Marshal.Copy(this.sourceArray, 0, (IntPtr)pinnedDestination, this.Count); + } + + [Benchmark(Description = "Span.CopyTo()")] + public void SpanCopyTo() + { + this.sourceMemory.Span.CopyTo(this.destMemory.Span); + } + + [Benchmark(Description = "Unsafe.CopyBlock()")] + public unsafe void UnsafeCopyBlock() + { + void* pinnedDestination = this.destHandle.Pointer; + void* pinnedSource = this.sourceHandle.Pointer; + Unsafe.CopyBlock(pinnedSource, pinnedDestination, (uint)this.Count); + } + + // BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17134.706 (1803/April2018Update/Redstone4) + // Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores + // Frequency=2742189 Hz, Resolution=364.6722 ns, Timer=TSC + // .NET Core SDK=2.2.202 + // [Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3394.0 + // Core : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // + // IterationCount=3 LaunchCount=1 WarmupCount=3 + // + // Method | Job | Runtime | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | + // -------------------- |----- |-------- |------ |-----------:|-----------:|----------:|------:|--------:|------------:|------------:|------------:|--------------------:| + // Array.Copy() | Clr | Clr | 10 | 23.579 ns | 1.6836 ns | 0.0923 ns | 1.00 | 0.00 | - | - | - | - | + // Buffer.BlockCopy() | Clr | Clr | 10 | 11.796 ns | 0.5280 ns | 0.0289 ns | 0.50 | 0.00 | - | - | - | - | + // Buffer.MemoryCopy() | Clr | Clr | 10 | 3.206 ns | 8.1741 ns | 0.4480 ns | 0.14 | 0.02 | - | - | - | - | + // Marshal.Copy() | Clr | Clr | 10 | 15.577 ns | 2.0937 ns | 0.1148 ns | 0.66 | 0.00 | - | - | - | - | + // Span.CopyTo() | Clr | Clr | 10 | 32.287 ns | 2.4107 ns | 0.1321 ns | 1.37 | 0.01 | - | - | - | - | + // Unsafe.CopyBlock() | Clr | Clr | 10 | 3.266 ns | 0.3848 ns | 0.0211 ns | 0.14 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | + // Array.Copy() | Core | Core | 10 | 19.713 ns | 7.3026 ns | 0.4003 ns | 1.00 | 0.00 | - | - | - | - | + // Buffer.BlockCopy() | Core | Core | 10 | 7.332 ns | 0.5465 ns | 0.0300 ns | 0.37 | 0.01 | - | - | - | - | + // Buffer.MemoryCopy() | Core | Core | 10 | 2.476 ns | 0.3476 ns | 0.0191 ns | 0.13 | 0.00 | - | - | - | - | + // Marshal.Copy() | Core | Core | 10 | 15.575 ns | 0.1335 ns | 0.0073 ns | 0.79 | 0.02 | - | - | - | - | + // Span.CopyTo() | Core | Core | 10 | 25.321 ns | 2.3556 ns | 0.1291 ns | 1.28 | 0.02 | - | - | - | - | + // Unsafe.CopyBlock() | Core | Core | 10 | 2.204 ns | 0.1836 ns | 0.0101 ns | 0.11 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | + // Array.Copy() | Clr | Clr | 50 | 35.217 ns | 2.7642 ns | 0.1515 ns | 1.00 | 0.00 | - | - | - | - | + // Buffer.BlockCopy() | Clr | Clr | 50 | 24.224 ns | 0.8737 ns | 0.0479 ns | 0.69 | 0.00 | - | - | - | - | + // Buffer.MemoryCopy() | Clr | Clr | 50 | 3.827 ns | 4.8733 ns | 0.2671 ns | 0.11 | 0.01 | - | - | - | - | + // Marshal.Copy() | Clr | Clr | 50 | 28.103 ns | 1.3570 ns | 0.0744 ns | 0.80 | 0.00 | - | - | - | - | + // Span.CopyTo() | Clr | Clr | 50 | 34.137 ns | 2.9274 ns | 0.1605 ns | 0.97 | 0.01 | - | - | - | - | + // Unsafe.CopyBlock() | Clr | Clr | 50 | 4.999 ns | 0.1778 ns | 0.0097 ns | 0.14 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | + // Array.Copy() | Core | Core | 50 | 20.925 ns | 1.0219 ns | 0.0560 ns | 1.00 | 0.00 | - | - | - | - | + // Buffer.BlockCopy() | Core | Core | 50 | 8.083 ns | 0.2158 ns | 0.0118 ns | 0.39 | 0.00 | - | - | - | - | + // Buffer.MemoryCopy() | Core | Core | 50 | 2.919 ns | 0.2878 ns | 0.0158 ns | 0.14 | 0.00 | - | - | - | - | + // Marshal.Copy() | Core | Core | 50 | 16.663 ns | 0.2505 ns | 0.0137 ns | 0.80 | 0.00 | - | - | - | - | + // Span.CopyTo() | Core | Core | 50 | 26.940 ns | 11.5855 ns | 0.6350 ns | 1.29 | 0.03 | - | - | - | - | + // Unsafe.CopyBlock() | Core | Core | 50 | 1.940 ns | 0.6327 ns | 0.0347 ns | 0.09 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | + // Array.Copy() | Clr | Clr | 100 | 39.284 ns | 0.5647 ns | 0.0310 ns | 1.00 | 0.00 | - | - | - | - | + // Buffer.BlockCopy() | Clr | Clr | 100 | 28.930 ns | 0.6774 ns | 0.0371 ns | 0.74 | 0.00 | - | - | - | - | + // Buffer.MemoryCopy() | Clr | Clr | 100 | 5.859 ns | 2.7931 ns | 0.1531 ns | 0.15 | 0.00 | - | - | - | - | + // Marshal.Copy() | Clr | Clr | 100 | 36.529 ns | 0.9886 ns | 0.0542 ns | 0.93 | 0.00 | - | - | - | - | + // Span.CopyTo() | Clr | Clr | 100 | 36.152 ns | 1.5109 ns | 0.0828 ns | 0.92 | 0.00 | - | - | - | - | + // Unsafe.CopyBlock() | Clr | Clr | 100 | 9.317 ns | 0.4342 ns | 0.0238 ns | 0.24 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | + // Array.Copy() | Core | Core | 100 | 22.899 ns | 8.4066 ns | 0.4608 ns | 1.00 | 0.00 | - | - | - | - | + // Buffer.BlockCopy() | Core | Core | 100 | 10.696 ns | 0.8106 ns | 0.0444 ns | 0.47 | 0.01 | - | - | - | - | + // Buffer.MemoryCopy() | Core | Core | 100 | 4.102 ns | 0.9040 ns | 0.0496 ns | 0.18 | 0.01 | - | - | - | - | + // Marshal.Copy() | Core | Core | 100 | 17.917 ns | 2.6490 ns | 0.1452 ns | 0.78 | 0.01 | - | - | - | - | + // Span.CopyTo() | Core | Core | 100 | 28.247 ns | 0.6375 ns | 0.0349 ns | 1.23 | 0.03 | - | - | - | - | + // Unsafe.CopyBlock() | Core | Core | 100 | 3.611 ns | 0.4792 ns | 0.0263 ns | 0.16 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | + // Array.Copy() | Clr | Clr | 1000 | 48.907 ns | 4.4228 ns | 0.2424 ns | 1.00 | 0.00 | - | - | - | - | + // Buffer.BlockCopy() | Clr | Clr | 1000 | 40.653 ns | 1.4055 ns | 0.0770 ns | 0.83 | 0.01 | - | - | - | - | + // Buffer.MemoryCopy() | Clr | Clr | 1000 | 24.720 ns | 1.2651 ns | 0.0693 ns | 0.51 | 0.00 | - | - | - | - | + // Marshal.Copy() | Clr | Clr | 1000 | 42.336 ns | 2.2466 ns | 0.1231 ns | 0.87 | 0.00 | - | - | - | - | + // Span.CopyTo() | Clr | Clr | 1000 | 70.735 ns | 2.6215 ns | 0.1437 ns | 1.45 | 0.01 | - | - | - | - | + // Unsafe.CopyBlock() | Clr | Clr | 1000 | 44.520 ns | 0.9641 ns | 0.0528 ns | 0.91 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | + // Array.Copy() | Core | Core | 1000 | 46.286 ns | 11.6373 ns | 0.6379 ns | 1.00 | 0.00 | - | - | - | - | + // Buffer.BlockCopy() | Core | Core | 1000 | 34.243 ns | 7.2264 ns | 0.3961 ns | 0.74 | 0.01 | - | - | - | - | + // Buffer.MemoryCopy() | Core | Core | 1000 | 23.135 ns | 0.3153 ns | 0.0173 ns | 0.50 | 0.01 | - | - | - | - | + // Marshal.Copy() | Core | Core | 1000 | 46.219 ns | 1.2869 ns | 0.0705 ns | 1.00 | 0.01 | - | - | - | - | + // Span.CopyTo() | Core | Core | 1000 | 45.371 ns | 3.3581 ns | 0.1841 ns | 0.98 | 0.02 | - | - | - | - | + // Unsafe.CopyBlock() | Core | Core | 1000 | 29.347 ns | 1.1349 ns | 0.0622 ns | 0.63 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | + // Array.Copy() | Clr | Clr | 10000 | 218.445 ns | 9.2567 ns | 0.5074 ns | 1.00 | 0.00 | - | - | - | - | + // Buffer.BlockCopy() | Clr | Clr | 10000 | 209.610 ns | 6.7447 ns | 0.3697 ns | 0.96 | 0.00 | - | - | - | - | + // Buffer.MemoryCopy() | Clr | Clr | 10000 | 213.061 ns | 66.6490 ns | 3.6533 ns | 0.98 | 0.02 | - | - | - | - | + // Marshal.Copy() | Clr | Clr | 10000 | 214.426 ns | 27.7722 ns | 1.5223 ns | 0.98 | 0.00 | - | - | - | - | + // Span.CopyTo() | Clr | Clr | 10000 | 486.728 ns | 12.1537 ns | 0.6662 ns | 2.23 | 0.00 | - | - | - | - | + // Unsafe.CopyBlock() | Clr | Clr | 10000 | 452.973 ns | 25.1490 ns | 1.3785 ns | 2.07 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | + // Array.Copy() | Core | Core | 10000 | 203.365 ns | 3.2200 ns | 0.1765 ns | 1.00 | 0.00 | - | - | - | - | + // Buffer.BlockCopy() | Core | Core | 10000 | 193.319 ns | 8.3370 ns | 0.4570 ns | 0.95 | 0.00 | - | - | - | - | + // Buffer.MemoryCopy() | Core | Core | 10000 | 196.541 ns | 37.8056 ns | 2.0723 ns | 0.97 | 0.01 | - | - | - | - | + // Marshal.Copy() | Core | Core | 10000 | 206.454 ns | 3.7652 ns | 0.2064 ns | 1.02 | 0.00 | - | - | - | - | + // Span.CopyTo() | Core | Core | 10000 | 214.799 ns | 3.0667 ns | 0.1681 ns | 1.06 | 0.00 | - | - | - | - | + // Unsafe.CopyBlock() | Core | Core | 10000 | 134.428 ns | 2.6024 ns | 0.1426 ns | 0.66 | 0.00 | - | - | - | - | + + } +} \ No newline at end of file From 6db07016952c25359759a20b06dc08fb8144637d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 16:47:01 +0200 Subject: [PATCH 071/223] moar RowInterval stuff --- src/ImageSharp/Memory/RowInterval.cs | 37 +++++++++++++- .../Transforms/Resize/ResizeWorker.cs | 43 ++++++++-------- .../Helpers/RowIntervalTests.cs | 49 +++++++++++++++++++ 3 files changed, 106 insertions(+), 23 deletions(-) diff --git a/src/ImageSharp/Memory/RowInterval.cs b/src/ImageSharp/Memory/RowInterval.cs index 835e880e9..7e144e37c 100644 --- a/src/ImageSharp/Memory/RowInterval.cs +++ b/src/ImageSharp/Memory/RowInterval.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; + using SixLabors.Primitives; namespace SixLabors.ImageSharp.Memory @@ -8,7 +10,7 @@ namespace SixLabors.ImageSharp.Memory /// /// Represents an interval of rows in a and/or /// - internal readonly struct RowInterval + internal readonly struct RowInterval : IEquatable { /// /// Initializes a new instance of the struct. @@ -36,7 +38,40 @@ namespace SixLabors.ImageSharp.Memory /// public int Height => this.Max - this.Min; + + public static bool operator ==(RowInterval left, RowInterval right) + { + return left.Equals(right); + } + + public static bool operator !=(RowInterval left, RowInterval right) + { + return !left.Equals(right); + } + /// public override string ToString() => $"RowInterval [{this.Min}->{this.Max}]"; + + public RowInterval Slice(int start) => new RowInterval(this.Min + start, this.Max); + + public RowInterval Slice(int start, int length) => new RowInterval(this.Min + start, this.Min + start + length); + + public bool Equals(RowInterval other) + { + return this.Min == other.Min && this.Max == other.Max; + } + + public override bool Equals(object obj) + { + return !ReferenceEquals(null, obj) && obj is RowInterval other && this.Equals(other); + } + + public override int GetHashCode() + { + unchecked + { + return (this.Min * 397) ^ this.Max; + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index e9e39ef13..66a17e2d7 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -45,6 +45,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly int windowHeight; + private RowInterval currentWindow; + public ResizeWorker( Configuration configuration, BufferArea source, @@ -82,14 +84,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.tempRowBuffer = configuration.MemoryAllocator.Allocate(this.sourceRectangle.Width); this.tempColumnBuffer = configuration.MemoryAllocator.Allocate(destWidth); - this.CurrentMinY = 0; - this.CurrentMaxY = this.windowHeight; + this.currentWindow = new RowInterval(0, this.windowHeight); } - public int CurrentMaxY { get; private set; } - - public int CurrentMinY { get; private set; } - public void Dispose() { this.buffer.Dispose(); @@ -100,18 +97,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span GetColumnSpan(int x, int startY) { - return this.buffer.GetRowSpan(x).Slice(startY - this.CurrentMinY); + return this.buffer.GetRowSpan(x).Slice(startY - this.currentWindow.Min); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span GetColumnSpan(int x) - { - return this.buffer.GetRowSpan(x); - } public void Initialize() { - this.CalculateFirstPassValues(0, this.windowHeight); + this.CalculateFirstPassValues(this.currentWindow); } public void FillDestinationPixels(int minY, int maxY, int startY, Buffer2D destination) @@ -123,14 +115,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Ensure offsets are normalized for cropping and padding. ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); - while (kernel.StartIndex + kernel.Length > this.CurrentMaxY) + while (kernel.StartIndex + kernel.Length > this.currentWindow.Max) { this.Slide(); } ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempColSpan); - int top = kernel.StartIndex - this.CurrentMinY; + int top = kernel.StartIndex - this.currentWindow.Min; for (int x = 0; x < this.destWidth; x++) { @@ -146,17 +138,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } } - public void Slide() + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private Span GetColumnSpan(int x) + { + return this.buffer.GetRowSpan(x); + } + + private void Slide() { - this.CurrentMinY = this.CurrentMinY + this.windowBandDiameter; - this.CurrentMaxY = Math.Min(this.CurrentMaxY + this.windowBandDiameter, this.sourceRectangle.Height); - this.CalculateFirstPassValues(this.CurrentMinY, this.CurrentMaxY); + int minY = this.currentWindow.Min + this.windowBandDiameter; + int maxY = Math.Min(this.currentWindow.Max + this.windowBandDiameter, this.sourceRectangle.Height); + this.currentWindow = new RowInterval(minY, maxY); + this.CalculateFirstPassValues(this.currentWindow); } - private void CalculateFirstPassValues(int minY, int maxY) + private void CalculateFirstPassValues(RowInterval window) { Span tempRowSpan = this.tempRowBuffer.GetSpan(); - for (int y = minY; y < maxY; y++) + for (int y = window.Min; y < window.Max; y++) { Span sourceRow = this.source.GetRowSpan(y); @@ -167,7 +166,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.conversionModifiers); // ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top]; - Span firstPassSpan = this.buffer.Span.Slice(y - minY); + Span firstPassSpan = this.buffer.Span.Slice(y - window.Min); for (int x = this.destWorkingRect.Left; x < this.destWorkingRect.Right; x++) { diff --git a/tests/ImageSharp.Tests/Helpers/RowIntervalTests.cs b/tests/ImageSharp.Tests/Helpers/RowIntervalTests.cs index 629b3cdeb..3aead6aaa 100644 --- a/tests/ImageSharp.Tests/Helpers/RowIntervalTests.cs +++ b/tests/ImageSharp.Tests/Helpers/RowIntervalTests.cs @@ -34,5 +34,54 @@ namespace SixLabors.ImageSharp.Tests.Helpers Assert.True(Unsafe.AreSame(ref expected0, ref actual0)); } } + + [Fact] + public void Slice1() + { + RowInterval rowInterval = new RowInterval(10, 20); + RowInterval sliced = rowInterval.Slice(5); + + Assert.Equal(15, sliced.Min); + Assert.Equal(20, sliced.Max); + } + + [Fact] + public void Slice2() + { + RowInterval rowInterval = new RowInterval(10, 20); + RowInterval sliced = rowInterval.Slice(3, 5); + + Assert.Equal(13, sliced.Min); + Assert.Equal(18, sliced.Max); + } + + [Fact] + public void Equality_WhenTrue() + { + RowInterval a = new RowInterval(42, 123); + RowInterval b = new RowInterval(42, 123); + + Assert.True(a.Equals(b)); + Assert.True(a.Equals((object)b)); + Assert.True(a == b); + Assert.Equal(a.GetHashCode(), b.GetHashCode()); + } + + [Fact] + public void Equality_WhenFalse() + { + RowInterval a = new RowInterval(42, 123); + RowInterval b = new RowInterval(42, 125); + RowInterval c = new RowInterval(40, 123); + + Assert.False(a.Equals(b)); + Assert.False(c.Equals(a)); + Assert.False(b.Equals(c)); + + Assert.False(a.Equals((object)b)); + Assert.False(a.Equals(null)); + Assert.False(a == b); + Assert.True(a != c); + } } } From 19766df11ad23998660f8e8ba6732af187703b62 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 17:27:01 +0200 Subject: [PATCH 072/223] buffer.CopyColumns(...) --- src/ImageSharp/Memory/Buffer2DExtensions.cs | 144 +++++++++++------- .../ImageSharp.Tests/Memory/Buffer2DTests.cs | 28 ++++ .../TestUtilities/TestDataGenerator.cs | 13 +- 3 files changed, 130 insertions(+), 55 deletions(-) diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs index 17ab6e252..c8bbf01c7 100644 --- a/src/ImageSharp/Memory/Buffer2DExtensions.cs +++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; using System.Runtime.CompilerServices; using SixLabors.Primitives; @@ -14,41 +15,90 @@ namespace SixLabors.ImageSharp.Memory internal static class Buffer2DExtensions { /// - /// Gets a to the backing buffer of . + /// Copy columns of inplace, + /// from positions starting at to positions at . /// - internal static Span GetSpan(this Buffer2D buffer) + public static unsafe void CopyColumns( + this Buffer2D buffer, + int sourceIndex, + int destIndex, + int columnCount) where T : struct { - return buffer.MemorySource.GetSpan(); + DebugGuard.NotNull(buffer, nameof(buffer)); + DebugGuard.MustBeGreaterThanOrEqualTo(sourceIndex, 0, nameof(sourceIndex)); + DebugGuard.MustBeGreaterThanOrEqualTo(destIndex, sourceIndex + columnCount, nameof(destIndex)); + DebugGuard.MustBeLessThanOrEqualTo(destIndex, buffer.Width - columnCount, nameof(destIndex)); + + int elementSize = Unsafe.SizeOf(); + int width = buffer.Width * elementSize; + int sOffset = sourceIndex * elementSize; + int dOffset = destIndex * elementSize; + long count = columnCount * elementSize; + + using (MemoryHandle handle = buffer.Memory.Pin()) + { + byte* basePtr = (byte*)handle.Pointer; + for (int y = 0; y < buffer.Height; y++) + { + byte* sPtr = basePtr + sOffset; + byte* dPtr = basePtr + dOffset; + + Buffer.MemoryCopy(sPtr, dPtr, count, count); + + basePtr += width; + } + } } /// - /// Gets a to the row 'y' beginning from the pixel at 'x'. + /// Returns a representing the full area of the buffer. /// - /// The buffer - /// The x coordinate (position in the row) - /// The y (row) coordinate /// The element type - /// The - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span GetRowSpan(this Buffer2D buffer, int x, int y) + /// The + /// The + public static Rectangle FullRectangle(this Buffer2D buffer) where T : struct { - return buffer.GetSpan().Slice((y * buffer.Width) + x, buffer.Width - x); + return new Rectangle(0, 0, buffer.Width, buffer.Height); } /// - /// Gets a to the row 'y' beginning from the pixel at the first pixel on that row. + /// Return a to the subarea represented by 'rectangle' /// - /// The buffer - /// The y (row) coordinate /// The element type - /// The - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span GetRowSpan(this Buffer2D buffer, int y) + /// The + /// The rectangle subarea + /// The + public static BufferArea GetArea(this Buffer2D buffer, in Rectangle rectangle) + where T : struct => + new BufferArea(buffer, rectangle); + + public static BufferArea GetArea(this Buffer2D buffer, int x, int y, int width, int height) + where T : struct => + new BufferArea(buffer, new Rectangle(x, y, width, height)); + + /// + /// Return a to the whole area of 'buffer' + /// + /// The element type + /// The + /// The + public static BufferArea GetArea(this Buffer2D buffer) + where T : struct => + new BufferArea(buffer); + + public static BufferArea GetAreaBetweenRows(this Buffer2D buffer, int minY, int maxY) + where T : struct => + new BufferArea(buffer, new Rectangle(0, minY, buffer.Width, maxY - minY)); + + /// + /// Gets a span for all the pixels in defined by + /// + public static Span GetMultiRowSpan(this Buffer2D buffer, in RowInterval rows) where T : struct { - return buffer.GetSpan().Slice(y * buffer.Width, buffer.Width); + return buffer.Span.Slice(rows.Min * buffer.Width, rows.Height * buffer.Width); } /// @@ -66,61 +116,53 @@ namespace SixLabors.ImageSharp.Memory } /// - /// Returns the size of the buffer. + /// Gets a to the row 'y' beginning from the pixel at 'x'. /// + /// The buffer + /// The x coordinate (position in the row) + /// The y (row) coordinate /// The element type - /// The - /// The of the buffer - public static Size Size(this Buffer2D buffer) + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span GetRowSpan(this Buffer2D buffer, int x, int y) where T : struct { - return new Size(buffer.Width, buffer.Height); + return buffer.GetSpan().Slice((y * buffer.Width) + x, buffer.Width - x); } /// - /// Returns a representing the full area of the buffer. + /// Gets a to the row 'y' beginning from the pixel at the first pixel on that row. /// + /// The buffer + /// The y (row) coordinate /// The element type - /// The - /// The - public static Rectangle FullRectangle(this Buffer2D buffer) + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span GetRowSpan(this Buffer2D buffer, int y) where T : struct { - return new Rectangle(0, 0, buffer.Width, buffer.Height); + return buffer.GetSpan().Slice(y * buffer.Width, buffer.Width); } /// - /// Return a to the subarea represented by 'rectangle' - /// - /// The element type - /// The - /// The rectangle subarea - /// The - public static BufferArea GetArea(this Buffer2D buffer, in Rectangle rectangle) - where T : struct => new BufferArea(buffer, rectangle); - - public static BufferArea GetArea(this Buffer2D buffer, int x, int y, int width, int height) - where T : struct => new BufferArea(buffer, new Rectangle(x, y, width, height)); - - public static BufferArea GetAreaBetweenRows(this Buffer2D buffer, int minY, int maxY) - where T : struct => new BufferArea(buffer, new Rectangle(0, minY, buffer.Width, maxY - minY)); - - /// - /// Return a to the whole area of 'buffer' + /// Returns the size of the buffer. /// /// The element type /// The - /// The - public static BufferArea GetArea(this Buffer2D buffer) - where T : struct => new BufferArea(buffer); + /// The of the buffer + public static Size Size(this Buffer2D buffer) + where T : struct + { + return new Size(buffer.Width, buffer.Height); + } /// - /// Gets a span for all the pixels in defined by + /// Gets a to the backing buffer of . /// - public static Span GetMultiRowSpan(this Buffer2D buffer, in RowInterval rows) + internal static Span GetSpan(this Buffer2D buffer) where T : struct { - return buffer.Span.Slice(rows.Min * buffer.Width, rows.Height * buffer.Width); + return buffer.MemorySource.GetSpan(); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs index 19ec725f2..3d4087546 100644 --- a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs +++ b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs @@ -127,5 +127,33 @@ namespace SixLabors.ImageSharp.Tests.Memory Assert.Equal(new Size(10, 5), b.Size()); } } + + [Theory] + [InlineData(100, 20, 0, 90, 10)] + [InlineData(100, 3, 0, 50, 50)] + [InlineData(123, 23, 10, 80, 13)] + [InlineData(10, 1, 3, 6, 3)] + [InlineData(2, 2, 0, 1, 1)] + [InlineData(5, 1, 1, 3, 2)] + public void CopyColumns(int width, int height, int startIndex, int destIndex, int columnCount) + { + Random rnd = new Random(123); + using (Buffer2D b = this.MemoryAllocator.Allocate2D(width, height)) + { + rnd.RandomFill(b.Span, 0, 1); + + b.CopyColumns(startIndex, destIndex, columnCount); + + for (int y = 0; y < b.Height; y++) + { + Span row = b.GetRowSpan(y); + + Span s = row.Slice(startIndex, columnCount); + Span d = row.Slice(destIndex, columnCount); + + Xunit.Assert.True(s.SequenceEqual(d)); + } + } + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/TestDataGenerator.cs b/tests/ImageSharp.Tests/TestUtilities/TestDataGenerator.cs index e3d8bf380..4ccb38745 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestDataGenerator.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestDataGenerator.cs @@ -23,14 +23,19 @@ namespace SixLabors.ImageSharp.Tests { float[] values = new float[length]; - for (int i = 0; i < length; i++) - { - values[i] = GetRandomFloat(rnd, minVal, maxVal); - } + RandomFill(rnd, values, minVal, maxVal); return values; } + public static void RandomFill(this Random rnd, Span destination, float minVal, float maxVal) + { + for (int i = 0; i < destination.Length; i++) + { + destination[i] = GetRandomFloat(rnd, minVal, maxVal); + } + } + /// /// Creates an of the given length consisting of random values between the two ranges. /// From d9e4d6cdd5ed328d28d399755a6218d6307454b9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 17:47:35 +0200 Subject: [PATCH 073/223] simplify ResizeWorker logic --- src/ImageSharp/Memory/RowInterval.cs | 1 - .../Transforms/Resize/ResizeProcessor.cs | 18 +++++---- .../Transforms/Resize/ResizeWorker.cs | 37 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/ImageSharp/Memory/RowInterval.cs b/src/ImageSharp/Memory/RowInterval.cs index 7e144e37c..3ee7ae774 100644 --- a/src/ImageSharp/Memory/RowInterval.cs +++ b/src/ImageSharp/Memory/RowInterval.cs @@ -38,7 +38,6 @@ namespace SixLabors.ImageSharp.Memory /// public int Height => this.Max - this.Min; - public static bool operator ==(RowInterval left, RowInterval right) { return left.Equals(right); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 63dd5efca..e75f6014a 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int startY = this.TargetRectangle.Y; int startX = this.TargetRectangle.X; - var destWorkingRect = Rectangle.Intersect( + var targetWorkingRect = Rectangle.Intersect( this.TargetRectangle, new Rectangle(0, 0, width, height)); @@ -208,7 +208,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms float heightFactor = sourceRectangle.Height / (float)this.TargetRectangle.Height; ParallelHelper.IterateRows( - destWorkingRect, + targetWorkingRect, configuration, rows => { @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); Span targetRow = destination.GetPixelRowSpan(y); - for (int x = destWorkingRect.Left; x < destWorkingRect.Right; x++) + for (int x = targetWorkingRect.Left; x < targetWorkingRect.Right; x++) { // X coordinates of source points targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; @@ -237,8 +237,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms BufferArea sourceArea = source.PixelBuffer.GetArea(sourceRectangle); - // If we want to reintroduce processing: - // it's possible to launch multiple workers for different regions of the image + // To reintroduce parallel processing, we to launch multiple workers + // for different row intervals of the image. using (var worker = new ResizeWorker( configuration, sourceArea, @@ -246,11 +246,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.horizontalKernelMap, this.verticalKernelMap, width, - destWorkingRect, - startX)) + targetWorkingRect, + this.TargetRectangle.Location)) { worker.Initialize(); - worker.FillDestinationPixels(destWorkingRect.Top, destWorkingRect.Bottom, startY, destination.PixelBuffer); + + var workingInterval = new RowInterval(targetWorkingRect.Top, targetWorkingRect.Bottom); + worker.FillDestinationPixels(workingInterval, destination.PixelBuffer); } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index 66a17e2d7..339e8a3b2 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms internal class ResizeWorker : IDisposable where TPixel : struct, IPixel { - private readonly Buffer2D buffer; + private readonly Buffer2D transposedFirstPassBuffer; private readonly Configuration configuration; @@ -29,8 +29,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly Rectangle sourceRectangle; - private readonly int startX; - private readonly IMemoryOwner tempRowBuffer; private readonly IMemoryOwner tempColumnBuffer; @@ -39,7 +37,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly int destWidth; - private readonly Rectangle destWorkingRect; + private readonly Rectangle targetWorkingRect; + + private readonly Point targetOrigin; private readonly int windowBandDiameter; @@ -54,8 +54,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms ResizeKernelMap horizontalKernelMap, ResizeKernelMap verticalKernelMap, int destWidth, - Rectangle destWorkingRect, - int startX) + Rectangle targetWorkingRect, + Point targetOrigin) { this.configuration = configuration; this.source = source; @@ -64,8 +64,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.horizontalKernelMap = horizontalKernelMap; this.verticalKernelMap = verticalKernelMap; this.destWidth = destWidth; - this.destWorkingRect = destWorkingRect; - this.startX = startX; + this.targetWorkingRect = targetWorkingRect; + this.targetOrigin = targetOrigin; this.windowBandDiameter = verticalKernelMap.MaxDiameter; @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.windowHeight = Math.Min(this.sourceRectangle.Height, numberOfWindowBands * this.windowBandDiameter); - this.buffer = configuration.MemoryAllocator.Allocate2D( + this.transposedFirstPassBuffer = configuration.MemoryAllocator.Allocate2D( this.windowHeight, destWidth, AllocationOptions.Clean); @@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public void Dispose() { - this.buffer.Dispose(); + this.transposedFirstPassBuffer.Dispose(); this.tempRowBuffer.Dispose(); this.tempColumnBuffer.Dispose(); } @@ -97,23 +97,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span GetColumnSpan(int x, int startY) { - return this.buffer.GetRowSpan(x).Slice(startY - this.currentWindow.Min); + return this.transposedFirstPassBuffer.GetRowSpan(x).Slice(startY - this.currentWindow.Min); } - public void Initialize() { this.CalculateFirstPassValues(this.currentWindow); } - public void FillDestinationPixels(int minY, int maxY, int startY, Buffer2D destination) + public void FillDestinationPixels(RowInterval rowInterval, Buffer2D destination) { Span tempColSpan = this.tempColumnBuffer.GetSpan(); - for (int y = minY; y < maxY; y++) + for (int y = rowInterval.Min; y < rowInterval.Max; y++) { // Ensure offsets are normalized for cropping and padding. - ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - startY); + ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - this.targetOrigin.Y); while (kernel.StartIndex + kernel.Length > this.currentWindow.Max) { @@ -141,7 +140,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(MethodImplOptions.AggressiveInlining)] private Span GetColumnSpan(int x) { - return this.buffer.GetRowSpan(x); + return this.transposedFirstPassBuffer.GetRowSpan(x); } private void Slide() @@ -166,11 +165,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.conversionModifiers); // ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top]; - Span firstPassSpan = this.buffer.Span.Slice(y - window.Min); + Span firstPassSpan = this.transposedFirstPassBuffer.Span.Slice(y - window.Min); - for (int x = this.destWorkingRect.Left; x < this.destWorkingRect.Right; x++) + for (int x = this.targetWorkingRect.Left; x < this.targetWorkingRect.Right; x++) { - ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.startX); + ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.targetOrigin.X); firstPassSpan[x * this.windowHeight] = kernel.Convolve(tempRowSpan); // Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); From 51cc6593535d13116ee023a43626c92f1515a306 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 21:00:39 +0200 Subject: [PATCH 074/223] WorkingBufferSizeHintInBytes_IsAppliedCorrectly --- .../Transforms/Resize/ResizeHelper.cs | 4 +- .../Transforms/Resize/ResizeWorker.cs | 20 +- .../Processors/Transforms/ResamplerTests.cs | 69 +++ .../Transforms/ResizeHelperTests.cs | 35 ++ .../Processors/Transforms/ResizeTests.cs | 143 +++--- .../BasicTestPatternProvider.cs | 2 +- .../ImageProviders/BlankProvider.cs | 2 +- .../ImageProviders/FileProvider.cs | 2 +- .../ImageProviders/TestImageProvider.cs | 2 +- .../ImageProviders/TestPatternProvider.cs | 3 +- .../TestUtilities/TestMemoryAllocator.cs | 39 +- .../Tests/TestImageProviderTests.cs | 458 ++++++++++-------- tests/Images/External | 2 +- 13 files changed, 474 insertions(+), 307 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Processors/Transforms/ResamplerTests.cs create mode 100644 tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeHelperTests.cs diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs index 595a7e852..956e6b84e 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs @@ -16,12 +16,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms internal static class ResizeHelper { public static unsafe int CalculateResizeWorkerHeightInWindowBands( - int windowBandDiameter, + int windowBandHeight, int width, int sizeLimitHintInBytes) { int sizeLimitHint = sizeLimitHintInBytes / sizeof(Vector4); - int sizeOfOneWindow = windowBandDiameter * width; + int sizeOfOneWindow = windowBandHeight * width; return Math.Max(2, sizeLimitHint / sizeOfOneWindow); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index 339e8a3b2..ce28a00ee 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -41,9 +41,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly Point targetOrigin; - private readonly int windowBandDiameter; + private readonly int windowBandHeight; - private readonly int windowHeight; + private readonly int workerHeight; private RowInterval currentWindow; @@ -67,24 +67,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.targetWorkingRect = targetWorkingRect; this.targetOrigin = targetOrigin; - this.windowBandDiameter = verticalKernelMap.MaxDiameter; + this.windowBandHeight = verticalKernelMap.MaxDiameter; int numberOfWindowBands = ResizeHelper.CalculateResizeWorkerHeightInWindowBands( - this.windowBandDiameter, + this.windowBandHeight, destWidth, configuration.WorkingBufferSizeHintInBytes); - this.windowHeight = Math.Min(this.sourceRectangle.Height, numberOfWindowBands * this.windowBandDiameter); + this.workerHeight = Math.Min(this.sourceRectangle.Height, numberOfWindowBands * this.windowBandHeight); this.transposedFirstPassBuffer = configuration.MemoryAllocator.Allocate2D( - this.windowHeight, + this.workerHeight, destWidth, AllocationOptions.Clean); this.tempRowBuffer = configuration.MemoryAllocator.Allocate(this.sourceRectangle.Width); this.tempColumnBuffer = configuration.MemoryAllocator.Allocate(destWidth); - this.currentWindow = new RowInterval(0, this.windowHeight); + this.currentWindow = new RowInterval(0, this.workerHeight); } public void Dispose() @@ -145,8 +145,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private void Slide() { - int minY = this.currentWindow.Min + this.windowBandDiameter; - int maxY = Math.Min(this.currentWindow.Max + this.windowBandDiameter, this.sourceRectangle.Height); + int minY = this.currentWindow.Min + this.windowBandHeight; + int maxY = Math.Min(this.currentWindow.Max + this.windowBandHeight, this.sourceRectangle.Height); this.currentWindow = new RowInterval(minY, maxY); this.CalculateFirstPassValues(this.currentWindow); } @@ -170,7 +170,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = this.targetWorkingRect.Left; x < this.targetWorkingRect.Right; x++) { ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.targetOrigin.X); - firstPassSpan[x * this.windowHeight] = kernel.Convolve(tempRowSpan); + firstPassSpan[x * this.workerHeight] = kernel.Convolve(tempRowSpan); // Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResamplerTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResamplerTests.cs new file mode 100644 index 000000000..b7b4597c7 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResamplerTests.cs @@ -0,0 +1,69 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Transforms; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms +{ + public class ResamplerTests + { + [Theory] + [InlineData(-2, 0)] + [InlineData(-1, 0)] + [InlineData(0, 1)] + [InlineData(1, 0)] + [InlineData(2, 0)] + public static void BicubicWindowOscillatesCorrectly(float x, float expected) + { + IResampler sampler = KnownResamplers.Bicubic; + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + + [Theory] + [InlineData(-2, 0)] + [InlineData(-1, 0)] + [InlineData(0, 1)] + [InlineData(1, 0)] + [InlineData(2, 0)] + public static void Lanczos3WindowOscillatesCorrectly(float x, float expected) + { + IResampler sampler = KnownResamplers.Lanczos3; + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + + [Theory] + [InlineData(-4, 0)] + [InlineData(-2, 0)] + [InlineData(0, 1)] + [InlineData(2, 0)] + [InlineData(4, 0)] + public static void Lanczos5WindowOscillatesCorrectly(float x, float expected) + { + IResampler sampler = KnownResamplers.Lanczos5; + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + + [Theory] + [InlineData(-2, 0)] + [InlineData(-1, 0)] + [InlineData(0, 1)] + [InlineData(1, 0)] + [InlineData(2, 0)] + public static void TriangleWindowOscillatesCorrectly(float x, float expected) + { + IResampler sampler = KnownResamplers.Triangle; + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeHelperTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeHelperTests.cs new file mode 100644 index 000000000..b0d8ef653 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeHelperTests.cs @@ -0,0 +1,35 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.Processing.Processors.Transforms; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms +{ + public class ResizeHelperTests + { + + [Theory] + [InlineData(20, 100, 1, 2)] + [InlineData(20, 100, 20*100*16, 2)] + [InlineData(20, 100, 40*100*16, 2)] + [InlineData(20, 100, 59*100*16, 2)] + [InlineData(20, 100, 60*100*16, 3)] + [InlineData(17, 63, 5*17*63*16, 5)] + [InlineData(17, 63, 5*17*63*16+1, 5)] + [InlineData(17, 63, 6*17*63*16-1, 5)] + [InlineData(33, 400, 1*1024*1024, 4)] + [InlineData(33, 400, 8*1024*1024, 39)] + [InlineData(50, 300, 1*1024*1024, 4)] + public void CalculateResizeWorkerHeightInWindowBands( + int windowDiameter, + int width, + int sizeLimitHintInBytes, + int expectedCount) + { + int actualCount = ResizeHelper.CalculateResizeWorkerHeightInWindowBands(windowDiameter, width, sizeLimitHintInBytes); + Assert.Equal(expectedCount, actualCount); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 532558166..2ffb42916 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -2,12 +2,17 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Linq; +using System.Numerics; +using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Transforms; +using SixLabors.ImageSharp.Tests.Memory; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.Memory; using SixLabors.Primitives; using Xunit; @@ -35,84 +40,6 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.07F); - [Theory] - [InlineData(20, 100, 1, 2)] - [InlineData(20, 100, 20*100*16, 2)] - [InlineData(20, 100, 40*100*16, 2)] - [InlineData(20, 100, 59*100*16, 2)] - [InlineData(20, 100, 60*100*16, 3)] - [InlineData(17, 63, 5*17*63*16, 5)] - [InlineData(17, 63, 5*17*63*16+1, 5)] - [InlineData(17, 63, 6*17*63*16-1, 5)] - [InlineData(33, 400, 1*1024*1024, 4)] - [InlineData(33, 400, 8*1024*1024, 39)] - [InlineData(50, 300, 1*1024*1024, 4)] - public void CalculateResizeWorkerHeightInWindowBands( - int windowDiameter, - int width, - int sizeLimitHintInBytes, - int expectedCount) - { - int actualCount = ResizeHelper.CalculateResizeWorkerHeightInWindowBands(windowDiameter, width, sizeLimitHintInBytes); - Assert.Equal(expectedCount, actualCount); - } - - [Theory] - [InlineData(-2, 0)] - [InlineData(-1, 0)] - [InlineData(0, 1)] - [InlineData(1, 0)] - [InlineData(2, 0)] - public static void BicubicWindowOscillatesCorrectly(float x, float expected) - { - IResampler sampler = KnownResamplers.Bicubic; - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - - [Theory] - [InlineData(-2, 0)] - [InlineData(-1, 0)] - [InlineData(0, 1)] - [InlineData(1, 0)] - [InlineData(2, 0)] - public static void Lanczos3WindowOscillatesCorrectly(float x, float expected) - { - IResampler sampler = KnownResamplers.Lanczos3; - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - - [Theory] - [InlineData(-4, 0)] - [InlineData(-2, 0)] - [InlineData(0, 1)] - [InlineData(2, 0)] - [InlineData(4, 0)] - public static void Lanczos5WindowOscillatesCorrectly(float x, float expected) - { - IResampler sampler = KnownResamplers.Lanczos5; - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - - [Theory] - [InlineData(-2, 0)] - [InlineData(-1, 0)] - [InlineData(0, 1)] - [InlineData(1, 0)] - [InlineData(2, 0)] - public static void TriangleWindowOscillatesCorrectly(float x, float expected) - { - IResampler sampler = KnownResamplers.Triangle; - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - [Theory] [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32, 2, 3, 1, 2)] [WithBasicTestPatternImages(2, 256, PixelTypes.Rgba32, 1, 1, 1, 8)] @@ -136,6 +63,66 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms } } + private static readonly int SizeOfVector4 = Unsafe.SizeOf(); + + [Theory] + [WithTestPatternImages(100, 100, PixelTypes.Rgba32, 50)] + [WithTestPatternImages(100, 100, PixelTypes.Rgba32, 60)] + [WithTestPatternImages(100, 400, PixelTypes.Rgba32, 110)] + [WithTestPatternImages(79, 97, PixelTypes.Rgba32, 73)] + [WithTestPatternImages(79, 97, PixelTypes.Rgba32, 5)] + [WithTestPatternImages(47, 193, PixelTypes.Rgba32, 73)] + [WithTestPatternImages(23, 211, PixelTypes.Rgba32, 31)] + public void WorkingBufferSizeHintInBytes_IsAppliedCorrectly( + TestImageProvider provider, + int workingBufferLimitInRows) + where TPixel : struct, IPixel + { + using (Image image0 = provider.GetImage()) + { + Size destSize = image0.Size() / 4; + + Configuration configuration = Configuration.CreateDefaultInstance(); + + int workingBufferSizeHintInBytes = workingBufferLimitInRows * destSize.Width * SizeOfVector4; + TestMemoryAllocator allocator = new TestMemoryAllocator(); + configuration.MemoryAllocator = allocator; + configuration.WorkingBufferSizeHintInBytes = workingBufferSizeHintInBytes; + + var verticalKernelMap = ResizeKernelMap.Calculate( + KnownResamplers.Bicubic, + destSize.Height, + image0.Height, + Configuration.Default.MemoryAllocator); + int minimumWorkerAllocationInBytes = verticalKernelMap.MaxDiameter * 2 * destSize.Width * SizeOfVector4; + verticalKernelMap.Dispose(); + + using (Image image = image0.Clone(configuration)) + { + image.Mutate(x => x.Resize(destSize, KnownResamplers.Bicubic, false)); + + image.DebugSave( + provider, + testOutputDetails: workingBufferLimitInRows, + appendPixelTypeToFileName: false); + image.CompareToReferenceOutput( + provider, + testOutputDetails: workingBufferLimitInRows, + appendPixelTypeToFileName: false); + + Assert.NotEmpty(allocator.AllocationLog); + + var internalAllocations = allocator.AllocationLog.Where( + e => e.ElementType == typeof(Vector4)).ToArray(); + + int maxAllocationSize = internalAllocations.Max(e => e.LengthInBytes); + + + Assert.True(maxAllocationSize <= Math.Max(workingBufferSizeHintInBytes, minimumWorkerAllocationInBytes)); + } + } + } + [Theory] [WithTestPatternImages(100, 100, DefaultPixelType)] public void Resize_Compand(TestImageProvider provider) diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs index 47bb22aeb..de203535c 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Tests public override Image GetImage() { - var result = new Image(this.Width, this.Height); + var result = new Image(this.Configuration, this.Width, this.Height); TPixel topLeftColor = NamedColors.Red; TPixel topRightColor = NamedColors.Green; diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs index 1275e522f..dae2f0cfe 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BlankProvider.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Tests protected int Width { get; private set; } - public override Image GetImage() => new Image(this.Width, this.Height); + public override Image GetImage() => new Image(this.Configuration, this.Width, this.Height); public override void Deserialize(IXunitSerializationInfo info) diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs index 3ed696c47..8c5b88b28 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs @@ -152,7 +152,7 @@ namespace SixLabors.ImageSharp.Tests Image cachedImage = cache.GetOrAdd(key, _ => this.LoadImage(decoder)); - return cachedImage.Clone(); + return cachedImage.Clone(this.Configuration); } public override void Deserialize(IXunitSerializationInfo info) diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs index 52f66a78b..15fab9b2b 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs @@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Tests ///
public Image GetImage(Action> operationsToApply) { - Image img = GetImage(); + Image img = this.GetImage(); img.Mutate(operationsToApply); return img; } diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs index 336cdbf11..6df8c8501 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs @@ -45,9 +45,8 @@ namespace SixLabors.ImageSharp.Tests DrawTestPattern(image); TestImages.Add(this.SourceFileOrDescription, image); } + return TestImages[this.SourceFileOrDescription].Clone(this.Configuration); } - - return TestImages[this.SourceFileOrDescription].Clone(); } /// diff --git a/tests/ImageSharp.Tests/TestUtilities/TestMemoryAllocator.cs b/tests/ImageSharp.Tests/TestUtilities/TestMemoryAllocator.cs index dc755e682..5613e7b68 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestMemoryAllocator.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestMemoryAllocator.cs @@ -1,5 +1,7 @@ using System; using System.Buffers; +using System.Collections.Generic; +using System.Numerics; using System.Runtime.InteropServices; using SixLabors.Memory; @@ -8,6 +10,8 @@ namespace SixLabors.ImageSharp.Tests.Memory { internal class TestMemoryAllocator : MemoryAllocator { + private List allocationLog = new List(); + public TestMemoryAllocator(byte dirtyValue = 42) { this.DirtyValue = dirtyValue; @@ -18,10 +22,11 @@ namespace SixLabors.ImageSharp.Tests.Memory /// public byte DirtyValue { get; } + public IList AllocationLog => this.allocationLog; + public override IMemoryOwner Allocate(int length, AllocationOptions options = AllocationOptions.None) - { + { T[] array = this.AllocateArray(length, options); - return new BasicArrayBuffer(array, length); } @@ -34,6 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Memory private T[] AllocateArray(int length, AllocationOptions options) where T : struct { + this.allocationLog.Add(AllocationRequest.Create(options, length)); var array = new T[length + 42]; if (options == AllocationOptions.None) @@ -44,6 +50,35 @@ namespace SixLabors.ImageSharp.Tests.Memory return array; } + + public struct AllocationRequest + { + private AllocationRequest(Type elementType, AllocationOptions allocationOptions, int length, int lengthInBytes) + { + this.ElementType = elementType; + this.AllocationOptions = allocationOptions; + this.Length = length; + this.LengthInBytes = lengthInBytes; + + if (elementType == typeof(Vector4)) + { + + } + } + + public static AllocationRequest Create(AllocationOptions allocationOptions, int length) + { + Type type = typeof(T); + int elementSize = Marshal.SizeOf(type); + return new AllocationRequest(type, allocationOptions, length, length * elementSize); + } + + public Type ElementType { get; } + public AllocationOptions AllocationOptions { get; } + public int Length { get; } + public int LengthInBytes { get; } + } + /// /// Wraps an array as an instance. diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 1bee34f1a..4ef6a582c 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -4,112 +4,135 @@ using System; using System.Collections.Concurrent; using System.IO; + +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; + using Xunit; using Xunit.Abstractions; + // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests { public class TestImageProviderTests { + public static readonly TheoryData BasicData = new TheoryData() + { + TestImageProvider.Blank(10, 20), + TestImageProvider.Blank(10, 20), + }; + + public static readonly TheoryData FileData = new TheoryData() + { + TestImageProvider.File(TestImages.Bmp.Car), + TestImageProvider.File( + TestImages.Bmp.F) + }; + + public static string[] AllBmpFiles = { TestImages.Bmp.F, TestImages.Bmp.Bit8 }; + public TestImageProviderTests(ITestOutputHelper output) => this.Output = output; private ITestOutputHelper Output { get; } - [Theory] - [WithBlankImages(1, 1, PixelTypes.Rgba32)] - public void NoOutputSubfolderIsPresentByDefault(TestImageProvider provider) - where TPixel : struct, IPixel => Assert.Empty(provider.Utility.OutputSubfolderName); + /// + /// Need to us to create instance of when pixelType is StandardImageClass + /// + /// + /// + /// + public static Image CreateTestImage() + where TPixel : struct, IPixel => + new Image(3, 3); [Theory] - [WithBlankImages(42, 666, PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.HalfSingle, "hello")] - public void Use_WithEmptyImageAttribute(TestImageProvider provider, string message) + [MemberData(nameof(BasicData))] + public void Blank_MemberData(TestImageProvider provider) where TPixel : struct, IPixel { Image img = provider.GetImage(); - Assert.Equal(42, img.Width); - Assert.Equal(666, img.Height); - Assert.Equal("hello", message); + Assert.True(img.Width * img.Height > 0); } [Theory] - [WithBlankImages(42, 666, PixelTypes.All, "hello")] - public void Use_WithBlankImagesAttribute_WithAllPixelTypes( - TestImageProvider provider, - string message) + [MemberData(nameof(FileData))] + public void File_MemberData(TestImageProvider provider) where TPixel : struct, IPixel { + this.Output.WriteLine("SRC: " + provider.Utility.SourceFileOrDescription); + this.Output.WriteLine("OUT: " + provider.Utility.GetTestOutputFileName()); + Image img = provider.GetImage(); - Assert.Equal(42, img.Width); - Assert.Equal(666, img.Height); - Assert.Equal("hello", message); + Assert.True(img.Width * img.Height > 0); } [Theory] - [WithBlankImages(1, 1, PixelTypes.Rgba32, PixelTypes.Rgba32)] - [WithBlankImages(1, 1, PixelTypes.Alpha8, PixelTypes.Alpha8)] - [WithBlankImages(1, 1, PixelTypes.Argb32, PixelTypes.Argb32)] - public void PixelType_PropertyValueIsCorrect(TestImageProvider provider, PixelTypes expected) - where TPixel : struct, IPixel => Assert.Equal(expected, provider.PixelType); - - [Theory] - [WithFile(TestImages.Bmp.Car, PixelTypes.All, 88)] - [WithFile(TestImages.Bmp.F, PixelTypes.All, 88)] - public void Use_WithFileAttribute(TestImageProvider provider, int yo) + [WithFile(TestImages.Bmp.F, PixelTypes.Rgba32)] + public void GetImage_WithCustomParameterlessDecoder_ShouldUtilizeCache( + TestImageProvider provider) where TPixel : struct, IPixel { + if (!TestEnvironment.Is64BitProcess) + { + // We don't cache with the 32 bit build. + return; + } + Assert.NotNull(provider.Utility.SourceFileOrDescription); - Image img = provider.GetImage(); - Assert.True(img.Width * img.Height > 0); - Assert.Equal(88, yo); + TestDecoder.DoTestThreadSafe( + () => + { + string testName = nameof(this.GetImage_WithCustomParameterlessDecoder_ShouldUtilizeCache); - string fn = provider.Utility.GetTestOutputFileName("jpg"); - this.Output.WriteLine(fn); - } + var decoder = new TestDecoder(); + decoder.InitCaller(testName); - private class TestDecoder : IImageDecoder - { - public Image Decode(Configuration configuration, Stream stream) - where TPixel : struct, IPixel - { - invocationCounts[this.callerName]++; - return new Image(42, 42); - } + provider.GetImage(decoder); + Assert.Equal(1, TestDecoder.GetInvocationCount(testName)); - // Couldn't make xUnit happy without this hackery: + provider.GetImage(decoder); + Assert.Equal(1, TestDecoder.GetInvocationCount(testName)); + }); + } - private static readonly ConcurrentDictionary invocationCounts = new ConcurrentDictionary(); + [Theory] + [WithFile(TestImages.Bmp.F, PixelTypes.Rgba32)] + public void GetImage_WithCustomParametricDecoder_ShouldNotUtilizeCache_WhenParametersAreNotEqual( + TestImageProvider provider) + where TPixel : struct, IPixel + { + Assert.NotNull(provider.Utility.SourceFileOrDescription); - private string callerName = null; + TestDecoderWithParameters.DoTestThreadSafe( + () => + { + string testName = nameof(this + .GetImage_WithCustomParametricDecoder_ShouldNotUtilizeCache_WhenParametersAreNotEqual); - internal void InitCaller(string name) - { - this.callerName = name; - invocationCounts[name] = 0; - } + var decoder1 = new TestDecoderWithParameters() { Param1 = "Lol", Param2 = 42 }; + decoder1.InitCaller(testName); - internal static int GetInvocationCount(string callerName) => invocationCounts[callerName]; + var decoder2 = new TestDecoderWithParameters() { Param1 = "LoL", Param2 = 42 }; + decoder2.InitCaller(testName); - private static readonly object Monitor = new object(); + provider.GetImage(decoder1); + Assert.Equal(1, TestDecoderWithParameters.GetInvocationCount(testName)); - public static void DoTestThreadSafe(Action action) - { - lock (Monitor) - { - action(); - } - } + provider.GetImage(decoder2); + Assert.Equal(2, TestDecoderWithParameters.GetInvocationCount(testName)); + }); } [Theory] [WithFile(TestImages.Bmp.F, PixelTypes.Rgba32)] - public void GetImage_WithCustomParameterlessDecoder_ShouldUtilizeCache(TestImageProvider provider) + public void GetImage_WithCustomParametricDecoder_ShouldUtilizeCache_WhenParametersAreEqual( + TestImageProvider provider) where TPixel : struct, IPixel { if (!TestEnvironment.Is64BitProcess) @@ -120,121 +143,122 @@ namespace SixLabors.ImageSharp.Tests Assert.NotNull(provider.Utility.SourceFileOrDescription); - TestDecoder.DoTestThreadSafe(() => - { - string testName = nameof(this.GetImage_WithCustomParameterlessDecoder_ShouldUtilizeCache); - - var decoder = new TestDecoder(); - decoder.InitCaller(testName); - - provider.GetImage(decoder); - Assert.Equal(1, TestDecoder.GetInvocationCount(testName)); + TestDecoderWithParameters.DoTestThreadSafe( + () => + { + string testName = nameof(this + .GetImage_WithCustomParametricDecoder_ShouldUtilizeCache_WhenParametersAreEqual); - provider.GetImage(decoder); - Assert.Equal(1, TestDecoder.GetInvocationCount(testName)); - }); - } + var decoder1 = new TestDecoderWithParameters() { Param1 = "Lol", Param2 = 666 }; + decoder1.InitCaller(testName); - private class TestDecoderWithParameters : IImageDecoder - { - public string Param1 { get; set; } + var decoder2 = new TestDecoderWithParameters() { Param1 = "Lol", Param2 = 666 }; + decoder2.InitCaller(testName); - public int Param2 { get; set; } + provider.GetImage(decoder1); + Assert.Equal(1, TestDecoderWithParameters.GetInvocationCount(testName)); - public Image Decode(Configuration configuration, Stream stream) - where TPixel : struct, IPixel - { - invocationCounts[this.callerName]++; - return new Image(42, 42); - } + provider.GetImage(decoder2); + Assert.Equal(1, TestDecoderWithParameters.GetInvocationCount(testName)); + }); + } - private static readonly ConcurrentDictionary invocationCounts = new ConcurrentDictionary(); + [Theory] + [WithBlankImages(1, 1, PixelTypes.Rgba32)] + public void NoOutputSubfolderIsPresentByDefault(TestImageProvider provider) + where TPixel : struct, IPixel => + Assert.Empty(provider.Utility.OutputSubfolderName); - private string callerName = null; + [Theory] + [WithBlankImages(1, 1, PixelTypes.Rgba32, PixelTypes.Rgba32)] + [WithBlankImages(1, 1, PixelTypes.Alpha8, PixelTypes.Alpha8)] + [WithBlankImages(1, 1, PixelTypes.Argb32, PixelTypes.Argb32)] + public void PixelType_PropertyValueIsCorrect(TestImageProvider provider, PixelTypes expected) + where TPixel : struct, IPixel => + Assert.Equal(expected, provider.PixelType); - internal void InitCaller(string name) + [Theory] + [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)] + public void SaveTestOutputFileMultiFrame(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) { - this.callerName = name; - invocationCounts[name] = 0; - } - - internal static int GetInvocationCount(string callerName) => invocationCounts[callerName]; - - private static readonly object Monitor = new object(); + string[] files = provider.Utility.SaveTestOutputFileMultiFrame(image); - public static void DoTestThreadSafe(Action action) - { - lock (Monitor) + Assert.True(files.Length > 2); + foreach (string path in files) { - action(); + this.Output.WriteLine(path); + Assert.True(File.Exists(path)); } } } [Theory] - [WithFile(TestImages.Bmp.F, PixelTypes.Rgba32)] - public void GetImage_WithCustomParametricDecoder_ShouldUtilizeCache_WhenParametersAreEqual(TestImageProvider provider) + [WithBasicTestPatternImages(50, 100, PixelTypes.Rgba32)] + [WithBasicTestPatternImages(49, 17, PixelTypes.Rgba32)] + [WithBasicTestPatternImages(20, 10, PixelTypes.Rgba32)] + public void Use_WithBasicTestPatternImages(TestImageProvider provider) where TPixel : struct, IPixel { - if (!TestEnvironment.Is64BitProcess) + using (Image img = provider.GetImage()) { - // We don't cache with the 32 bit build. - return; + img.DebugSave(provider); } + } - Assert.NotNull(provider.Utility.SourceFileOrDescription); - - TestDecoderWithParameters.DoTestThreadSafe(() => - { - string testName = - nameof(this.GetImage_WithCustomParametricDecoder_ShouldUtilizeCache_WhenParametersAreEqual); - - var decoder1 = new TestDecoderWithParameters() { Param1 = "Lol", Param2 = 666 }; - decoder1.InitCaller(testName); + [Theory] + [WithBlankImages(42, 666, PixelTypes.All, "hello")] + public void Use_WithBlankImagesAttribute_WithAllPixelTypes( + TestImageProvider provider, + string message) + where TPixel : struct, IPixel + { + Image img = provider.GetImage(); - var decoder2 = new TestDecoderWithParameters() { Param1 = "Lol", Param2 = 666 }; - decoder2.InitCaller(testName); + Assert.Equal(42, img.Width); + Assert.Equal(666, img.Height); + Assert.Equal("hello", message); + } - provider.GetImage(decoder1); - Assert.Equal(1, TestDecoderWithParameters.GetInvocationCount(testName)); + [Theory] + [WithBlankImages(42, 666, PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.HalfSingle, "hello")] + public void Use_WithEmptyImageAttribute(TestImageProvider provider, string message) + where TPixel : struct, IPixel + { + Image img = provider.GetImage(); - provider.GetImage(decoder2); - Assert.Equal(1, TestDecoderWithParameters.GetInvocationCount(testName)); - }); + Assert.Equal(42, img.Width); + Assert.Equal(666, img.Height); + Assert.Equal("hello", message); } [Theory] - [WithFile(TestImages.Bmp.F, PixelTypes.Rgba32)] - public void GetImage_WithCustomParametricDecoder_ShouldNotUtilizeCache_WhenParametersAreNotEqual(TestImageProvider provider) + [WithFile(TestImages.Bmp.Car, PixelTypes.All, 123)] + [WithFile(TestImages.Bmp.F, PixelTypes.All, 123)] + public void Use_WithFileAttribute(TestImageProvider provider, int yo) where TPixel : struct, IPixel { Assert.NotNull(provider.Utility.SourceFileOrDescription); - - TestDecoderWithParameters.DoTestThreadSafe(() => + using (Image img = provider.GetImage()) { - string testName = - nameof(this.GetImage_WithCustomParametricDecoder_ShouldNotUtilizeCache_WhenParametersAreNotEqual); - - var decoder1 = new TestDecoderWithParameters() { Param1 = "Lol", Param2 = 42 }; - decoder1.InitCaller(testName); - - var decoder2 = new TestDecoderWithParameters() { Param1 = "LoL", Param2 = 42 }; - decoder2.InitCaller(testName); + Assert.True(img.Width * img.Height > 0); - provider.GetImage(decoder1); - Assert.Equal(1, TestDecoderWithParameters.GetInvocationCount(testName)); + Assert.Equal(123, yo); - provider.GetImage(decoder2); - Assert.Equal(2, TestDecoderWithParameters.GetInvocationCount(testName)); - }); + string fn = provider.Utility.GetTestOutputFileName("jpg"); + this.Output.WriteLine(fn); + } } - - public static string[] AllBmpFiles = - { - TestImages.Bmp.F, - TestImages.Bmp.Bit8 - }; + [Theory] + [WithFile(TestImages.Jpeg.Baseline.Testorig420, PixelTypes.Rgba32)] + public void Use_WithFileAttribute_CustomConfig(TestImageProvider provider) + where TPixel : struct, IPixel + { + EnsureCustomConfigurationIsApplied(provider); + } [Theory] [WithFileCollection(nameof(AllBmpFiles), PixelTypes.Rgba32 | PixelTypes.Argb32)] @@ -249,20 +273,15 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)] - public void SaveTestOutputFileMultiFrame(TestImageProvider provider) + [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All)] + public void Use_WithMemberFactoryAttribute(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) + Image img = provider.GetImage(); + Assert.Equal(3, img.Width); + if (provider.PixelType == PixelTypes.Rgba32) { - string[] files = provider.Utility.SaveTestOutputFileMultiFrame(image); - - Assert.True(files.Length > 2); - foreach (string path in files) - { - this.Output.WriteLine(path); - Assert.True(File.Exists(path)); - } + Assert.IsType>(img); } } @@ -291,89 +310,112 @@ namespace SixLabors.ImageSharp.Tests } } - /// - /// Need to us to create instance of when pixelType is StandardImageClass - /// - /// - /// - /// - public static Image CreateTestImage() - where TPixel : struct, IPixel => new Image(3, 3); - [Theory] - [WithMemberFactory(nameof(CreateTestImage), PixelTypes.All)] - public void Use_WithMemberFactoryAttribute(TestImageProvider provider) + [WithTestPatternImages(49, 20, PixelTypes.Rgba32)] + public void Use_WithTestPatternImages(TestImageProvider provider) where TPixel : struct, IPixel { - Image img = provider.GetImage(); - Assert.Equal(3, img.Width); - if (provider.PixelType == PixelTypes.Rgba32) + using (Image img = provider.GetImage()) { - Assert.IsType>(img); + img.DebugSave(provider); } - } - + [Theory] - [WithTestPatternImages(49,20, PixelTypes.Rgba32)] - public void Use_WithTestPatternImages(TestImageProvider provider) + [WithTestPatternImages(20, 20, PixelTypes.Rgba32)] + public void Use_WithTestPatternImages_CustomConfiguration(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image img = provider.GetImage()) - { - img.DebugSave(provider); - } + EnsureCustomConfigurationIsApplied(provider); } - [Theory] - [WithBasicTestPatternImages(50, 100, PixelTypes.Rgba32)] - [WithBasicTestPatternImages(49,17, PixelTypes.Rgba32)] - [WithBasicTestPatternImages(20, 10, PixelTypes.Rgba32)] - public void Use_WithBasicTestPatternImages(TestImageProvider provider) + private static void EnsureCustomConfigurationIsApplied(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image img = provider.GetImage()) + using (var image1 = provider.GetImage()) { - img.DebugSave(provider); + var customConfiguration = Configuration.CreateDefaultInstance(); + provider.Configuration = customConfiguration; + + using (var image2 = provider.GetImage()) + using (var image3 = provider.GetImage()) + { + Assert.Same(customConfiguration, image2.GetConfiguration()); + Assert.Same(customConfiguration, image3.GetConfiguration()); + } } } - - public static readonly TheoryData BasicData = new TheoryData() + private class TestDecoder : IImageDecoder { - TestImageProvider.Blank(10, 20), - TestImageProvider.Blank( - 10, - 20), - }; + // Couldn't make xUnit happy without this hackery: - [Theory] - [MemberData(nameof(BasicData))] - public void Blank_MemberData(TestImageProvider provider) - where TPixel : struct, IPixel - { - Image img = provider.GetImage(); + private static readonly ConcurrentDictionary invocationCounts = + new ConcurrentDictionary(); - Assert.True(img.Width * img.Height > 0); + private static readonly object Monitor = new object(); + + private string callerName = null; + + public static void DoTestThreadSafe(Action action) + { + lock (Monitor) + { + action(); + } + } + + public Image Decode(Configuration configuration, Stream stream) + where TPixel : struct, IPixel + { + invocationCounts[this.callerName]++; + return new Image(42, 42); + } + + internal static int GetInvocationCount(string callerName) => invocationCounts[callerName]; + + internal void InitCaller(string name) + { + this.callerName = name; + invocationCounts[name] = 0; + } } - public static readonly TheoryData FileData = new TheoryData() + private class TestDecoderWithParameters : IImageDecoder { - TestImageProvider.File(TestImages.Bmp.Car), - TestImageProvider.File(TestImages.Bmp.F) - }; + private static readonly ConcurrentDictionary invocationCounts = + new ConcurrentDictionary(); - [Theory] - [MemberData(nameof(FileData))] - public void File_MemberData(TestImageProvider provider) - where TPixel : struct, IPixel - { - this.Output.WriteLine("SRC: " + provider.Utility.SourceFileOrDescription); - this.Output.WriteLine("OUT: " + provider.Utility.GetTestOutputFileName()); + private static readonly object Monitor = new object(); - Image img = provider.GetImage(); + private string callerName = null; - Assert.True(img.Width * img.Height > 0); + public string Param1 { get; set; } + + public int Param2 { get; set; } + + public static void DoTestThreadSafe(Action action) + { + lock (Monitor) + { + action(); + } + } + + public Image Decode(Configuration configuration, Stream stream) + where TPixel : struct, IPixel + { + invocationCounts[this.callerName]++; + return new Image(42, 42); + } + + internal static int GetInvocationCount(string callerName) => invocationCounts[callerName]; + + internal void InitCaller(string name) + { + this.callerName = name; + invocationCounts[name] = 0; + } } } -} +} \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index c7333d2a8..6db7ed95d 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit c7333d2a81a74d1936bd202bcb6b16cbfe6bcdce +Subproject commit 6db7ed95dd8a2de4caa6d885952b6689d026ad27 From 3860fb6f5bcd23e3fdd1f2e907df44806f28dde1 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 21:15:50 +0200 Subject: [PATCH 075/223] more robust tests --- .../Processing/Processors/Transforms/ResizeTests.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 2ffb42916..6d02b4b45 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -112,11 +112,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms Assert.NotEmpty(allocator.AllocationLog); - var internalAllocations = allocator.AllocationLog.Where( - e => e.ElementType == typeof(Vector4)).ToArray(); - - int maxAllocationSize = internalAllocations.Max(e => e.LengthInBytes); - + int maxAllocationSize = allocator.AllocationLog.Where( + e => e.ElementType == typeof(Vector4)).Max(e => e.LengthInBytes); Assert.True(maxAllocationSize <= Math.Max(workingBufferSizeHintInBytes, minimumWorkerAllocationInBytes)); } @@ -256,6 +253,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms var comparer = ImageComparer.TolerantPercentage(allowHigherInaccuracy ? 0.3f : 0.017f); + // Let's make the working buffer size non-default: + provider.Configuration.WorkingBufferSizeHintInBytes = 16 * 1024 * SizeOfVector4; + provider.RunValidatingProcessorTest( ctx => { From 1fd135f62bb833e5524e7a4740d04eca2b847777 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 21:42:39 +0200 Subject: [PATCH 076/223] ResizeTests.LargeImage --- .../Transforms/Resize/ResizeWorker.cs | 7 ++++--- .../Processors/Transforms/ResizeTests.cs | 17 ++++++++++++++++- tests/Images/External | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index ce28a00ee..9282c2128 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -114,7 +114,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Ensure offsets are normalized for cropping and padding. ResizeKernel kernel = this.verticalKernelMap.GetKernel(y - this.targetOrigin.Y); - while (kernel.StartIndex + kernel.Length > this.currentWindow.Max) + if (kernel.StartIndex + kernel.Length > this.currentWindow.Max) { this.Slide(); } @@ -145,8 +145,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private void Slide() { - int minY = this.currentWindow.Min + this.windowBandHeight; - int maxY = Math.Min(this.currentWindow.Max + this.windowBandHeight, this.sourceRectangle.Height); + int minY = this.currentWindow.Max - this.windowBandHeight; + int maxY = Math.Min(minY + this.workerHeight, this.sourceRectangle.Height); + this.currentWindow = new RowInterval(minY, maxY); this.CalculateFirstPassValues(this.currentWindow); } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 6d02b4b45..f4098aaf7 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -34,12 +34,27 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms public static readonly string[] SmokeTestResamplerNames = { - nameof(KnownResamplers.NearestNeighbor), nameof(KnownResamplers.Bicubic), nameof(KnownResamplers.Box), + nameof(KnownResamplers.NearestNeighbor), + nameof(KnownResamplers.Bicubic), + nameof(KnownResamplers.Box), nameof(KnownResamplers.Lanczos5), }; private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.07F); + [Theory] + [WithTestPatternImages(4000, 4000, PixelTypes.Rgba32)] + public void LargeImage(TestImageProvider provider) + where TPixel : struct, IPixel + { + if (!TestEnvironment.Is64BitProcess) + { + return; + } + + provider.RunValidatingProcessorTest(x => x.Resize(300, 300), appendPixelTypeToFileName: false); + } + [Theory] [WithBasicTestPatternImages(15, 12, PixelTypes.Rgba32, 2, 3, 1, 2)] [WithBasicTestPatternImages(2, 256, PixelTypes.Rgba32, 1, 1, 1, 8)] diff --git a/tests/Images/External b/tests/Images/External index 6db7ed95d..8693e2fd4 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 6db7ed95dd8a2de4caa6d885952b6689d026ad27 +Subproject commit 8693e2fd4577a9ac1a749da8db564095b5a05389 From f6c778442d1210c7bdc93221eeb52ee804313275 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 22:52:14 +0200 Subject: [PATCH 077/223] optimized sliding works! --- src/ImageSharp/Memory/Buffer2DExtensions.cs | 28 ++++++++++++++++--- .../Transforms/Resize/ResizeWorker.cs | 17 ++++++++--- .../ImageSharp.Tests/Memory/Buffer2DTests.cs | 23 +++++++++++++++ 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs index c8bbf01c7..61fcb99db 100644 --- a/src/ImageSharp/Memory/Buffer2DExtensions.cs +++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs @@ -3,7 +3,9 @@ using System; using System.Buffers; +using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using SixLabors.Primitives; @@ -27,8 +29,8 @@ namespace SixLabors.ImageSharp.Memory { DebugGuard.NotNull(buffer, nameof(buffer)); DebugGuard.MustBeGreaterThanOrEqualTo(sourceIndex, 0, nameof(sourceIndex)); - DebugGuard.MustBeGreaterThanOrEqualTo(destIndex, sourceIndex + columnCount, nameof(destIndex)); - DebugGuard.MustBeLessThanOrEqualTo(destIndex, buffer.Width - columnCount, nameof(destIndex)); + DebugGuard.MustBeGreaterThanOrEqualTo(destIndex, 0, nameof(sourceIndex)); + CheckColumnRegionsDoNotOverlap(buffer, sourceIndex, destIndex, columnCount); int elementSize = Unsafe.SizeOf(); int width = buffer.Width * elementSize; @@ -36,9 +38,11 @@ namespace SixLabors.ImageSharp.Memory int dOffset = destIndex * elementSize; long count = columnCount * elementSize; - using (MemoryHandle handle = buffer.Memory.Pin()) + Span span = MemoryMarshal.AsBytes(buffer.Memory.Span); + + fixed (byte* ptr = span) { - byte* basePtr = (byte*)handle.Pointer; + byte* basePtr = (byte*)ptr; for (int y = 0; y < buffer.Height; y++) { byte* sPtr = basePtr + sOffset; @@ -164,5 +168,21 @@ namespace SixLabors.ImageSharp.Memory { return buffer.MemorySource.GetSpan(); } + + [Conditional("DEBUG")] + private static void CheckColumnRegionsDoNotOverlap( + Buffer2D buffer, + int sourceIndex, + int destIndex, + int columnCount) + where T : struct + { + int minIndex = Math.Min(sourceIndex, destIndex); + int maxIndex = Math.Max(sourceIndex, destIndex); + if (maxIndex < minIndex + columnCount || maxIndex > buffer.Width - columnCount) + { + throw new InvalidOperationException("Column regions should not overlap!"); + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index 9282c2128..ed505e221 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -148,14 +148,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int minY = this.currentWindow.Max - this.windowBandHeight; int maxY = Math.Min(minY + this.workerHeight, this.sourceRectangle.Height); + // Copy previous bottom band to the new top: + // (rows <--> columns, because the buffer is transposed) + this.transposedFirstPassBuffer.CopyColumns( + this.workerHeight - this.windowBandHeight, + 0, + this.windowBandHeight); + this.currentWindow = new RowInterval(minY, maxY); - this.CalculateFirstPassValues(this.currentWindow); + + // Calculate the remainder: + this.CalculateFirstPassValues(this.currentWindow.Slice(this.windowBandHeight)); } - private void CalculateFirstPassValues(RowInterval window) + private void CalculateFirstPassValues(RowInterval calculationInterval) { Span tempRowSpan = this.tempRowBuffer.GetSpan(); - for (int y = window.Min; y < window.Max; y++) + for (int y = calculationInterval.Min; y < calculationInterval.Max; y++) { Span sourceRow = this.source.GetRowSpan(y); @@ -166,7 +175,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.conversionModifiers); // ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top]; - Span firstPassSpan = this.transposedFirstPassBuffer.Span.Slice(y - window.Min); + Span firstPassSpan = this.transposedFirstPassBuffer.Span.Slice(y - this.currentWindow.Min); for (int x = this.targetWorkingRect.Left; x < this.targetWorkingRect.Right; x++) { diff --git a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs index 3d4087546..4af3b81e2 100644 --- a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs +++ b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs @@ -155,5 +155,28 @@ namespace SixLabors.ImageSharp.Tests.Memory } } } + + [Fact] + public void CopyColumns_InvokeMultipleTimes() + { + Random rnd = new Random(123); + using (Buffer2D b = this.MemoryAllocator.Allocate2D(100, 100)) + { + rnd.RandomFill(b.Span, 0, 1); + + b.CopyColumns(0, 50, 22); + b.CopyColumns(0, 50, 22); + + for (int y = 0; y < b.Height; y++) + { + Span row = b.GetRowSpan(y); + + Span s = row.Slice(0, 22); + Span d = row.Slice(50, 22); + + Xunit.Assert.True(s.SequenceEqual(d)); + } + } + } } } \ No newline at end of file From f7e0a94e1d1a81c3c7494ed42d6df12dc4bc38ca Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 23:02:10 +0200 Subject: [PATCH 078/223] reapply unsafe optimizations --- .../Processors/Transforms/Resize/ResizeKernel.cs | 8 ++++---- .../Processors/Transforms/Resize/ResizeWorker.cs | 13 +++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs index 71cba9056..dce4e70d6 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs @@ -55,11 +55,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public Vector4 Convolve(Span rowSpan) { - return this.ConvolveCore(rowSpan.Slice(this.StartIndex)); + return this.ConvolveCore(ref rowSpan[this.StartIndex]); } [MethodImpl(InliningOptions.ShortMethod)] - public Vector4 ConvolveCore(Span offsetedRowSpan) + public Vector4 ConvolveCore(ref Vector4 rowStartRef) { ref float horizontalValues = ref Unsafe.AsRef(this.bufferPtr); @@ -70,8 +70,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { float weight = Unsafe.Add(ref horizontalValues, i); - // Vector4 v = Unsafe.Add(ref rowStartRef, i); - Vector4 v = offsetedRowSpan[i]; + // Vector4 v = offsetedRowSpan[i]; + Vector4 v = Unsafe.Add(ref rowStartRef, i); result += v * weight; } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index ed505e221..9b7d1d17c 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -125,10 +125,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = 0; x < this.destWidth; x++) { - Span firstPassColumn = this.GetColumnSpan(x).Slice(top); + // Span firstPassColumn = this.GetColumnSpan(x).Slice(top); + ref Vector4 firstPassColumnBase = ref this.GetColumnSpan(x)[top]; // Destination color components - Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(firstPassColumn); + Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(ref firstPassColumnBase); } Span targetRowSpan = destination.GetRowSpan(y); @@ -174,15 +175,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms tempRowSpan, this.conversionModifiers); - // ref Vector4 firstPassBaseRef = ref this.buffer.Span[y - top]; - Span firstPassSpan = this.transposedFirstPassBuffer.Span.Slice(y - this.currentWindow.Min); + // Span firstPassSpan = this.transposedFirstPassBuffer.Span.Slice(y - this.currentWindow.Min); + ref Vector4 firstPassBaseRef = ref this.transposedFirstPassBuffer.Span[y - this.currentWindow.Min]; for (int x = this.targetWorkingRect.Left; x < this.targetWorkingRect.Right; x++) { ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.targetOrigin.X); - firstPassSpan[x * this.workerHeight] = kernel.Convolve(tempRowSpan); - // Unsafe.Add(ref firstPassBaseRef, x * this.sourceRectangle.Height) = kernel.Convolve(tempRowSpan); + // firstPassSpan[x * this.workerHeight] = kernel.Convolve(tempRowSpan); + Unsafe.Add(ref firstPassBaseRef, x * this.workerHeight) = kernel.Convolve(tempRowSpan); } } } From 2168071e703a9b26f16161061e99eb7fa4cfc764 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 19 Apr 2019 23:07:32 +0200 Subject: [PATCH 079/223] moar unsafe optimization --- .../Processing/Processors/Transforms/Resize/ResizeWorker.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index 9b7d1d17c..7fe263880 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -123,10 +123,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int top = kernel.StartIndex - this.currentWindow.Min; + ref Vector4 fpBase = ref this.transposedFirstPassBuffer.Span[top]; + for (int x = 0; x < this.destWidth; x++) { // Span firstPassColumn = this.GetColumnSpan(x).Slice(top); - ref Vector4 firstPassColumnBase = ref this.GetColumnSpan(x)[top]; + // ref Vector4 firstPassColumnBase = ref this.GetColumnSpan(x)[top]; + ref Vector4 firstPassColumnBase = ref Unsafe.Add(ref fpBase, x * this.workerHeight); // Destination color components Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(ref firstPassColumnBase); From a7c5295107f66d36bc01a8b57127ad19ddb90a10 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 20 Apr 2019 00:08:29 +0200 Subject: [PATCH 080/223] benchmark WorkingBufferSizeHint effects --- .../ImageSharp.Benchmarks/Samplers/Resize.cs | 61 +++++++++++++------ .../Processors/Transforms/ResizeTests.cs | 18 ++++-- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs index 51f3a5653..cb2481dbf 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs @@ -4,6 +4,7 @@ using System; using System.Drawing; using System.Drawing.Drawing2D; +using System.Globalization; using BenchmarkDotNet.Attributes; @@ -23,15 +24,21 @@ namespace SixLabors.ImageSharp.Benchmarks private Bitmap sourceBitmap; - [Params(3032)] - public int SourceSize { get; set; } + [Params("3032-400")] + public virtual string SourceToDest { get; set; } + + protected int SourceSize { get; private set; } + + protected int DestSize { get; private set; } - [Params(400)] - public int DestSize { get; set; } [GlobalSetup] - public void Setup() + public virtual void Setup() { + string[] stuff = this.SourceToDest.Split('-'); + this.SourceSize = int.Parse(stuff[0], CultureInfo.InvariantCulture); + this.DestSize = int.Parse(stuff[1], CultureInfo.InvariantCulture); + this.sourceImage = new Image(this.Configuration, this.SourceSize, this.SourceSize); this.sourceBitmap = new Bitmap(this.SourceSize, this.SourceSize); } @@ -95,26 +102,44 @@ namespace SixLabors.ImageSharp.Benchmarks ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); } - // RESULTS (2019 April): + // RESULTS - 2019 April - ResizeWorker: // - // BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17134.648 (1803/April2018Update/Redstone4) + // BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17134.706 (1803/April2018Update/Redstone4) // Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores - // Frequency=2742192 Hz, Resolution=364.6718 ns, Timer=TSC - // .NET Core SDK=2.1.602 + // Frequency=2742189 Hz, Resolution=364.6722 ns, Timer=TSC + // .NET Core SDK=2.2.202 // [Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT - // Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3362.0 + // Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3394.0 // Core : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT // - // IterationCount=3 LaunchCount=1 WarmupCount=3 + // IterationCount=3 LaunchCount=1 WarmupCount=3 // - // Method | Job | Runtime | SourceSize | DestSize | Mean | Error | StdDev | Ratio | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | - // ----------------------------------------- |----- |-------- |----------- |--------- |----------:|----------:|----------:|------:|------------:|------------:|------------:|--------------------:| - // SystemDrawing | Clr | Clr | 3032 | 400 | 118.71 ms | 4.884 ms | 0.2677 ms | 1.00 | - | - | - | 2048 B | - // 'ImageSharp, MaxDegreeOfParallelism = 1' | Clr | Clr | 3032 | 400 | 94.55 ms | 16.160 ms | 0.8858 ms | 0.80 | - | - | - | 16384 B | - // | | | | | | | | | | | | | - // SystemDrawing | Core | Core | 3032 | 400 | 118.38 ms | 2.814 ms | 0.1542 ms | 1.00 | - | - | - | 96 B | - // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032 | 400 | 90.28 ms | 4.679 ms | 0.2565 ms | 0.76 | - | - | - | 15712 B | + // Method | Job | Runtime | SourceToDest | Mean | Error | StdDev | Ratio | RatioSD | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | + // ----------------------------------------- |----- |-------- |------------- |----------:|----------:|----------:|------:|--------:|------------:|------------:|------------:|--------------------:| + // SystemDrawing | Clr | Clr | 3032-400 | 120.11 ms | 1.435 ms | 0.0786 ms | 1.00 | 0.00 | - | - | - | 1638 B | + // 'ImageSharp, MaxDegreeOfParallelism = 1' | Clr | Clr | 3032-400 | 75.32 ms | 34.143 ms | 1.8715 ms | 0.63 | 0.02 | - | - | - | 16384 B | + // | | | | | | | | | | | | | + // SystemDrawing | Core | Core | 3032-400 | 120.33 ms | 6.669 ms | 0.3656 ms | 1.00 | 0.00 | - | - | - | 96 B | + // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032-400 | 88.56 ms | 1.864 ms | 0.1022 ms | 0.74 | 0.00 | - | - | - | 15568 B | + } + + /// + /// Is it worth to set a larger working buffer limit for resize? + /// Conclusion: It doesn't really have an effect. + /// + public class Resize_Bicubic_Rgba32_CompareWorkBufferSizes : Resize_Bicubic_Rgba32 + { + [Params(128, 512, 1024, 8 * 1024)] + public int WorkingBufferSizeHintInKilobytes { get; set; } + + [Params("3032-400", "4000-300")] + public override string SourceToDest { get; set; } + public override void Setup() + { + this.Configuration.WorkingBufferSizeHintInBytes = this.WorkingBufferSizeHintInKilobytes * 1024; + base.Setup(); + } } public class Resize_Bicubic_Bgra32 : ResizeBenchmarkBase diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index f4098aaf7..6bc2321de 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -42,9 +42,13 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.07F); - [Theory] - [WithTestPatternImages(4000, 4000, PixelTypes.Rgba32)] - public void LargeImage(TestImageProvider provider) + [Theory( + Skip = "Debug only, enable manually" + )] + [WithTestPatternImages(4000, 4000, PixelTypes.Rgba32, 300, 1024)] + [WithTestPatternImages(3032, 3032, PixelTypes.Rgba32, 400, 1024)] + [WithTestPatternImages(3032, 3032, PixelTypes.Rgba32, 400, 128)] + public void LargeImage(TestImageProvider provider, int destSize, int workingBufferSizeHintInKilobytes) where TPixel : struct, IPixel { if (!TestEnvironment.Is64BitProcess) @@ -52,7 +56,13 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms return; } - provider.RunValidatingProcessorTest(x => x.Resize(300, 300), appendPixelTypeToFileName: false); + provider.Configuration.WorkingBufferSizeHintInBytes = workingBufferSizeHintInKilobytes * 1024; + + using (var image = provider.GetImage()) + { + image.Mutate(x => x.Resize(destSize, destSize)); + image.DebugSave(provider, appendPixelTypeToFileName: false); + } } [Theory] From d882d911ef3b72176495633ee8925c10d66e1096 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 20 Apr 2019 00:36:26 +0200 Subject: [PATCH 081/223] memory profiling with Sandbox46 --- tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj | 2 +- tests/ImageSharp.Sandbox46/Program.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj index cb286cc28..6569dc002 100644 --- a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj +++ b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj @@ -1,7 +1,7 @@  Exe - net461 + net472 win7-x64 True false diff --git a/tests/ImageSharp.Sandbox46/Program.cs b/tests/ImageSharp.Sandbox46/Program.cs index 02d4f80c5..afe7eb04f 100644 --- a/tests/ImageSharp.Sandbox46/Program.cs +++ b/tests/ImageSharp.Sandbox46/Program.cs @@ -33,11 +33,11 @@ namespace SixLabors.ImageSharp.Sandbox46 /// public static void Main(string[] args) { - RunJpegColorProfilingTests(); + // RunJpegColorProfilingTests(); // RunDecodeJpegProfilingTests(); // RunToVector4ProfilingTest(); - // RunResizeProfilingTest(); + RunResizeProfilingTest(); Console.ReadLine(); } @@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Sandbox46 private static void RunResizeProfilingTest() { var test = new ResizeProfilingBenchmarks(new ConsoleOutput()); - test.ResizeBicubic(2000, 2000); + test.ResizeBicubic(4000, 4000); } private static void RunToVector4ProfilingTest() From 0c684abc7e9187eaff9d52057d3a18bbfc46c274 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 20 Apr 2019 01:21:15 +0200 Subject: [PATCH 082/223] add ResizeWorker.pptx --- .../Transforms/Resize/The ResizeWorker.pptx | Bin 0 -> 38674 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Transforms/Resize/The ResizeWorker.pptx diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/The ResizeWorker.pptx b/src/ImageSharp/Processing/Processors/Transforms/Resize/The ResizeWorker.pptx new file mode 100644 index 0000000000000000000000000000000000000000..063f72de84022037dcd5d44331b3fce6b12efe3c GIT binary patch literal 38674 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 Date: Sat, 20 Apr 2019 01:46:31 +0200 Subject: [PATCH 083/223] refine ResizeWorker.pptx --- ...he ResizeWorker.pptx => ResizeWorker.pptx} | Bin 38674 -> 45342 bytes 1 file changed, 0 insertions(+), 0 deletions(-) rename src/ImageSharp/Processing/Processors/Transforms/Resize/{The ResizeWorker.pptx => ResizeWorker.pptx} (59%) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/The ResizeWorker.pptx b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.pptx similarity index 59% rename from src/ImageSharp/Processing/Processors/Transforms/Resize/The ResizeWorker.pptx rename to src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.pptx index 063f72de84022037dcd5d44331b3fce6b12efe3c..66087ce5423736e5bcd615fd68cc75f0024778f8 100644 GIT binary patch delta 14372 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 M?{9MYkAF%32jo|;O;WGhM>VExE&;r;1(R_ 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 Date: Sat, 20 Apr 2019 02:15:38 +0200 Subject: [PATCH 084/223] xmldoc for ResizeWorker --- src/ImageSharp/Configuration.cs | 3 +-- .../Processors/Transforms/Resize/ResizeWorker.cs | 15 +++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index 7cb014563..4e8284c2c 100644 --- a/src/ImageSharp/Configuration.cs +++ b/src/ImageSharp/Configuration.cs @@ -10,7 +10,6 @@ using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.Memory; namespace SixLabors.ImageSharp @@ -108,7 +107,7 @@ namespace SixLabors.ImageSharp /// The default value is 1MB. /// /// - /// Currently only used by . + /// Currently only used by Resize. /// internal int WorkingBufferSizeHintInBytes { get; set; } = 1 * 1024 * 1024; diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index 7fe263880..00a8cfbf3 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -14,6 +14,13 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { + ///

+ /// Implements the resize algorithm using a sliding window of size + /// maximized by . + /// The height of the window is a multiple of the vertical kernel's maximum diameter. + /// When sliding the window, the contents of the bottom window band are copied to the new top band. + /// For more details, and visual explanation, see "ResizeWorker.pptx". + /// internal class ResizeWorker : IDisposable where TPixel : struct, IPixel { @@ -127,8 +134,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = 0; x < this.destWidth; x++) { - // Span firstPassColumn = this.GetColumnSpan(x).Slice(top); - // ref Vector4 firstPassColumnBase = ref this.GetColumnSpan(x)[top]; ref Vector4 firstPassColumnBase = ref Unsafe.Add(ref fpBase, x * this.workerHeight); // Destination color components @@ -141,12 +146,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private Span GetColumnSpan(int x) - { - return this.transposedFirstPassBuffer.GetRowSpan(x); - } - private void Slide() { int minY = this.currentWindow.Max - this.windowBandHeight; From d2e1a8d14c3e411c23f5a9cbec5ae0d968023b78 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 20 Apr 2019 02:48:20 +0200 Subject: [PATCH 085/223] update ResizeWorker.pptx [skip CI] --- .../Transforms/Resize/ResizeWorker.pptx | Bin 45342 -> 45638 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.pptx b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.pptx index 66087ce5423736e5bcd615fd68cc75f0024778f8..248959170b01291490b7ab8c89dc646d3c2cb936 100644 GIT binary patch delta 5686 zcmZ9QWl&t*mWG?gCBZv5!L{)~;|>7=!7UJ68wgI2(AbB2W5J zlgn^trsmH1v!4CFYwdmNRPD2>R`w>ae;ZiMkBLL#CLNp(1OQy0!NoDDVNQ!YBmpNZ zN7VFdYIcJ#sgSaY5rGJ$l6w4g<{~+dpM!!VB1bD;KN%U-RS!_NahCS3@BIYFg)f#Y ziFuwK*Q5UJD=ETF zdpGUCs~AG*k_g%3VMEWkg9&{~YZvmwUd-ABNtJxQ@gy`6TNFDL!~1?s!n1OHC66!W z$?}n6LgB%^aX?cRYaet*E?1D-p5zkuKuiJ;&ClPL$0}#;FMmr$!ou2vSFa{#c2|bu z;#2n2=o}$8_euGz*u>(z8030#4fa``wyG;HAy87ws4H#pM8skVF;kTA9Q5#uts*|u zOrzohiP`U&emQ>aJj{c+TrIO2Wx~eJOLQj&dC&vhKG?>-Z*uy2`*!Z_F|%W_NJOfn`PUoQ_b6!2_Irw9WwPRM%US zpB^1$AF1^5>(@D@^#MhwQW|7&ahIPXON}H`(thFfJA!c;pxnbG4>t)bRw@%$M@ri^ zp6g&)(ZIND@wSP3PWM!==hm2~Ipd7j3Nu#`M@w=Sl&vW!eU$CHiO z`f!l^OSn{Zk|P+dB9HZjbh*6HjR7XVnb002k<0D!Zz zJGYyIou!rAzXLzlM@NUB#!F61gXHbplU^^~B@cyZqdh>G8$96ZCA1-@sQ0c+A|RP4 zc6m{?7r2+NZhbx_{^<$k9I15}N$B~wgL@&sGJd}XqdB;vts0No=R<;KTs`^d*ETeg zCSd(LmLhk~e78G$BtJCjOX?OFIff1V`EE106(n14FLK&*Xt^Vm(7xD2ZT+-#*PXxE zLLmCCIVC4RYsnXW7!ztE2V&(LwYSa!rL}J-54>IEcvBSj7Tg674)pL#O|rAq2D~+6 zxyLUIRs=P7zS()u#GX1$eH+4J z{_A!PBRSsD^AK?Q5Q{vComh2X6_vQ4RHpq!O;zbmv06sGd^ErDaM(IBP`yhVDF!n~ zIB`mH9r$a%_;zV|`7T|P!*5sv$0pojB;nU`ZW7;7sWP?I`IUOc;Fe3W5dXtGQy+mh zG6+Q>~;L!f6K@C?OcCyeh7>=V(Hb(OuMq)F&)Gxmb^y`#j>f4Kt~Pp!da`~ zEb`)942OjUfwSBC`R7j}g$2-2lt8e37;xa$Eg>wZ@29ap&J1BQ)LxMPb4z|CSKX#% zQp|wVX6q;S6xH+J4V|a+F;)hMCVL9J!neipH4YgL&=$ucjlioI+D;~n_1iG!%q z_0R(7ln{cDtEzch20@4iykdTH;GyfI#}Q{;zA5<5QChf_$#b-Tvxbc?x|2xDA|a+t zCX-;d^mn&N``ZSe`LgA&wJo(e>zr1+Sp}UP=}`wgNEK!TPtRGRMiqzyWfrS1 zmY(r$szPb*N>B_t7=qKsknWJ=rlQ$6nkQ&HXE?}Ga%O+V;`=P#&uXu;E8!|kv3xl| zmshx1laM_7a$IXNigj>I-+7}{Jx$Z^6pJceh-|y^7NuXWZk5?(!<{-pu+qvG# zFTD9yEQHeHdiQ*ksPZ2|u(c2c*DzLu@JbSaD{fVvd&-9}s0rH;$OfFOwq5~!CDxAF z{myib_|DqTDeyZHQ_FfCvK3Y0upE4iH?oMjDPcKjRd0tX0NYpJQcE*E(cWJv;3`RB zhm1mi8R9XH^Z;6XQr(GwXHH4oAHlNg0Wrwfn3h*UGr{y#W#=<4msKdCH0%^a6~fGH zn$ZK{THrjdd|Cal-dFAfa1nmrhg)_ssPBDgJQoa&}`3_bQTS8E$ zCE~ab&fN_a10&bs>VTp4x|80<*MbQW(e!JmsDV}y2X$gTsoX_>$Ny^R(q0_E{@$F> z2cc&qhrUv~OxUY|ONRGJ(f3Cw-(;Ms!rs`fTo@|+aU93R=CYd>@>HArjHT0N1 zHQdfH#3OKB;6`cM`{AZu@+ZC7VIn*SWp*Tx8CpP;ofsFw(^ED@CN@ zaXS{%yD0VAJOx&^7o+@$gl!{wr)LT^4QLfKHs*Fo)r{WR?l!0Z`_B*t430(hu1H=4 z+TLMRQ}QX}%NP|^pA(vmvfxdRkFFNPaj~kkFjdOep%fVf*cPSp7}y8Go6~(*(F&pA z4bxhb(2A=ct~;}2oJ)-tG4clIih1GQv8S)otL$fldKi|V&FU`jqQ5W8uhwTDQo7k3 z$nX77k;FB5{o>>-AqChadqF>{KS(ol@=K2!U{Ymh#{771*47PWO2cg2>ZeTm5)`DW z4ZC#G-jnCe;%;cpp~0U(V*Q+3>7X^eI@nU{Jm%=Qw;gM{UEnjC`C%jbY|6GWnICjI zCbMcyFAn^C6feXFl0YG*uCp0>NlbNX52o(NL%*{xxm^ey13Q#xU|48wREF+&WWF44 zmF{Pv!saS5U2b7qwE>PuON#E>tR?w3z%Gj#ZWq+A+E0@E8_CEtriue@51@Hfcb2h%opjZ88S1cH(DopVx>Fn5NK zS2Apt(P$h4>HzIXQrFTqj&EZ4<02&#%u*dKqW!RR;OtpAtbVWVavSlL((V5m(D)yd{1Wl z!E2Ezjku@K-YVdwa^(lbYgEk-o`yZ&B*L%S>lNGaP@G=-Zp+4C`jn<^jnX4)f>(v5 z6>xbh>*wfyV|(OX*}U~#F1cWhK(PQfaX8?;8`)#YR9WAnZVKiLU0RMWwuVVdtVX#E z#xD!|LcW)J_1KoU=ygXEN-&2L#p4+Tx|nLxFod>k8k+yy3fnFGiK#HQur?21l17Jj zy~YZkHkA*5h04+&WQtD1{|s&}hXGzLC}DTCw=%8c_gxXST+8;F`T9!ql>0>N3O;^>-d z-qPC^h5=h_qJm#CxbjSGR&NfgAKp;sUhwRT4JF;!57Mb{&ravu@xqXZJfD14y@<$4 z*--4@MmUWDxr&_mP$dI^v2Ff@QKN$FSYozT36+5eGpk&u6RWdz4AQ<9gA4yNSvib< zhhs*m$;~wmV`o{(P9soUAX5-#by};U{LE?WBIH??kaxRPf|+MQ99B|o>LV;exF3ag z1KH{KA>wbI|6VRg0>hm5{T?3r509ne0AF4j`GTV&A)j1icDs(_m8mW6)&rXC-2~oI zNMrl?$bzTfc;uOU!nd0jm$HIke=w*C)l2#W& zsbdvVCb=h#yK`cIHn5K|W2?w)T_9_!8+LH;x8GqX000CY|f_CWW(S}Zu#8e35K1%l;{z9 ziar;jWEslUZ+9^0!I5hzQ>#G}S69efuPhy~YfD*Ftg#8YoQcVpQPdnJkhk#$%-Oy~ zs5f_F@=p#tMOQsiIn@Whj4)BDnr0R+C2%9#^O`J<210yjYBD=PA=__3lcn-v?$z+# z9iyG5Mu$mdp9}{?e5X~N8joTF^t%VDLn$=GRYxbsh69tK5_GAch1a~UG5?iANt{v! z%P1mQHO5jL5J@#ex;g604-r!Lb8R8arX!k*zHpilAL7ZTLh>7|AEcw71>lx+FF4p} z{iSp2@~JPLw3<%2;2EB3F*xg(6Lxet4kr*9e&;fwIe^CMI zDyV2A0616>3qFyxg5E7Feaco>lg)$z>vCG+!E3|+E{WAHq}I$u36z&lpdZXL2=23+ zD3c$MAsvd>|GHw=QL}cK8r?uVZx;ky@f%{eIhT{1+TMFh*`s_aEh-v|(dOUVS)^vy zLZeu2>2oe_j#8*I4Z+>oCzo;Ol7MaEp5UC8(D5Wzn^EnA_p!#xruQg>(jp8YZA=&9Q&yAZ{J!fU%OE=RnLv$v)3bJ?TFe? zTm;w8puHcm^rZc$&l{!h^I4a%BMeA^0q>pQnb43May;q!R z7IrBo4VgvNr=exL_~+8~$SMI7=Ca5#3>{1@xhyx0i&~gGRxcun8uvkYRh&0`^(I29!{K#rV$#ZL6sgkFm zcD(kss_GV6XqV;(oEQx_xgVFAq2G5rYb457>rhUJC@VvD0TQ|5*8!d|M_LsD3ar0t z{?xM)M5|tn!kZ!p(E)}~*dfLHtI6*x^={I)MN99an5Xwek!$5O9Bt!gtQMl1m>6D_ zHj;Vv2@=V^rvno%4eq;n6qkr!!xnr&8Y*2Nd(DyZ(p@z>krx}G zr&e3e_K1;>dOg)*=?7vaKZQR&T4yXx^-y)uakIQd9HFs9l3+9B+qZ21&!z+1HAn8V z7jQa367+}lFB-OWg!#-Uuo0(j9s>ERbR+An{_DiiJub?2oNpJ<+*VMF4a3 zGh1v{*T5jb?&^c+?c7nT;)-^MDI8a&yZ|Br5eh|K@fxfKcRkF-?PyNYWA?^Knx5EI zk#B(>#)=+D`G-HepK`=I>h+!_J2fXt)e59ik%HpKRG)b|CH0#+b=}0E-_~j^5jI7Qbz7)+h z$N49^f$hqx>-w}rPO~#s%Lg7Ba3YNj>Ub#anA3|37Bg@Cb=v+AFxl1v%1IsnmPY&+ zN|Qg<3;2%{m49Db6d)Kt0>A)ZJt}kn_SZSEMic)ogI(A{F3sPWWFAGB~nG0Ei8KM0)r^6#?A0hysYl_2j4& z3jqIe!2^p`fvQ4q>2g~5Nii2NN(>$-$^h3XB!Fv{Pyj*Fk4qYObO|>wLg5LQ9??zZ z3E4}zfvp-(IH`^f_b+7!PU<`@2OpgzgC~4Z#tjTKc|z+)l(u?0s^Jk2?cf`>Tu-mX zR89d@hCVuKKxSunLb*PW)8#QR!tpBvfPAh`_{Ih2F_#Md(isiDR*nONxIM`|j~No~ zPe@%U0F?81!uRg~nXK&jBu_nNsCzvjN0k6j_aoe_N*`$C{ira(*B=!NpC>f2M~6!x zxq2Mhm-}nXTYzK3{?Ny_D}%;!vFd9Pmw1JE>tZJ+|7o2Rx|zkM-0!c lCI$B7z`s`0Q$1a>$9`G&I0*jFLV5)JS2Y7hSK)tc^Dix5rEvfN delta 5364 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 Date: Sat, 20 Apr 2019 13:17:54 +0200 Subject: [PATCH 086/223] fix tests --- .../Processing/Processors/Convolution/DetectEdgesTest.cs | 1 + .../Processing/Processors/Transforms/ResizeTests.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs index de72f6d09..edb24d6f1 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs @@ -42,6 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution var bounds = new Rectangle(10, 10, size.Width / 2, size.Height / 2); ctx.DetectEdges(bounds); }, + comparer: ValidatorComparer, useReferenceOutputFrom: nameof(this.DetectEdges_InBox)); } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 6bc2321de..e3a43a652 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -131,6 +131,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms testOutputDetails: workingBufferLimitInRows, appendPixelTypeToFileName: false); image.CompareToReferenceOutput( + ImageComparer.TolerantPercentage(0.001f), provider, testOutputDetails: workingBufferLimitInRows, appendPixelTypeToFileName: false); From 026df1e4c88dec0512f8f0670fa2dee5ae59cd9e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 20 Apr 2019 13:21:15 +0200 Subject: [PATCH 087/223] fix license text in CopyBuffers benchmark --- tests/ImageSharp.Benchmarks/General/CopyBuffers.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs b/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs index 117cdba41..4c6458c30 100644 --- a/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs +++ b/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs @@ -1,7 +1,5 @@ -// -// Copyright (c) James Jackson-South and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -// using System; using System.Buffers; From a064cedd7d7fc4dcfee1372a3d8d08843efbd9a9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 22 Apr 2019 13:38:01 +0200 Subject: [PATCH 088/223] update travis.yml --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2515ca82a..551ea129b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,10 +3,10 @@ solution: ImageSharp.sln matrix: include: - - os: linux # Ubuntu 14.04 - dist: trusty + - os: linux # Ubuntu 16.04 + dist: xenial sudo: required - dotnet: 2.1.401 + dotnet: 2.1.603 mono: latest # - os: osx # OSX 10.11 # osx_image: xcode7.3.1 @@ -40,4 +40,4 @@ addons: notification_email: james_south@hotmail.com build_command_prepend: "dotnet restore" build_command: "dotnet build -c Release" - branch_pattern: coverity_scan \ No newline at end of file +branch_pattern: coverity_scan \ No newline at end of file From e306994711c7dfcde17bd1c3c9f54162ec901745 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 22 Apr 2019 13:44:10 +0200 Subject: [PATCH 089/223] I'm terrible copy-paster --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 551ea129b..6fd38484d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,4 +40,4 @@ addons: notification_email: james_south@hotmail.com build_command_prepend: "dotnet restore" build_command: "dotnet build -c Release" -branch_pattern: coverity_scan \ No newline at end of file + branch_pattern: coverity_scan \ No newline at end of file From 143033660dc202e0764aedf13d0c71a82ea33fd3 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 22 Apr 2019 14:22:04 +0200 Subject: [PATCH 090/223] extend the CopyBuffers benchmark --- .../General/CopyBuffers.cs | 199 +++++++++++------- 1 file changed, 124 insertions(+), 75 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs b/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs index 4c6458c30..32f1d10c7 100644 --- a/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs +++ b/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs @@ -88,12 +88,32 @@ namespace SixLabors.ImageSharp.Benchmarks.General this.sourceMemory.Span.CopyTo(this.destMemory.Span); } - [Benchmark(Description = "Unsafe.CopyBlock()")] - public unsafe void UnsafeCopyBlock() + [Benchmark(Description = "Unsafe.CopyBlock(ref)")] + public unsafe void UnsafeCopyBlockReferences() + { + Unsafe.CopyBlock(ref this.destArray[0], ref this.sourceArray[0], (uint)this.Count); + } + + [Benchmark(Description = "Unsafe.CopyBlock(ptr)")] + public unsafe void UnsafeCopyBlockPointers() + { + void* pinnedDestination = this.destHandle.Pointer; + void* pinnedSource = this.sourceHandle.Pointer; + Unsafe.CopyBlock(pinnedDestination, pinnedSource, (uint)this.Count); + } + + [Benchmark(Description = "Unsafe.CopyBlockUnaligned(ref)")] + public unsafe void UnsafeCopyBlockUnalignedReferences() + { + Unsafe.CopyBlockUnaligned(ref this.destArray[0], ref this.sourceArray[0], (uint)this.Count); + } + + [Benchmark(Description = "Unsafe.CopyBlockUnaligned(ptr)")] + public unsafe void UnsafeCopyBlockUnalignedPointers() { void* pinnedDestination = this.destHandle.Pointer; void* pinnedSource = this.sourceHandle.Pointer; - Unsafe.CopyBlock(pinnedSource, pinnedDestination, (uint)this.Count); + Unsafe.CopyBlockUnaligned(pinnedDestination, pinnedSource, (uint)this.Count); } // BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17134.706 (1803/April2018Update/Redstone4) @@ -106,77 +126,106 @@ namespace SixLabors.ImageSharp.Benchmarks.General // // IterationCount=3 LaunchCount=1 WarmupCount=3 // - // Method | Job | Runtime | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op | - // -------------------- |----- |-------- |------ |-----------:|-----------:|----------:|------:|--------:|------------:|------------:|------------:|--------------------:| - // Array.Copy() | Clr | Clr | 10 | 23.579 ns | 1.6836 ns | 0.0923 ns | 1.00 | 0.00 | - | - | - | - | - // Buffer.BlockCopy() | Clr | Clr | 10 | 11.796 ns | 0.5280 ns | 0.0289 ns | 0.50 | 0.00 | - | - | - | - | - // Buffer.MemoryCopy() | Clr | Clr | 10 | 3.206 ns | 8.1741 ns | 0.4480 ns | 0.14 | 0.02 | - | - | - | - | - // Marshal.Copy() | Clr | Clr | 10 | 15.577 ns | 2.0937 ns | 0.1148 ns | 0.66 | 0.00 | - | - | - | - | - // Span.CopyTo() | Clr | Clr | 10 | 32.287 ns | 2.4107 ns | 0.1321 ns | 1.37 | 0.01 | - | - | - | - | - // Unsafe.CopyBlock() | Clr | Clr | 10 | 3.266 ns | 0.3848 ns | 0.0211 ns | 0.14 | 0.00 | - | - | - | - | - // | | | | | | | | | | | | | - // Array.Copy() | Core | Core | 10 | 19.713 ns | 7.3026 ns | 0.4003 ns | 1.00 | 0.00 | - | - | - | - | - // Buffer.BlockCopy() | Core | Core | 10 | 7.332 ns | 0.5465 ns | 0.0300 ns | 0.37 | 0.01 | - | - | - | - | - // Buffer.MemoryCopy() | Core | Core | 10 | 2.476 ns | 0.3476 ns | 0.0191 ns | 0.13 | 0.00 | - | - | - | - | - // Marshal.Copy() | Core | Core | 10 | 15.575 ns | 0.1335 ns | 0.0073 ns | 0.79 | 0.02 | - | - | - | - | - // Span.CopyTo() | Core | Core | 10 | 25.321 ns | 2.3556 ns | 0.1291 ns | 1.28 | 0.02 | - | - | - | - | - // Unsafe.CopyBlock() | Core | Core | 10 | 2.204 ns | 0.1836 ns | 0.0101 ns | 0.11 | 0.00 | - | - | - | - | - // | | | | | | | | | | | | | - // Array.Copy() | Clr | Clr | 50 | 35.217 ns | 2.7642 ns | 0.1515 ns | 1.00 | 0.00 | - | - | - | - | - // Buffer.BlockCopy() | Clr | Clr | 50 | 24.224 ns | 0.8737 ns | 0.0479 ns | 0.69 | 0.00 | - | - | - | - | - // Buffer.MemoryCopy() | Clr | Clr | 50 | 3.827 ns | 4.8733 ns | 0.2671 ns | 0.11 | 0.01 | - | - | - | - | - // Marshal.Copy() | Clr | Clr | 50 | 28.103 ns | 1.3570 ns | 0.0744 ns | 0.80 | 0.00 | - | - | - | - | - // Span.CopyTo() | Clr | Clr | 50 | 34.137 ns | 2.9274 ns | 0.1605 ns | 0.97 | 0.01 | - | - | - | - | - // Unsafe.CopyBlock() | Clr | Clr | 50 | 4.999 ns | 0.1778 ns | 0.0097 ns | 0.14 | 0.00 | - | - | - | - | - // | | | | | | | | | | | | | - // Array.Copy() | Core | Core | 50 | 20.925 ns | 1.0219 ns | 0.0560 ns | 1.00 | 0.00 | - | - | - | - | - // Buffer.BlockCopy() | Core | Core | 50 | 8.083 ns | 0.2158 ns | 0.0118 ns | 0.39 | 0.00 | - | - | - | - | - // Buffer.MemoryCopy() | Core | Core | 50 | 2.919 ns | 0.2878 ns | 0.0158 ns | 0.14 | 0.00 | - | - | - | - | - // Marshal.Copy() | Core | Core | 50 | 16.663 ns | 0.2505 ns | 0.0137 ns | 0.80 | 0.00 | - | - | - | - | - // Span.CopyTo() | Core | Core | 50 | 26.940 ns | 11.5855 ns | 0.6350 ns | 1.29 | 0.03 | - | - | - | - | - // Unsafe.CopyBlock() | Core | Core | 50 | 1.940 ns | 0.6327 ns | 0.0347 ns | 0.09 | 0.00 | - | - | - | - | - // | | | | | | | | | | | | | - // Array.Copy() | Clr | Clr | 100 | 39.284 ns | 0.5647 ns | 0.0310 ns | 1.00 | 0.00 | - | - | - | - | - // Buffer.BlockCopy() | Clr | Clr | 100 | 28.930 ns | 0.6774 ns | 0.0371 ns | 0.74 | 0.00 | - | - | - | - | - // Buffer.MemoryCopy() | Clr | Clr | 100 | 5.859 ns | 2.7931 ns | 0.1531 ns | 0.15 | 0.00 | - | - | - | - | - // Marshal.Copy() | Clr | Clr | 100 | 36.529 ns | 0.9886 ns | 0.0542 ns | 0.93 | 0.00 | - | - | - | - | - // Span.CopyTo() | Clr | Clr | 100 | 36.152 ns | 1.5109 ns | 0.0828 ns | 0.92 | 0.00 | - | - | - | - | - // Unsafe.CopyBlock() | Clr | Clr | 100 | 9.317 ns | 0.4342 ns | 0.0238 ns | 0.24 | 0.00 | - | - | - | - | - // | | | | | | | | | | | | | - // Array.Copy() | Core | Core | 100 | 22.899 ns | 8.4066 ns | 0.4608 ns | 1.00 | 0.00 | - | - | - | - | - // Buffer.BlockCopy() | Core | Core | 100 | 10.696 ns | 0.8106 ns | 0.0444 ns | 0.47 | 0.01 | - | - | - | - | - // Buffer.MemoryCopy() | Core | Core | 100 | 4.102 ns | 0.9040 ns | 0.0496 ns | 0.18 | 0.01 | - | - | - | - | - // Marshal.Copy() | Core | Core | 100 | 17.917 ns | 2.6490 ns | 0.1452 ns | 0.78 | 0.01 | - | - | - | - | - // Span.CopyTo() | Core | Core | 100 | 28.247 ns | 0.6375 ns | 0.0349 ns | 1.23 | 0.03 | - | - | - | - | - // Unsafe.CopyBlock() | Core | Core | 100 | 3.611 ns | 0.4792 ns | 0.0263 ns | 0.16 | 0.00 | - | - | - | - | - // | | | | | | | | | | | | | - // Array.Copy() | Clr | Clr | 1000 | 48.907 ns | 4.4228 ns | 0.2424 ns | 1.00 | 0.00 | - | - | - | - | - // Buffer.BlockCopy() | Clr | Clr | 1000 | 40.653 ns | 1.4055 ns | 0.0770 ns | 0.83 | 0.01 | - | - | - | - | - // Buffer.MemoryCopy() | Clr | Clr | 1000 | 24.720 ns | 1.2651 ns | 0.0693 ns | 0.51 | 0.00 | - | - | - | - | - // Marshal.Copy() | Clr | Clr | 1000 | 42.336 ns | 2.2466 ns | 0.1231 ns | 0.87 | 0.00 | - | - | - | - | - // Span.CopyTo() | Clr | Clr | 1000 | 70.735 ns | 2.6215 ns | 0.1437 ns | 1.45 | 0.01 | - | - | - | - | - // Unsafe.CopyBlock() | Clr | Clr | 1000 | 44.520 ns | 0.9641 ns | 0.0528 ns | 0.91 | 0.00 | - | - | - | - | - // | | | | | | | | | | | | | - // Array.Copy() | Core | Core | 1000 | 46.286 ns | 11.6373 ns | 0.6379 ns | 1.00 | 0.00 | - | - | - | - | - // Buffer.BlockCopy() | Core | Core | 1000 | 34.243 ns | 7.2264 ns | 0.3961 ns | 0.74 | 0.01 | - | - | - | - | - // Buffer.MemoryCopy() | Core | Core | 1000 | 23.135 ns | 0.3153 ns | 0.0173 ns | 0.50 | 0.01 | - | - | - | - | - // Marshal.Copy() | Core | Core | 1000 | 46.219 ns | 1.2869 ns | 0.0705 ns | 1.00 | 0.01 | - | - | - | - | - // Span.CopyTo() | Core | Core | 1000 | 45.371 ns | 3.3581 ns | 0.1841 ns | 0.98 | 0.02 | - | - | - | - | - // Unsafe.CopyBlock() | Core | Core | 1000 | 29.347 ns | 1.1349 ns | 0.0622 ns | 0.63 | 0.01 | - | - | - | - | - // | | | | | | | | | | | | | - // Array.Copy() | Clr | Clr | 10000 | 218.445 ns | 9.2567 ns | 0.5074 ns | 1.00 | 0.00 | - | - | - | - | - // Buffer.BlockCopy() | Clr | Clr | 10000 | 209.610 ns | 6.7447 ns | 0.3697 ns | 0.96 | 0.00 | - | - | - | - | - // Buffer.MemoryCopy() | Clr | Clr | 10000 | 213.061 ns | 66.6490 ns | 3.6533 ns | 0.98 | 0.02 | - | - | - | - | - // Marshal.Copy() | Clr | Clr | 10000 | 214.426 ns | 27.7722 ns | 1.5223 ns | 0.98 | 0.00 | - | - | - | - | - // Span.CopyTo() | Clr | Clr | 10000 | 486.728 ns | 12.1537 ns | 0.6662 ns | 2.23 | 0.00 | - | - | - | - | - // Unsafe.CopyBlock() | Clr | Clr | 10000 | 452.973 ns | 25.1490 ns | 1.3785 ns | 2.07 | 0.00 | - | - | - | - | - // | | | | | | | | | | | | | - // Array.Copy() | Core | Core | 10000 | 203.365 ns | 3.2200 ns | 0.1765 ns | 1.00 | 0.00 | - | - | - | - | - // Buffer.BlockCopy() | Core | Core | 10000 | 193.319 ns | 8.3370 ns | 0.4570 ns | 0.95 | 0.00 | - | - | - | - | - // Buffer.MemoryCopy() | Core | Core | 10000 | 196.541 ns | 37.8056 ns | 2.0723 ns | 0.97 | 0.01 | - | - | - | - | - // Marshal.Copy() | Core | Core | 10000 | 206.454 ns | 3.7652 ns | 0.2064 ns | 1.02 | 0.00 | - | - | - | - | - // Span.CopyTo() | Core | Core | 10000 | 214.799 ns | 3.0667 ns | 0.1681 ns | 1.06 | 0.00 | - | - | - | - | - // Unsafe.CopyBlock() | Core | Core | 10000 | 134.428 ns | 2.6024 ns | 0.1426 ns | 0.66 | 0.00 | - | - | - | - | - + // | Method | Job | Runtime | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | + // |------------------------------- |----- |-------- |------ |-----------:|-----------:|----------:|------:|--------:|------:|------:|------:|----------:| + // | Array.Copy() | Clr | Clr | 10 | 23.636 ns | 2.5299 ns | 0.1387 ns | 1.00 | 0.00 | - | - | - | - | + // | Buffer.BlockCopy() | Clr | Clr | 10 | 11.420 ns | 2.3341 ns | 0.1279 ns | 0.48 | 0.01 | - | - | - | - | + // | Buffer.MemoryCopy() | Clr | Clr | 10 | 2.861 ns | 0.5059 ns | 0.0277 ns | 0.12 | 0.00 | - | - | - | - | + // | Marshal.Copy() | Clr | Clr | 10 | 14.870 ns | 2.4541 ns | 0.1345 ns | 0.63 | 0.01 | - | - | - | - | + // | Span.CopyTo() | Clr | Clr | 10 | 31.906 ns | 1.2213 ns | 0.0669 ns | 1.35 | 0.01 | - | - | - | - | + // | Unsafe.CopyBlock(ref) | Clr | Clr | 10 | 3.513 ns | 0.7392 ns | 0.0405 ns | 0.15 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlock(ptr) | Clr | Clr | 10 | 3.053 ns | 0.2010 ns | 0.0110 ns | 0.13 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ref) | Clr | Clr | 10 | 3.497 ns | 0.4911 ns | 0.0269 ns | 0.15 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ptr) | Clr | Clr | 10 | 3.109 ns | 0.5958 ns | 0.0327 ns | 0.13 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Array.Copy() | Core | Core | 10 | 19.709 ns | 2.1867 ns | 0.1199 ns | 1.00 | 0.00 | - | - | - | - | + // | Buffer.BlockCopy() | Core | Core | 10 | 7.377 ns | 1.1582 ns | 0.0635 ns | 0.37 | 0.01 | - | - | - | - | + // | Buffer.MemoryCopy() | Core | Core | 10 | 2.581 ns | 1.1607 ns | 0.0636 ns | 0.13 | 0.00 | - | - | - | - | + // | Marshal.Copy() | Core | Core | 10 | 15.197 ns | 2.8446 ns | 0.1559 ns | 0.77 | 0.01 | - | - | - | - | + // | Span.CopyTo() | Core | Core | 10 | 25.394 ns | 0.9782 ns | 0.0536 ns | 1.29 | 0.01 | - | - | - | - | + // | Unsafe.CopyBlock(ref) | Core | Core | 10 | 2.254 ns | 0.1590 ns | 0.0087 ns | 0.11 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlock(ptr) | Core | Core | 10 | 1.878 ns | 0.1035 ns | 0.0057 ns | 0.10 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ref) | Core | Core | 10 | 2.263 ns | 0.1383 ns | 0.0076 ns | 0.11 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ptr) | Core | Core | 10 | 1.877 ns | 0.0602 ns | 0.0033 ns | 0.10 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Array.Copy() | Clr | Clr | 50 | 35.068 ns | 5.9137 ns | 0.3242 ns | 1.00 | 0.00 | - | - | - | - | + // | Buffer.BlockCopy() | Clr | Clr | 50 | 23.299 ns | 2.3797 ns | 0.1304 ns | 0.66 | 0.01 | - | - | - | - | + // | Buffer.MemoryCopy() | Clr | Clr | 50 | 3.598 ns | 4.8536 ns | 0.2660 ns | 0.10 | 0.01 | - | - | - | - | + // | Marshal.Copy() | Clr | Clr | 50 | 27.720 ns | 4.6602 ns | 0.2554 ns | 0.79 | 0.01 | - | - | - | - | + // | Span.CopyTo() | Clr | Clr | 50 | 35.673 ns | 16.2972 ns | 0.8933 ns | 1.02 | 0.03 | - | - | - | - | + // | Unsafe.CopyBlock(ref) | Clr | Clr | 50 | 5.534 ns | 2.8119 ns | 0.1541 ns | 0.16 | 0.01 | - | - | - | - | + // | Unsafe.CopyBlock(ptr) | Clr | Clr | 50 | 4.511 ns | 0.9555 ns | 0.0524 ns | 0.13 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ref) | Clr | Clr | 50 | 5.613 ns | 1.6679 ns | 0.0914 ns | 0.16 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ptr) | Clr | Clr | 50 | 4.884 ns | 7.3153 ns | 0.4010 ns | 0.14 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Array.Copy() | Core | Core | 50 | 20.232 ns | 1.5720 ns | 0.0862 ns | 1.00 | 0.00 | - | - | - | - | + // | Buffer.BlockCopy() | Core | Core | 50 | 8.142 ns | 0.7860 ns | 0.0431 ns | 0.40 | 0.00 | - | - | - | - | + // | Buffer.MemoryCopy() | Core | Core | 50 | 2.962 ns | 0.0611 ns | 0.0033 ns | 0.15 | 0.00 | - | - | - | - | + // | Marshal.Copy() | Core | Core | 50 | 16.802 ns | 2.9686 ns | 0.1627 ns | 0.83 | 0.00 | - | - | - | - | + // | Span.CopyTo() | Core | Core | 50 | 26.571 ns | 0.9228 ns | 0.0506 ns | 1.31 | 0.01 | - | - | - | - | + // | Unsafe.CopyBlock(ref) | Core | Core | 50 | 2.219 ns | 0.7191 ns | 0.0394 ns | 0.11 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlock(ptr) | Core | Core | 50 | 1.751 ns | 0.1884 ns | 0.0103 ns | 0.09 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ref) | Core | Core | 50 | 2.177 ns | 0.4489 ns | 0.0246 ns | 0.11 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ptr) | Core | Core | 50 | 1.806 ns | 0.1063 ns | 0.0058 ns | 0.09 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Array.Copy() | Clr | Clr | 100 | 39.158 ns | 4.3068 ns | 0.2361 ns | 1.00 | 0.00 | - | - | - | - | + // | Buffer.BlockCopy() | Clr | Clr | 100 | 27.623 ns | 0.4611 ns | 0.0253 ns | 0.71 | 0.00 | - | - | - | - | + // | Buffer.MemoryCopy() | Clr | Clr | 100 | 5.018 ns | 0.5689 ns | 0.0312 ns | 0.13 | 0.00 | - | - | - | - | + // | Marshal.Copy() | Clr | Clr | 100 | 33.527 ns | 1.9019 ns | 0.1042 ns | 0.86 | 0.01 | - | - | - | - | + // | Span.CopyTo() | Clr | Clr | 100 | 35.604 ns | 2.7039 ns | 0.1482 ns | 0.91 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlock(ref) | Clr | Clr | 100 | 7.853 ns | 0.4925 ns | 0.0270 ns | 0.20 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlock(ptr) | Clr | Clr | 100 | 7.406 ns | 1.9733 ns | 0.1082 ns | 0.19 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ref) | Clr | Clr | 100 | 7.822 ns | 0.6837 ns | 0.0375 ns | 0.20 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ptr) | Clr | Clr | 100 | 7.392 ns | 1.2832 ns | 0.0703 ns | 0.19 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Array.Copy() | Core | Core | 100 | 22.909 ns | 2.9754 ns | 0.1631 ns | 1.00 | 0.00 | - | - | - | - | + // | Buffer.BlockCopy() | Core | Core | 100 | 10.687 ns | 1.1262 ns | 0.0617 ns | 0.47 | 0.00 | - | - | - | - | + // | Buffer.MemoryCopy() | Core | Core | 100 | 4.063 ns | 0.1607 ns | 0.0088 ns | 0.18 | 0.00 | - | - | - | - | + // | Marshal.Copy() | Core | Core | 100 | 18.067 ns | 4.0557 ns | 0.2223 ns | 0.79 | 0.01 | - | - | - | - | + // | Span.CopyTo() | Core | Core | 100 | 28.352 ns | 1.2762 ns | 0.0700 ns | 1.24 | 0.01 | - | - | - | - | + // | Unsafe.CopyBlock(ref) | Core | Core | 100 | 4.130 ns | 0.2013 ns | 0.0110 ns | 0.18 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlock(ptr) | Core | Core | 100 | 4.096 ns | 0.2460 ns | 0.0135 ns | 0.18 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ref) | Core | Core | 100 | 4.160 ns | 0.3174 ns | 0.0174 ns | 0.18 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ptr) | Core | Core | 100 | 3.480 ns | 1.1683 ns | 0.0640 ns | 0.15 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Array.Copy() | Clr | Clr | 1000 | 49.059 ns | 2.0729 ns | 0.1136 ns | 1.00 | 0.00 | - | - | - | - | + // | Buffer.BlockCopy() | Clr | Clr | 1000 | 38.270 ns | 23.6970 ns | 1.2989 ns | 0.78 | 0.03 | - | - | - | - | + // | Buffer.MemoryCopy() | Clr | Clr | 1000 | 27.599 ns | 6.8328 ns | 0.3745 ns | 0.56 | 0.01 | - | - | - | - | + // | Marshal.Copy() | Clr | Clr | 1000 | 42.752 ns | 5.1357 ns | 0.2815 ns | 0.87 | 0.01 | - | - | - | - | + // | Span.CopyTo() | Clr | Clr | 1000 | 69.983 ns | 2.1860 ns | 0.1198 ns | 1.43 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlock(ref) | Clr | Clr | 1000 | 44.822 ns | 0.1625 ns | 0.0089 ns | 0.91 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlock(ptr) | Clr | Clr | 1000 | 45.072 ns | 1.4053 ns | 0.0770 ns | 0.92 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ref) | Clr | Clr | 1000 | 45.306 ns | 5.2646 ns | 0.2886 ns | 0.92 | 0.01 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ptr) | Clr | Clr | 1000 | 44.813 ns | 0.9117 ns | 0.0500 ns | 0.91 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Array.Copy() | Core | Core | 1000 | 51.907 ns | 3.1827 ns | 0.1745 ns | 1.00 | 0.00 | - | - | - | - | + // | Buffer.BlockCopy() | Core | Core | 1000 | 40.700 ns | 3.1488 ns | 0.1726 ns | 0.78 | 0.00 | - | - | - | - | + // | Buffer.MemoryCopy() | Core | Core | 1000 | 23.711 ns | 1.3004 ns | 0.0713 ns | 0.46 | 0.00 | - | - | - | - | + // | Marshal.Copy() | Core | Core | 1000 | 42.586 ns | 2.5390 ns | 0.1392 ns | 0.82 | 0.00 | - | - | - | - | + // | Span.CopyTo() | Core | Core | 1000 | 44.109 ns | 4.5604 ns | 0.2500 ns | 0.85 | 0.01 | - | - | - | - | + // | Unsafe.CopyBlock(ref) | Core | Core | 1000 | 33.926 ns | 5.1633 ns | 0.2830 ns | 0.65 | 0.01 | - | - | - | - | + // | Unsafe.CopyBlock(ptr) | Core | Core | 1000 | 33.267 ns | 0.2708 ns | 0.0148 ns | 0.64 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ref) | Core | Core | 1000 | 34.018 ns | 2.3238 ns | 0.1274 ns | 0.66 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ptr) | Core | Core | 1000 | 33.667 ns | 2.1983 ns | 0.1205 ns | 0.65 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Array.Copy() | Clr | Clr | 10000 | 153.429 ns | 6.1735 ns | 0.3384 ns | 1.00 | 0.00 | - | - | - | - | + // | Buffer.BlockCopy() | Clr | Clr | 10000 | 201.373 ns | 4.3670 ns | 0.2394 ns | 1.31 | 0.00 | - | - | - | - | + // | Buffer.MemoryCopy() | Clr | Clr | 10000 | 211.768 ns | 71.3510 ns | 3.9110 ns | 1.38 | 0.02 | - | - | - | - | + // | Marshal.Copy() | Clr | Clr | 10000 | 215.299 ns | 17.2677 ns | 0.9465 ns | 1.40 | 0.01 | - | - | - | - | + // | Span.CopyTo() | Clr | Clr | 10000 | 486.325 ns | 32.4445 ns | 1.7784 ns | 3.17 | 0.01 | - | - | - | - | + // | Unsafe.CopyBlock(ref) | Clr | Clr | 10000 | 452.314 ns | 33.0593 ns | 1.8121 ns | 2.95 | 0.02 | - | - | - | - | + // | Unsafe.CopyBlock(ptr) | Clr | Clr | 10000 | 455.600 ns | 56.7534 ns | 3.1108 ns | 2.97 | 0.02 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ref) | Clr | Clr | 10000 | 452.279 ns | 8.6457 ns | 0.4739 ns | 2.95 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ptr) | Clr | Clr | 10000 | 453.146 ns | 12.3776 ns | 0.6785 ns | 2.95 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Array.Copy() | Core | Core | 10000 | 204.508 ns | 3.1652 ns | 0.1735 ns | 1.00 | 0.00 | - | - | - | - | + // | Buffer.BlockCopy() | Core | Core | 10000 | 193.345 ns | 1.3742 ns | 0.0753 ns | 0.95 | 0.00 | - | - | - | - | + // | Buffer.MemoryCopy() | Core | Core | 10000 | 196.978 ns | 18.3279 ns | 1.0046 ns | 0.96 | 0.01 | - | - | - | - | + // | Marshal.Copy() | Core | Core | 10000 | 206.878 ns | 6.9938 ns | 0.3834 ns | 1.01 | 0.00 | - | - | - | - | + // | Span.CopyTo() | Core | Core | 10000 | 215.733 ns | 15.4824 ns | 0.8486 ns | 1.05 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlock(ref) | Core | Core | 10000 | 186.894 ns | 8.7617 ns | 0.4803 ns | 0.91 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlock(ptr) | Core | Core | 10000 | 186.662 ns | 10.6059 ns | 0.5813 ns | 0.91 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ref) | Core | Core | 10000 | 187.489 ns | 13.1527 ns | 0.7209 ns | 0.92 | 0.00 | - | - | - | - | + // | Unsafe.CopyBlockUnaligned(ptr) | Core | Core | 10000 | 186.586 ns | 4.6274 ns | 0.2536 ns | 0.91 | 0.00 | - | - | - | - | } } \ No newline at end of file From a359b195f2a6b4c5b0b33796153340a7e8a9eacb Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 22 Apr 2019 15:52:54 +0200 Subject: [PATCH 091/223] use HashCode.Combine() --- src/ImageSharp/Memory/RowInterval.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/ImageSharp/Memory/RowInterval.cs b/src/ImageSharp/Memory/RowInterval.cs index 3ee7ae774..815918754 100644 --- a/src/ImageSharp/Memory/RowInterval.cs +++ b/src/ImageSharp/Memory/RowInterval.cs @@ -65,12 +65,6 @@ namespace SixLabors.ImageSharp.Memory return !ReferenceEquals(null, obj) && obj is RowInterval other && this.Equals(other); } - public override int GetHashCode() - { - unchecked - { - return (this.Min * 397) ^ this.Max; - } - } + public override int GetHashCode() => HashCode.Combine(this.Min, this.Max); } } \ No newline at end of file From af0d3dd0c7ccfae4cb0f6c4b7f291a188a9255bb Mon Sep 17 00:00:00 2001 From: Daniil Samoylov Date: Tue, 23 Apr 2019 16:26:17 +1200 Subject: [PATCH 092/223] Pass correct output size in ResizeMode.Min #892 (#893) --- .../Transforms/Resize/ResizeHelper.cs | 2 +- .../Transforms/ResizeHelperTests.cs | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs index 956e6b84e..ae7b112fc 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs @@ -296,7 +296,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Don't upscale if (width > sourceWidth || height > sourceHeight) { - return (new Size(sourceWidth, sourceWidth), new Rectangle(0, 0, sourceWidth, sourceHeight)); + return (new Size(sourceWidth, sourceHeight), new Rectangle(0, 0, sourceWidth, sourceHeight)); } // Find the shortest distance to go. diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeHelperTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeHelperTests.cs index b0d8ef653..b5ed64f7e 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeHelperTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeHelperTests.cs @@ -1,7 +1,9 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Transforms; +using SixLabors.Primitives; using Xunit; @@ -31,5 +33,24 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms int actualCount = ResizeHelper.CalculateResizeWorkerHeightInWindowBands(windowDiameter, width, sizeLimitHintInBytes); Assert.Equal(expectedCount, actualCount); } + + [Fact] + public void CalculateMinRectangleWhenSourceIsSmallerThanTarget() + { + var sourceSize = new Size(200, 100); + var target = new Size(400, 200); + + var actual = ResizeHelper.CalculateTargetLocationAndBounds( + sourceSize, + new ResizeOptions{ + Mode = ResizeMode.Min, + Size = target + }, + target.Width, + target.Height); + + Assert.Equal(sourceSize, actual.Item1); + Assert.Equal(new Rectangle(0, 0, sourceSize.Width, sourceSize.Height), actual.Item2); + } } } \ No newline at end of file From 0a78af5bdb5343b9bcc83e58205ba0c81b8f544e Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 25 Apr 2019 23:29:03 +1000 Subject: [PATCH 093/223] Cleanup General Convolution (#887) * Remove multiple premultiplication. * Use in DenseMatrix everywhere. * Make private * Dont convert vector row on first pass * Remove incorrectly assigned alpha. * Remove boxing. * Use correct min row. * Reorder parameters * Correctly handle alpha component. * Update tests * Use dedicated methods over branching. --- .../Processing/PatternBrush{TPixel}.cs | 9 +- .../Common/Helpers/DenseMatrixUtils.cs | 240 +++++++++++++++--- .../Convolution/BoxBlurProcessor.cs | 3 +- .../Convolution/Convolution2DProcessor.cs | 48 +++- .../Convolution/Convolution2PassProcessor.cs | 53 +++- .../Convolution/ConvolutionProcessor.cs | 50 +++- .../Convolution/EdgeDetector2DProcessor.cs | 5 +- .../EdgeDetectorCompassProcessor.cs | 20 +- .../Convolution/EdgeDetectorProcessor.cs | 6 +- .../Convolution/GaussianBlurProcessor.cs | 2 +- .../Convolution/GaussianSharpenProcessor.cs | 2 +- .../Processors/Dithering/ErrorDiffuserBase.cs | 2 +- .../Samplers/GaussianBlur.cs | 19 ++ .../DataWriter/IccDataWriter.MatrixTests.cs | 2 +- .../Processors/Convolution/BoxBlurTest.cs | 2 +- .../Processors/Convolution/DetectEdgesTest.cs | 2 + 16 files changed, 378 insertions(+), 87 deletions(-) create mode 100644 tests/ImageSharp.Benchmarks/Samplers/GaussianBlur.cs diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs index 46ed36f68..20161b517 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs @@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Processing /// Color of the fore. /// Color of the back. /// The pattern. - internal PatternBrush(TPixel foreColor, TPixel backColor, DenseMatrix pattern) + internal PatternBrush(TPixel foreColor, TPixel backColor, in DenseMatrix pattern) { var foreColorVector = foreColor.ToVector4(); var backColorVector = backColor.ToVector4(); @@ -93,10 +93,7 @@ namespace SixLabors.ImageSharp.Processing } /// - public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) - { - return new PatternBrushApplicator(source, this.pattern, this.patternVector, options); - } + public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) => new PatternBrushApplicator(source, this.pattern, this.patternVector, options); /// /// The pattern brush applicator. @@ -116,7 +113,7 @@ namespace SixLabors.ImageSharp.Processing /// The pattern. /// The patternVector. /// The options - public PatternBrushApplicator(ImageFrame source, DenseMatrix pattern, DenseMatrix patternVector, GraphicsOptions options) + public PatternBrushApplicator(ImageFrame source, in DenseMatrix pattern, DenseMatrix patternVector, GraphicsOptions options) : base(source, options) { this.pattern = pattern; diff --git a/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs b/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs index 2e700c9d6..427b24005 100644 --- a/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs +++ b/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs @@ -3,6 +3,7 @@ using System; using System.Numerics; +using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; @@ -11,83 +12,120 @@ namespace SixLabors.ImageSharp { /// /// Extension methods for . + /// TODO: One day rewrite all this to use SIMD intrinsics. There's a lot of scope for improvement. /// internal static class DenseMatrixUtils { /// - /// Computes the sum of vectors in weighted by the kernel weight values. + /// Computes the sum of vectors in the span referenced by weighted by the two kernel weight values. + /// Using this method the convolution filter is not applied to alpha in addition to the color channels. /// /// The pixel format. - /// The dense matrix. + /// The vertical dense matrix. + /// The horizontal dense matrix. /// The source frame. - /// The target row. + /// The target row base reference. /// The current row. /// The current column. + /// The minimum working area row. /// The maximum working area row. + /// The minimum working area column. /// The maximum working area column. - /// The column offset to apply to source sampling. - public static void Convolve( - in DenseMatrix matrix, + [MethodImpl(InliningOptions.ShortMethod)] + public static void Convolve2D3( + in DenseMatrix matrixY, + in DenseMatrix matrixX, Buffer2D sourcePixels, - Span targetRow, + ref Vector4 targetRowRef, int row, int column, + int minRow, int maxRow, - int maxColumn, - int offsetColumn) + int minColumn, + int maxColumn) where TPixel : struct, IPixel { Vector4 vector = default; - int matrixHeight = matrix.Rows; - int matrixWidth = matrix.Columns; - int radiusY = matrixHeight >> 1; - int radiusX = matrixWidth >> 1; - int sourceOffsetColumnBase = column + offsetColumn; - - for (int y = 0; y < matrixHeight; y++) - { - int offsetY = (row + y - radiusY).Clamp(0, maxRow); - Span sourceRowSpan = sourcePixels.GetRowSpan(offsetY); - for (int x = 0; x < matrixWidth; x++) - { - int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(offsetColumn, maxColumn); - var currentColor = sourceRowSpan[offsetX].ToVector4(); - Vector4Utils.Premultiply(ref currentColor); - - vector += matrix[y, x] * currentColor; - } - } + Convolve2DImpl( + in matrixY, + in matrixX, + sourcePixels, + row, + column, + minRow, + maxRow, + minColumn, + maxColumn, + ref vector); - ref Vector4 target = ref targetRow[column]; + ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); vector.W = target.W; + Vector4Utils.UnPremultiply(ref vector); target = vector; } /// - /// Computes the sum of vectors in weighted by the two kernel weight values. + /// Computes the sum of vectors in the span referenced by weighted by the two kernel weight values. + /// Using this method the convolution filter is applied to alpha in addition to the color channels. /// /// The pixel format. /// The vertical dense matrix. /// The horizontal dense matrix. /// The source frame. - /// The target row. + /// The target row base reference. /// The current row. /// The current column. + /// The minimum working area row. /// The maximum working area row. + /// The minimum working area column. /// The maximum working area column. - /// The column offset to apply to source sampling. - public static void Convolve2D( + [MethodImpl(InliningOptions.ShortMethod)] + public static void Convolve2D4( in DenseMatrix matrixY, in DenseMatrix matrixX, Buffer2D sourcePixels, - Span targetRow, + ref Vector4 targetRowRef, int row, int column, + int minRow, int maxRow, + int minColumn, + int maxColumn) + where TPixel : struct, IPixel + { + Vector4 vector = default; + + Convolve2DImpl( + in matrixY, + in matrixX, + sourcePixels, + row, + column, + minRow, + maxRow, + minColumn, + maxColumn, + ref vector); + + ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); + Vector4Utils.UnPremultiply(ref vector); + target = vector; + } + + [MethodImpl(InliningOptions.ShortMethod)] + public static void Convolve2DImpl( + in DenseMatrix matrixY, + in DenseMatrix matrixX, + Buffer2D sourcePixels, + int row, + int column, + int minRow, + int maxRow, + int minColumn, int maxColumn, - int offsetColumn) + ref Vector4 vector) where TPixel : struct, IPixel { Vector4 vectorY = default; @@ -96,16 +134,16 @@ namespace SixLabors.ImageSharp int matrixWidth = matrixY.Columns; int radiusY = matrixHeight >> 1; int radiusX = matrixWidth >> 1; - int sourceOffsetColumnBase = column + offsetColumn; + int sourceOffsetColumnBase = column + minColumn; for (int y = 0; y < matrixHeight; y++) { - int offsetY = (row + y - radiusY).Clamp(0, maxRow); + int offsetY = (row + y - radiusY).Clamp(minRow, maxRow); Span sourceRowSpan = sourcePixels.GetRowSpan(offsetY); for (int x = 0; x < matrixWidth; x++) { - int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(offsetColumn, maxColumn); + int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn); var currentColor = sourceRowSpan[offsetX].ToVector4(); Vector4Utils.Premultiply(ref currentColor); @@ -114,11 +152,133 @@ namespace SixLabors.ImageSharp } } - var vector = Vector4.SquareRoot((vectorX * vectorX) + (vectorY * vectorY)); - ref Vector4 target = ref targetRow[column]; + vector = Vector4.SquareRoot((vectorX * vectorX) + (vectorY * vectorY)); + } + + /// + /// Computes the sum of vectors in the span referenced by weighted by the kernel weight values. + /// Using this method the convolution filter is not applied to alpha in addition to the color channels. + /// + /// The pixel format. + /// The dense matrix. + /// The source frame. + /// The target row base reference. + /// The current row. + /// The current column. + /// The minimum working area row. + /// The maximum working area row. + /// The minimum working area column. + /// The maximum working area column. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Convolve3( + in DenseMatrix matrix, + Buffer2D sourcePixels, + ref Vector4 targetRowRef, + int row, + int column, + int minRow, + int maxRow, + int minColumn, + int maxColumn) + where TPixel : struct, IPixel + { + Vector4 vector = default; + + ConvolveImpl( + in matrix, + sourcePixels, + row, + column, + minRow, + maxRow, + minColumn, + maxColumn, + ref vector); + + ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); vector.W = target.W; + Vector4Utils.UnPremultiply(ref vector); target = vector; } + + /// + /// Computes the sum of vectors in the span referenced by weighted by the kernel weight values. + /// Using this method the convolution filter is applied to alpha in addition to the color channels. + /// + /// The pixel format. + /// The dense matrix. + /// The source frame. + /// The target row base reference. + /// The current row. + /// The current column. + /// The minimum working area row. + /// The maximum working area row. + /// The minimum working area column. + /// The maximum working area column. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Convolve4( + in DenseMatrix matrix, + Buffer2D sourcePixels, + ref Vector4 targetRowRef, + int row, + int column, + int minRow, + int maxRow, + int minColumn, + int maxColumn) + where TPixel : struct, IPixel + { + Vector4 vector = default; + + ConvolveImpl( + in matrix, + sourcePixels, + row, + column, + minRow, + maxRow, + minColumn, + maxColumn, + ref vector); + + ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); + Vector4Utils.UnPremultiply(ref vector); + target = vector; + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void ConvolveImpl( + in DenseMatrix matrix, + Buffer2D sourcePixels, + int row, + int column, + int minRow, + int maxRow, + int minColumn, + int maxColumn, + ref Vector4 vector) + where TPixel : struct, IPixel + { + int matrixHeight = matrix.Rows; + int matrixWidth = matrix.Columns; + int radiusY = matrixHeight >> 1; + int radiusX = matrixWidth >> 1; + int sourceOffsetColumnBase = column + minColumn; + + for (int y = 0; y < matrixHeight; y++) + { + int offsetY = (row + y - radiusY).Clamp(minRow, maxRow); + Span sourceRowSpan = sourcePixels.GetRowSpan(offsetY); + + for (int x = 0; x < matrixWidth; x++) + { + int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn); + var currentColor = sourceRowSpan[offsetX].ToVector4(); + Vector4Utils.Premultiply(ref currentColor); + vector += matrix[y, x] * currentColor; + } + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs index 644d6c9e1..3d5bdc42a 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs @@ -49,7 +49,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution public DenseMatrix KernelY { get; } /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) => new Convolution2PassProcessor(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration); + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + => new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply(source, sourceRectangle, configuration); /// /// Create a 1 dimensional Box kernel. diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs index 341a26ae8..633b50a9b 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs @@ -3,6 +3,7 @@ using System; using System.Numerics; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; @@ -23,11 +24,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// The horizontal gradient operator. /// The vertical gradient operator. - public Convolution2DProcessor(DenseMatrix kernelX, DenseMatrix kernelY) + /// Whether the convolution filter is applied to alpha as well as the color channels. + public Convolution2DProcessor(in DenseMatrix kernelX, in DenseMatrix kernelY, bool preserveAlpha) { Guard.IsTrue(kernelX.Size.Equals(kernelY.Size), $"{nameof(kernelX)} {nameof(kernelY)}", "Kernel sizes must be the same."); this.KernelX = kernelX; this.KernelY = kernelY; + this.PreserveAlpha = preserveAlpha; } /// @@ -40,6 +43,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// public DenseMatrix KernelY { get; } + /// + /// Gets a value indicating whether the convolution filter is applied to alpha as well as the color channels. + /// + public bool PreserveAlpha { get; } + /// protected override void OnFrameApply( ImageFrame source, @@ -48,6 +56,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { DenseMatrix matrixY = this.KernelY; DenseMatrix matrixX = this.KernelX; + bool preserveAlpha = this.PreserveAlpha; var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); int startY = interest.Y; @@ -71,18 +80,49 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { Span vectorSpan = vectorBuffer.Span; int length = vectorSpan.Length; + ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan); for (int y = rows.Min; y < rows.Max; y++) { Span targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX); PixelOperations.Instance.ToVector4(configuration, targetRowSpan.Slice(0, length), vectorSpan); - for (int x = 0; x < width; x++) + if (preserveAlpha) + { + for (int x = 0; x < width; x++) + { + DenseMatrixUtils.Convolve2D3( + in matrixY, + in matrixX, + source.PixelBuffer, + ref vectorSpanRef, + y, + x, + startY, + maxY, + startX, + maxX); + } + } + else { - DenseMatrixUtils.Convolve2D(in matrixY, in matrixX, source.PixelBuffer, vectorSpan, y, x, maxY, maxX, startX); + for (int x = 0; x < width; x++) + { + DenseMatrixUtils.Convolve2D4( + in matrixY, + in matrixX, + source.PixelBuffer, + ref vectorSpanRef, + y, + x, + startY, + maxY, + startX, + maxX); + } } - PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan.Slice(0, length), targetRowSpan); + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); } }); diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs index 9de467328..03268c9dd 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs @@ -3,7 +3,7 @@ using System; using System.Numerics; - +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; @@ -24,10 +24,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// The horizontal gradient operator. /// The vertical gradient operator. - public Convolution2PassProcessor(DenseMatrix kernelX, DenseMatrix kernelY) + /// Whether the convolution filter is applied to alpha as well as the color channels. + public Convolution2PassProcessor( + in DenseMatrix kernelX, + in DenseMatrix kernelY, + bool preserveAlpha) { this.KernelX = kernelX; this.KernelY = kernelY; + this.PreserveAlpha = preserveAlpha; } /// @@ -40,13 +45,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// public DenseMatrix KernelY { get; } + /// + /// Gets a value indicating whether the convolution filter is applied to alpha as well as the color channels. + /// + public bool PreserveAlpha { get; } + /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { using (Buffer2D firstPassPixels = configuration.MemoryAllocator.Allocate2D(source.Size())) { - source.CopyTo(firstPassPixels); - var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); this.ApplyConvolution(firstPassPixels, source.PixelBuffer, interest, this.KernelX, configuration); this.ApplyConvolution(source.PixelBuffer, firstPassPixels, interest, this.KernelY, configuration); @@ -72,6 +80,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution Configuration configuration) { DenseMatrix matrix = kernel; + bool preserveAlpha = this.PreserveAlpha; + int startY = sourceRectangle.Y; int endY = sourceRectangle.Bottom; int startX = sourceRectangle.X; @@ -89,18 +99,47 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { Span vectorSpan = vectorBuffer.Span; int length = vectorSpan.Length; + ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan); for (int y = rows.Min; y < rows.Max; y++) { Span targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX); PixelOperations.Instance.ToVector4(configuration, targetRowSpan.Slice(0, length), vectorSpan); - for (int x = 0; x < width; x++) + if (preserveAlpha) + { + for (int x = 0; x < width; x++) + { + DenseMatrixUtils.Convolve3( + in matrix, + sourcePixels, + ref vectorSpanRef, + y, + x, + startY, + maxY, + startX, + maxX); + } + } + else { - DenseMatrixUtils.Convolve(in matrix, sourcePixels, vectorSpan, y, x, maxY, maxX, startX); + for (int x = 0; x < width; x++) + { + DenseMatrixUtils.Convolve4( + in matrix, + sourcePixels, + ref vectorSpanRef, + y, + x, + startY, + maxY, + startX, + maxX); + } } - PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan.Slice(0, length), targetRowSpan); + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); } }); } diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs index 7e003cb03..6c3b9a46f 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs @@ -3,6 +3,7 @@ using System; using System.Numerics; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; @@ -22,17 +23,29 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Initializes a new instance of the class. /// /// The 2d gradient operator. - public ConvolutionProcessor(DenseMatrix kernelXY) => this.KernelXY = kernelXY; + /// Whether the convolution filter is applied to alpha as well as the color channels. + public ConvolutionProcessor(in DenseMatrix kernelXY, bool preserveAlpha) + { + this.KernelXY = kernelXY; + this.PreserveAlpha = preserveAlpha; + } /// /// Gets the 2d gradient operator. /// public DenseMatrix KernelXY { get; } + /// + /// Gets a value indicating whether the convolution filter is applied to alpha as well as the color channels. + /// + public bool PreserveAlpha { get; } + /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { DenseMatrix matrix = this.KernelXY; + bool preserveAlpha = this.PreserveAlpha; + var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); int startY = interest.Y; int endY = interest.Bottom; @@ -55,18 +68,47 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { Span vectorSpan = vectorBuffer.Span; int length = vectorSpan.Length; + ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan); for (int y = rows.Min; y < rows.Max; y++) { Span targetRowSpan = targetPixels.GetRowSpan(y).Slice(startX); PixelOperations.Instance.ToVector4(configuration, targetRowSpan.Slice(0, length), vectorSpan); - for (int x = 0; x < width; x++) + if (preserveAlpha) + { + for (int x = 0; x < width; x++) + { + DenseMatrixUtils.Convolve3( + in matrix, + source.PixelBuffer, + ref vectorSpanRef, + y, + x, + startY, + maxY, + startX, + maxX); + } + } + else { - DenseMatrixUtils.Convolve(in matrix, source.PixelBuffer, vectorSpan, y, x, maxY, maxX, startX); + for (int x = 0; x < width; x++) + { + DenseMatrixUtils.Convolve4( + in matrix, + source.PixelBuffer, + ref vectorSpanRef, + y, + x, + startY, + maxY, + startX, + maxX); + } } - PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan.Slice(0, length), targetRowSpan); + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); } }); diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs index 892771649..d2e9630dc 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// The horizontal gradient operator. /// The vertical gradient operator. /// Whether to convert the image to grayscale before performing edge detection. - protected EdgeDetector2DProcessor(DenseMatrix kernelX, DenseMatrix kernelY, bool grayscale) + protected EdgeDetector2DProcessor(in DenseMatrix kernelX, in DenseMatrix kernelY, bool grayscale) { Guard.IsTrue(kernelX.Size.Equals(kernelY.Size), $"{nameof(kernelX)} {nameof(kernelY)}", "Kernel sizes must be the same."); this.KernelX = kernelX; @@ -43,7 +43,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution public bool Grayscale { get; set; } /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) => new Convolution2DProcessor(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration); + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + => new Convolution2DProcessor(this.KernelX, this.KernelY, true).Apply(source, sourceRectangle, configuration); /// protected override void BeforeFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs index 4165cf024..73f92fae3 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs @@ -5,14 +5,12 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Threading.Tasks; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing.Processors.Filters; -using SixLabors.Memory; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Convolution @@ -28,10 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. - protected EdgeDetectorCompassProcessor(bool grayscale) - { - this.Grayscale = grayscale; - } + protected EdgeDetectorCompassProcessor(bool grayscale) => this.Grayscale = grayscale; /// /// Gets the North gradient operator @@ -104,7 +99,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution // we need a clean copy for each pass to start from using (ImageFrame cleanCopy = source.Clone()) { - new ConvolutionProcessor(kernels[0]).Apply(source, sourceRectangle, configuration); + new ConvolutionProcessor(kernels[0], true).Apply(source, sourceRectangle, configuration); if (kernels.Length == 1) { @@ -133,7 +128,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { using (ImageFrame pass = cleanCopy.Clone()) { - new ConvolutionProcessor(kernels[i]).Apply(pass, sourceRectangle, configuration); + new ConvolutionProcessor(kernels[i], true).Apply(pass, sourceRectangle, configuration); Buffer2D passPixels = pass.PixelBuffer; Buffer2D targetPixels = source.PixelBuffer; @@ -147,10 +142,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { int offsetY = y - shiftY; - ref TPixel passPixelsBase = - ref MemoryMarshal.GetReference(passPixels.GetRowSpan(offsetY)); - ref TPixel targetPixelsBase = - ref MemoryMarshal.GetReference(targetPixels.GetRowSpan(offsetY)); + ref TPixel passPixelsBase = ref MemoryMarshal.GetReference(passPixels.GetRowSpan(offsetY)); + ref TPixel targetPixelsBase = ref MemoryMarshal.GetReference(targetPixels.GetRowSpan(offsetY)); for (int x = minX; x < maxX; x++) { @@ -158,8 +151,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution // Grab the max components of the two pixels ref TPixel currentPassPixel = ref Unsafe.Add(ref passPixelsBase, offsetX); - ref TPixel currentTargetPixel = - ref Unsafe.Add(ref targetPixelsBase, offsetX); + ref TPixel currentTargetPixel = ref Unsafe.Add(ref targetPixelsBase, offsetX); var pixelValue = Vector4.Max( currentPassPixel.ToVector4(), diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs index 9173bc229..edc7ec4cc 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// The 2d gradient operator. /// Whether to convert the image to grayscale before performing edge detection. - protected EdgeDetectorProcessor(DenseMatrix kernelXY, bool grayscale) + protected EdgeDetectorProcessor(in DenseMatrix kernelXY, bool grayscale) { this.KernelXY = kernelXY; this.Grayscale = grayscale; @@ -45,8 +45,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - new ConvolutionProcessor(this.KernelXY).Apply(source, sourceRectangle, configuration); - } + => new ConvolutionProcessor(this.KernelXY, true).Apply(source, sourceRectangle, configuration); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs index b3bc15d39..0fc822d57 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs @@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - => new Convolution2PassProcessor(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration); + => new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply(source, sourceRectangle, configuration); /// /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs index 786bf7757..001471720 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - => new Convolution2PassProcessor(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration); + => new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply(source, sourceRectangle, configuration); /// /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs index 642da2f00..abf5dce18 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// /// The dithering matrix. /// The divisor. - internal ErrorDiffuserBase(DenseMatrix matrix, byte divisor) + internal ErrorDiffuserBase(in DenseMatrix matrix, byte divisor) { Guard.MustBeGreaterThan(divisor, 0, nameof(divisor)); diff --git a/tests/ImageSharp.Benchmarks/Samplers/GaussianBlur.cs b/tests/ImageSharp.Benchmarks/Samplers/GaussianBlur.cs new file mode 100644 index 000000000..47bd42a3c --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Samplers/GaussianBlur.cs @@ -0,0 +1,19 @@ +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; + +namespace SixLabors.ImageSharp.Benchmarks.Samplers +{ + [Config(typeof(Config.ShortClr))] + public class GaussianBlur + { + [Benchmark] + public void Blur() + { + using (var image = new Image(Configuration.Default, 400, 400, Rgba32.White)) + { + image.Mutate(c => c.GaussianBlur()); + } + } + } +} diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MatrixTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MatrixTests.cs index b43c17f79..088222222 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MatrixTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.MatrixTests.cs @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Icc [Theory] [MemberData(nameof(IccTestDataMatrix.Matrix2D_DenseMatrixTestData), MemberType = typeof(IccTestDataMatrix))] - internal void WriteMatrix2D_DenseMatrix(byte[] expected, int xCount, int yCount, bool isSingle, DenseMatrix data) + internal void WriteMatrix2D_DenseMatrix(byte[] expected, int xCount, int yCount, bool isSingle, in DenseMatrix data) { IccDataWriter writer = CreateWriter(); diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs index 0c40debad..1f0d12cf7 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs @@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution where TPixel : struct, IPixel { using (Image source = provider.GetImage()) - using (var image = source.Clone()) + using (Image image = source.Clone()) { var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs index edb24d6f1..b6a7741b3 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs @@ -12,6 +12,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { public class DetectEdgesTest : FileTestBase { + // I think our comparison is not accurate enough (nor can be) for RgbaVector. + // The image pixels are identical according to BeyondCompare. private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.0456F); public static readonly string[] CommonTestImages = { TestImages.Png.Bike }; From 2fcba54a3e134bc04f0218fe9e8b4af7b700c20a Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 26 Apr 2019 09:09:20 +1000 Subject: [PATCH 094/223] Faster Jpeg Huffman Decoding. (#894) * Read from underlying stream less often * Update benchmark dependencies * Experimental mango port Currently broken * Populate table, 64byte buffer Still broken. * Baseline, non RST works * 15/19 baseline tests pass now. * Optimize position change. * 18/19 pass * 19/19 baseline decoded * Can now decode all images. * Now faster and much cleaner. * Cleanup * Fix reader, update benchmarks * Update dependencies * Remove unused method * No need to clean initial buffer * Remove bounds check on ReadByte() * Refactor from feedback --- .../ImageSharp.Drawing.csproj | 2 +- .../Jpeg/Components/Decoder/FastACTable.cs | 61 - .../Components/Decoder/HuffmanScanBuffer.cs | 188 +++ .../Components/Decoder/HuffmanScanDecoder.cs | 694 +++++++++++ .../Jpeg/Components/Decoder/HuffmanTable.cs | 172 +-- .../Jpeg/Components/Decoder/ScanDecoder.cs | 1058 ----------------- src/ImageSharp/Formats/Jpeg/JpegConstants.cs | 31 +- .../Formats/Jpeg/JpegDecoderCore.cs | 10 +- .../Formats/Jpeg/JpegThrowHelper.cs | 3 - .../IO/DoubleBufferedStreamReader.cs | 115 +- src/ImageSharp/ImageSharp.csproj | 4 +- .../Codecs/Jpeg/DecodeJpegParseStreamOnly.cs | 17 + .../Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs | 25 +- .../Codecs/Jpeg/DoubleBufferedStreams.cs | 42 +- .../Codecs/MultiImageBenchmarkBase.cs | 2 +- .../ImageSharp.Benchmarks.csproj | 2 +- .../ImageSharp.Tests/ImageSharp.Tests.csproj | 4 +- 17 files changed, 1160 insertions(+), 1270 deletions(-) delete mode 100644 src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs create mode 100644 src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs create mode 100644 src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs delete mode 100644 src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 638687ae5..6f5cabb09 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -39,7 +39,7 @@ - + diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs deleted file mode 100644 index dc78a89dd..000000000 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTable.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Runtime.CompilerServices; - -namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder -{ - internal unsafe struct FastACTable - { - /// - /// Gets the lookahead array. - /// - public fixed short Lookahead[512]; - - /// - /// Derives a lookup table for fast AC entropy scan decoding. - /// This can happen multiple times during progressive decoding but always outside mcu loops. - /// - /// The AC Huffman table. - public void Derive(ref HuffmanTable huffmanTable) - { - const int FastBits = ScanDecoder.FastBits; - ref short fastACRef = ref this.Lookahead[0]; - ref byte huffmanLookaheadRef = ref huffmanTable.Lookahead[0]; - ref byte huffmanValuesRef = ref huffmanTable.Values[0]; - ref short huffmanSizesRef = ref huffmanTable.Sizes[0]; - - int i; - for (i = 0; i < (1 << FastBits); i++) - { - byte fast = Unsafe.Add(ref huffmanLookaheadRef, i); - Unsafe.Add(ref fastACRef, i) = 0; - - if (fast < byte.MaxValue) - { - int rs = Unsafe.Add(ref huffmanValuesRef, fast); - int run = (rs >> 4) & 15; - int magbits = rs & 15; - int len = Unsafe.Add(ref huffmanSizesRef, fast); - - if (magbits != 0 && len + magbits <= FastBits) - { - // Magnitude code followed by receive_extend code - int k = ((i << len) & ((1 << FastBits) - 1)) >> (FastBits - magbits); - int m = 1 << (magbits - 1); - if (k < m) - { - k += (int)((~0U << magbits) + 1); - } - - // If the result is small enough, we can fit it in fastAC table - if (k >= -128 && k <= 127) - { - Unsafe.Add(ref fastACRef, i) = (short)((k << 8) + (run << 4) + (len + magbits)); - } - } - } - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs new file mode 100644 index 000000000..72bfa3864 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs @@ -0,0 +1,188 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Runtime.CompilerServices; +using SixLabors.ImageSharp.IO; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder +{ + /// + /// Used to buffer and track the bits read from the Huffman entropy encoded data. + /// + internal struct HuffmanScanBuffer + { + private readonly DoubleBufferedStreamReader stream; + + // The entropy encoded code buffer. + private ulong data; + + // The number of valid bits left to read in the buffer. + private int remain; + + // Whether there is more data to pull from the stream for the current mcu. + private bool noMore; + + public HuffmanScanBuffer(DoubleBufferedStreamReader stream) + { + this.stream = stream; + this.data = 0ul; + this.remain = 0; + this.Marker = JpegConstants.Markers.XFF; + this.MarkerPosition = 0; + this.BadMarker = false; + this.noMore = false; + this.Eof = false; + } + + /// + /// Gets or sets the current, if any, marker in the input stream. + /// + public byte Marker { get; set; } + + /// + /// Gets or sets the opening position of an identified marker. + /// + public long MarkerPosition { get; set; } + + /// + /// Gets or sets a value indicating whether we have a bad marker, I.E. One that is not between RST0 and RST7 + /// + public bool BadMarker { get; set; } + + /// + /// Gets or sets a value indicating whether we have prematurely reached the end of the file. + /// + public bool Eof { get; set; } + + [MethodImpl(InliningOptions.ShortMethod)] + public void CheckBits() + { + if (this.remain < 16) + { + this.FillBuffer(); + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void Reset() + { + this.data = 0ul; + this.remain = 0; + this.Marker = JpegConstants.Markers.XFF; + this.MarkerPosition = 0; + this.BadMarker = false; + this.noMore = false; + this.Eof = false; + } + + [MethodImpl(InliningOptions.ShortMethod)] + public bool HasRestart() + { + byte m = this.Marker; + return m >= JpegConstants.Markers.RST0 && m <= JpegConstants.Markers.RST7; + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void FillBuffer() + { + // Attempt to load at least the minimum number of required bits into the buffer. + // We fail to do so only if we hit a marker or reach the end of the input stream. + this.remain += 48; + this.data = (this.data << 48) | this.GetBytes(); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public unsafe int DecodeHuffman(ref HuffmanTable h) + { + this.CheckBits(); + int v = this.PeekBits(JpegConstants.Huffman.LookupBits); + int symbol = h.LookaheadValue[v]; + int size = h.LookaheadSize[v]; + + if (size == JpegConstants.Huffman.SlowBits) + { + ulong x = this.data << (JpegConstants.Huffman.RegisterSize - this.remain); + while (x > h.MaxCode[size]) + { + size++; + } + + v = (int)(x >> (JpegConstants.Huffman.RegisterSize - size)); + symbol = h.Values[h.ValOffset[size] + v]; + } + + this.remain -= size; + + return symbol; + } + + [MethodImpl(InliningOptions.ShortMethod)] + public int Receive(int nbits) + { + this.CheckBits(); + return Extend(this.GetBits(nbits), nbits); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public int GetBits(int nbits) => (int)ExtractBits(this.data, this.remain -= nbits, nbits); + + [MethodImpl(InliningOptions.ShortMethod)] + public int PeekBits(int nbits) => (int)ExtractBits(this.data, this.remain - nbits, nbits); + + [MethodImpl(InliningOptions.ShortMethod)] + private static ulong ExtractBits(ulong value, int offset, int size) => (value >> offset) & (ulong)((1 << size) - 1); + + [MethodImpl(InliningOptions.ShortMethod)] + private static int Extend(int v, int nbits) => v - ((((v + v) >> nbits) - 1) & ((1 << nbits) - 1)); + + [MethodImpl(InliningOptions.ShortMethod)] + private ulong GetBytes() + { + ulong temp = 0; + for (int i = 0; i < 6; i++) + { + int b = this.noMore ? 0 : this.stream.ReadByte(); + + if (b == -1) + { + // We've encountered the end of the file stream which means there's no EOI marker in the image + // or the SOS marker has the wrong dimensions set. + this.Eof = true; + b = 0; + } + + // Found a marker. + if (b == JpegConstants.Markers.XFF) + { + this.MarkerPosition = this.stream.Position - 1; + int c = this.stream.ReadByte(); + while (c == JpegConstants.Markers.XFF) + { + c = this.stream.ReadByte(); + + if (c == -1) + { + this.Eof = true; + c = 0; + break; + } + } + + if (c != 0) + { + this.Marker = (byte)c; + this.noMore = true; + if (!this.HasRestart()) + { + this.BadMarker = true; + } + } + } + + temp = (temp << 8) | (ulong)(long)b; + } + + return temp; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs new file mode 100644 index 000000000..76fea9297 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs @@ -0,0 +1,694 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using SixLabors.ImageSharp.IO; +using SixLabors.ImageSharp.Memory; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder +{ + /// + /// Decodes the Huffman encoded spectral scan. + /// Originally ported from + /// with additional fixes for both performance and common encoding errors. + /// + internal class HuffmanScanDecoder + { + private readonly JpegFrame frame; + private readonly HuffmanTable[] dcHuffmanTables; + private readonly HuffmanTable[] acHuffmanTables; + private readonly DoubleBufferedStreamReader stream; + private readonly JpegComponent[] components; + + // The restart interval. + private readonly int restartInterval; + + // The number of interleaved components. + private readonly int componentsLength; + + // The spectral selection start. + private readonly int spectralStart; + + // The spectral selection end. + private readonly int spectralEnd; + + // The successive approximation high bit end. + private readonly int successiveHigh; + + // The successive approximation low bit end. + private readonly int successiveLow; + + // How many mcu's are left to do. + private int todo; + + // The End-Of-Block countdown for ending the sequence prematurely when the remaining coefficients are zero. + private int eobrun; + + // The unzig data. + private ZigZag dctZigZag; + + private HuffmanScanBuffer scanBuffer; + + /// + /// Initializes a new instance of the class. + /// + /// The input stream. + /// The image frame. + /// The DC Huffman tables. + /// The AC Huffman tables. + /// The length of the components. Different to the array length. + /// The reset interval. + /// The spectral selection start. + /// The spectral selection end. + /// The successive approximation bit high end. + /// The successive approximation bit low end. + public HuffmanScanDecoder( + DoubleBufferedStreamReader stream, + JpegFrame frame, + HuffmanTable[] dcHuffmanTables, + HuffmanTable[] acHuffmanTables, + int componentsLength, + int restartInterval, + int spectralStart, + int spectralEnd, + int successiveHigh, + int successiveLow) + { + this.dctZigZag = ZigZag.CreateUnzigTable(); + this.stream = stream; + this.scanBuffer = new HuffmanScanBuffer(stream); + this.frame = frame; + this.dcHuffmanTables = dcHuffmanTables; + this.acHuffmanTables = acHuffmanTables; + this.components = frame.Components; + this.componentsLength = componentsLength; + this.restartInterval = restartInterval; + this.todo = restartInterval; + this.spectralStart = spectralStart; + this.spectralEnd = spectralEnd; + this.successiveHigh = successiveHigh; + this.successiveLow = successiveLow; + } + + /// + /// Decodes the entropy coded data. + /// + public void ParseEntropyCodedData() + { + if (!this.frame.Progressive) + { + this.ParseBaselineData(); + } + else + { + this.ParseProgressiveData(); + } + + if (this.scanBuffer.BadMarker) + { + this.stream.Position = this.scanBuffer.MarkerPosition; + } + } + + private void ParseBaselineData() + { + if (this.componentsLength == 1) + { + this.ParseBaselineDataNonInterleaved(); + } + else + { + this.ParseBaselineDataInterleaved(); + } + } + + private unsafe void ParseBaselineDataInterleaved() + { + // Interleaved + int mcu = 0; + int mcusPerColumn = this.frame.McusPerColumn; + int mcusPerLine = this.frame.McusPerLine; + + // Pre-derive the huffman table to avoid in-loop checks. + for (int i = 0; i < this.componentsLength; i++) + { + int order = this.frame.ComponentOrder[i]; + JpegComponent component = this.components[order]; + + ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; + ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; + dcHuffmanTable.Configure(); + acHuffmanTable.Configure(); + } + + for (int j = 0; j < mcusPerColumn; j++) + { + for (int i = 0; i < mcusPerLine; i++) + { + // Scan an interleaved mcu... process components in order + int mcuRow = mcu / mcusPerLine; + int mcuCol = mcu % mcusPerLine; + for (int k = 0; k < this.componentsLength; k++) + { + int order = this.frame.ComponentOrder[k]; + JpegComponent component = this.components[order]; + + ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; + ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; + + int h = component.HorizontalSamplingFactor; + int v = component.VerticalSamplingFactor; + + // Scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (int y = 0; y < v; y++) + { + int blockRow = (mcuRow * v) + y; + Span blockSpan = component.SpectralBlocks.GetRowSpan(blockRow); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); + + for (int x = 0; x < h; x++) + { + int blockCol = (mcuCol * h) + x; + + this.DecodeBlockBaseline( + component, + ref Unsafe.Add(ref blockRef, blockCol), + ref dcHuffmanTable, + ref acHuffmanTable); + } + } + } + + // After all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + mcu++; + this.HandleRestart(); + } + } + } + + private unsafe void ParseBaselineDataNonInterleaved() + { + JpegComponent component = this.components[this.frame.ComponentOrder[0]]; + + int w = component.WidthInBlocks; + int h = component.HeightInBlocks; + + ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; + ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; + dcHuffmanTable.Configure(); + acHuffmanTable.Configure(); + + int mcu = 0; + for (int j = 0; j < h; j++) + { + Span blockSpan = component.SpectralBlocks.GetRowSpan(j); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); + + for (int i = 0; i < w; i++) + { + this.DecodeBlockBaseline( + component, + ref Unsafe.Add(ref blockRef, i), + ref dcHuffmanTable, + ref acHuffmanTable); + + // Every data block is an MCU, so countdown the restart interval + mcu++; + + this.HandleRestart(); + } + } + } + + private void CheckProgressiveData() + { + // Validate successive scan parameters. + // Logic has been adapted from libjpeg. + // See Table B.3 – Scan header parameter size and values. itu-t81.pdf + bool invalid = false; + if (this.spectralStart == 0) + { + if (this.spectralEnd != 0) + { + invalid = true; + } + } + else + { + // Need not check Ss/Se < 0 since they came from unsigned bytes. + if (this.spectralEnd < this.spectralStart || this.spectralEnd > 63) + { + invalid = true; + } + + // AC scans may have only one component. + if (this.componentsLength != 1) + { + invalid = true; + } + } + + if (this.successiveHigh != 0) + { + // Successive approximation refinement scan: must have Al = Ah-1. + if (this.successiveHigh - 1 != this.successiveLow) + { + invalid = true; + } + } + + // TODO: How does this affect 12bit jpegs. + // According to libjpeg the range covers 8bit only? + if (this.successiveLow > 13) + { + invalid = true; + } + + if (invalid) + { + JpegThrowHelper.ThrowBadProgressiveScan(this.spectralStart, this.spectralEnd, this.successiveHigh, this.successiveLow); + } + } + + private void ParseProgressiveData() + { + this.CheckProgressiveData(); + + if (this.componentsLength == 1) + { + this.ParseProgressiveDataNonInterleaved(); + } + else + { + this.ParseProgressiveDataInterleaved(); + } + } + + private void ParseProgressiveDataInterleaved() + { + // Interleaved + int mcu = 0; + int mcusPerColumn = this.frame.McusPerColumn; + int mcusPerLine = this.frame.McusPerLine; + + // Pre-derive the huffman table to avoid in-loop checks. + for (int k = 0; k < this.componentsLength; k++) + { + int order = this.frame.ComponentOrder[k]; + JpegComponent component = this.components[order]; + ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; + dcHuffmanTable.Configure(); + } + + for (int j = 0; j < mcusPerColumn; j++) + { + for (int i = 0; i < mcusPerLine; i++) + { + // Scan an interleaved mcu... process components in order + int mcuRow = mcu / mcusPerLine; + int mcuCol = mcu % mcusPerLine; + for (int k = 0; k < this.componentsLength; k++) + { + int order = this.frame.ComponentOrder[k]; + JpegComponent component = this.components[order]; + ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; + ref HuffmanScanBuffer buffer = ref this.scanBuffer; + + int h = component.HorizontalSamplingFactor; + int v = component.VerticalSamplingFactor; + + // Scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (int y = 0; y < v; y++) + { + int blockRow = (mcuRow * v) + y; + Span blockSpan = component.SpectralBlocks.GetRowSpan(blockRow); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); + + for (int x = 0; x < h; x++) + { + if (buffer.Eof) + { + return; + } + + int blockCol = (mcuCol * h) + x; + + this.DecodeBlockProgressiveDC( + component, + ref Unsafe.Add(ref blockRef, blockCol), + ref dcHuffmanTable); + } + } + } + + // After all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + mcu++; + this.HandleRestart(); + } + } + } + + private unsafe void ParseProgressiveDataNonInterleaved() + { + JpegComponent component = this.components[this.frame.ComponentOrder[0]]; + ref HuffmanScanBuffer buffer = ref this.scanBuffer; + + int w = component.WidthInBlocks; + int h = component.HeightInBlocks; + + if (this.spectralStart == 0) + { + ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; + dcHuffmanTable.Configure(); + + int mcu = 0; + for (int j = 0; j < h; j++) + { + Span blockSpan = component.SpectralBlocks.GetRowSpan(j); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); + + for (int i = 0; i < w; i++) + { + if (buffer.Eof) + { + return; + } + + this.DecodeBlockProgressiveDC( + component, + ref Unsafe.Add(ref blockRef, i), + ref dcHuffmanTable); + + // Every data block is an MCU, so countdown the restart interval + mcu++; + this.HandleRestart(); + } + } + } + else + { + ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; + acHuffmanTable.Configure(); + + int mcu = 0; + for (int j = 0; j < h; j++) + { + Span blockSpan = component.SpectralBlocks.GetRowSpan(j); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); + + for (int i = 0; i < w; i++) + { + if (buffer.Eof) + { + return; + } + + this.DecodeBlockProgressiveAC( + ref Unsafe.Add(ref blockRef, i), + ref acHuffmanTable); + + // Every data block is an MCU, so countdown the restart interval + mcu++; + this.HandleRestart(); + } + } + } + } + + private void DecodeBlockBaseline( + JpegComponent component, + ref Block8x8 block, + ref HuffmanTable dcTable, + ref HuffmanTable acTable) + { + ref short blockDataRef = ref Unsafe.As(ref block); + ref HuffmanScanBuffer buffer = ref this.scanBuffer; + ref ZigZag zigzag = ref this.dctZigZag; + + // DC + int t = buffer.DecodeHuffman(ref dcTable); + if (t != 0) + { + t = buffer.Receive(t); + } + + t += component.DcPredictor; + component.DcPredictor = t; + blockDataRef = (short)t; + + // AC + for (int i = 1; i < 64;) + { + int s = buffer.DecodeHuffman(ref acTable); + + int r = s >> 4; + s &= 15; + + if (s != 0) + { + i += r; + s = buffer.Receive(s); + Unsafe.Add(ref blockDataRef, zigzag[i++]) = (short)s; + } + else + { + if (r == 0) + { + break; + } + + i += 16; + } + } + } + + private void DecodeBlockProgressiveDC(JpegComponent component, ref Block8x8 block, ref HuffmanTable dcTable) + { + ref short blockDataRef = ref Unsafe.As(ref block); + ref HuffmanScanBuffer buffer = ref this.scanBuffer; + + if (this.successiveHigh == 0) + { + // First scan for DC coefficient, must be first + int s = buffer.DecodeHuffman(ref dcTable); + if (s != 0) + { + s = buffer.Receive(s); + } + + s += component.DcPredictor; + component.DcPredictor = s; + blockDataRef = (short)(s << this.successiveLow); + } + else + { + // Refinement scan for DC coefficient + buffer.CheckBits(); + blockDataRef |= (short)(buffer.GetBits(1) << this.successiveLow); + } + } + + private void DecodeBlockProgressiveAC(ref Block8x8 block, ref HuffmanTable acTable) + { + ref short blockDataRef = ref Unsafe.As(ref block); + if (this.successiveHigh == 0) + { + // MCU decoding for AC initial scan (either spectral selection, + // or first pass of successive approximation). + if (this.eobrun != 0) + { + --this.eobrun; + return; + } + + ref HuffmanScanBuffer buffer = ref this.scanBuffer; + ref ZigZag zigzag = ref this.dctZigZag; + int start = this.spectralStart; + int end = this.spectralEnd; + int low = this.successiveLow; + + for (int i = start; i <= end; ++i) + { + int s = buffer.DecodeHuffman(ref acTable); + int r = s >> 4; + s &= 15; + + i += r; + + if (s != 0) + { + s = buffer.Receive(s); + Unsafe.Add(ref blockDataRef, zigzag[i]) = (short)(s << low); + } + else + { + if (r != 15) + { + this.eobrun = 1 << r; + if (r != 0) + { + buffer.CheckBits(); + this.eobrun += buffer.GetBits(r); + } + + --this.eobrun; + break; + } + } + } + } + else + { + // Refinement scan for these AC coefficients + this.DecodeBlockProgressiveACRefined(ref blockDataRef, ref acTable); + } + } + + private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref HuffmanTable acTable) + { + // Refinement scan for these AC coefficients + ref HuffmanScanBuffer buffer = ref this.scanBuffer; + ref ZigZag zigzag = ref this.dctZigZag; + int start = this.spectralStart; + int end = this.spectralEnd; + + int p1 = 1 << this.successiveLow; + int m1 = (-1) << this.successiveLow; + + int k = start; + + if (this.eobrun == 0) + { + for (; k <= end; k++) + { + int s = buffer.DecodeHuffman(ref acTable); + int r = s >> 4; + s &= 15; + + if (s != 0) + { + buffer.CheckBits(); + if (buffer.GetBits(1) != 0) + { + s = p1; + } + else + { + s = m1; + } + } + else + { + if (r != 15) + { + this.eobrun = 1 << r; + + if (r != 0) + { + buffer.CheckBits(); + this.eobrun += buffer.GetBits(r); + } + + break; + } + } + + do + { + ref short coef = ref Unsafe.Add(ref blockDataRef, zigzag[k]); + if (coef != 0) + { + buffer.CheckBits(); + if (buffer.GetBits(1) != 0) + { + if ((coef & p1) == 0) + { + coef += (short)(coef >= 0 ? p1 : m1); + } + } + } + else + { + if (--r < 0) + { + break; + } + } + + k++; + } + while (k <= end); + + if ((s != 0) && (k < 64)) + { + Unsafe.Add(ref blockDataRef, zigzag[k]) = (short)s; + } + } + } + + if (this.eobrun > 0) + { + for (; k <= end; k++) + { + ref short coef = ref Unsafe.Add(ref blockDataRef, zigzag[k]); + + if (coef != 0) + { + buffer.CheckBits(); + if (buffer.GetBits(1) != 0) + { + if ((coef & p1) == 0) + { + coef += (short)(coef >= 0 ? p1 : m1); + } + } + } + } + + --this.eobrun; + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + private void Reset() + { + for (int i = 0; i < this.components.Length; i++) + { + this.components[i].DcPredictor = 0; + } + + this.eobrun = 0; + this.scanBuffer.Reset(); + } + + [MethodImpl(InliningOptions.ShortMethod)] + private bool HandleRestart() + { + if (this.restartInterval > 0 && (--this.todo) == 0) + { + this.todo = this.restartInterval; + + if (this.scanBuffer.HasRestart()) + { + this.Reset(); + return true; + } + + if (this.scanBuffer.Marker != JpegConstants.Markers.XFF) + { + this.stream.Position = this.scanBuffer.MarkerPosition; + this.Reset(); + return true; + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs index 7e025e271..21ed5018f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs @@ -2,53 +2,60 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Buffers; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - -using SixLabors.ImageSharp.Memory; using SixLabors.Memory; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { /// - /// Represents a Huffman Table + /// Represents a Huffman coding table containing basic coding data plus tables for accellerated computation. /// [StructLayout(LayoutKind.Sequential)] internal unsafe struct HuffmanTable { - private bool isDerived; - private readonly MemoryAllocator memoryAllocator; + private bool isConfigured; -#pragma warning disable IDE0044 // Add readonly modifier - private fixed byte codeLengths[17]; -#pragma warning restore IDE0044 // Add readonly modifier + /// + /// Derived from the DHT marker. Sizes[k] = # of symbols with codes of length k bits; Sizes[0] is unused. + /// + public fixed byte Sizes[17]; /// - /// Gets the max code array. + /// Derived from the DHT marker. Contains the symbols, in order of incremental code length. /// - public fixed uint MaxCode[18]; + public fixed byte Values[256]; /// - /// Gets the value offset array. + /// Contains the largest code of length k (0 if none). MaxCode[17] is a sentinel to + /// ensure terminates. /// - public fixed int ValOffset[18]; + public fixed ulong MaxCode[18]; /// - /// Gets the huffman value array. + /// Values[] offset for codes of length k ValOffset[k] = Values[] index of 1st symbol of code length + /// k, less the smallest code of length k; so given a code of length k, the corresponding symbol is + /// Values[code + ValOffset[k]]. /// - public fixed byte Values[256]; + public fixed int ValOffset[19]; /// - /// Gets the lookahead array. + /// Contains the length of bits for the given k value. /// - public fixed byte Lookahead[512]; + public fixed byte LookaheadSize[JpegConstants.Huffman.LookupSize]; /// - /// Gets the sizes array + /// Lookahead table: indexed by the next bits of + /// the input data stream. If the next Huffman code is no more + /// than bits long, we can obtain its length and + /// the corresponding symbol directly from this tables. + /// + /// The lower 8 bits of each table entry contain the number of + /// bits in the corresponding Huffman code, or + 1 + /// if too long. The next 8 bits of each entry contain the symbol. /// - public fixed short Sizes[257]; + public fixed byte LookaheadValue[JpegConstants.Huffman.LookupSize]; /// /// Initializes a new instance of the struct. @@ -58,91 +65,104 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// The huffman values public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan codeLengths, ReadOnlySpan values) { - this.isDerived = false; + this.isConfigured = false; this.memoryAllocator = memoryAllocator; - Unsafe.CopyBlockUnaligned(ref this.codeLengths[0], ref MemoryMarshal.GetReference(codeLengths), (uint)codeLengths.Length); + Unsafe.CopyBlockUnaligned(ref this.Sizes[0], ref MemoryMarshal.GetReference(codeLengths), (uint)codeLengths.Length); Unsafe.CopyBlockUnaligned(ref this.Values[0], ref MemoryMarshal.GetReference(values), (uint)values.Length); } /// - /// Expands the HuffmanTable into its derived form. + /// Expands the HuffmanTable into its readable form. /// - public void Derive() + public void Configure() { - if (this.isDerived) + if (this.isConfigured) { return; } - const int Length = 257; - using (IMemoryOwner huffcode = this.memoryAllocator.Allocate(Length)) - { - ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.GetSpan()); - ref byte codeLengthsRef = ref this.codeLengths[0]; + int p, si; + Span huffsize = stackalloc char[257]; + Span huffcode = stackalloc uint[257]; + uint code; - // Figure C.1: make table of Huffman code length for each symbol - ref short sizesRef = ref this.Sizes[0]; - short x = 0; - for (short i = 1; i < 17; i++) + // Figure C.1: make table of Huffman code length for each symbol + p = 0; + for (int l = 1; l <= 16; l++) + { + int i = this.Sizes[l]; + while (i-- != 0) { - byte length = Unsafe.Add(ref codeLengthsRef, i); - for (short j = 0; j < length; j++) - { - Unsafe.Add(ref sizesRef, x++) = i; - } + huffsize[p++] = (char)l; } + } - Unsafe.Add(ref sizesRef, x) = 0; - - // Figure C.2: generate the codes themselves - int si = 0; - ref int valOffsetRef = ref this.ValOffset[0]; - ref uint maxcodeRef = ref this.MaxCode[0]; + huffsize[p] = (char)0; - uint code = 0; - int k; - for (k = 1; k < 17; k++) + // Figure C.2: generate the codes themselves + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p] != 0) + { + while (huffsize[p] == si) { - // Compute delta to add to code to compute symbol id. - Unsafe.Add(ref valOffsetRef, k) = (int)(si - code); - if (Unsafe.Add(ref sizesRef, si) == k) - { - while (Unsafe.Add(ref sizesRef, si) == k) - { - Unsafe.Add(ref huffcodeRef, si++) = (short)code++; - } - } + huffcode[p++] = code; + code++; + } + + code <<= 1; + si++; + } - // Figure F.15: generate decoding tables for bit-sequential decoding. - // Compute largest code + 1 for this size. preshifted as we need it later. - Unsafe.Add(ref maxcodeRef, k) = code << (16 - k); - code <<= 1; + // Figure F.15: generate decoding tables for bit-sequential decoding + p = 0; + for (int l = 1; l <= 16; l++) + { + if (this.Sizes[l] != 0) + { + int offset = p - (int)huffcode[p]; + this.ValOffset[l] = offset; + p += this.Sizes[l]; + this.MaxCode[l] = huffcode[p - 1]; // Maximum code of length l + this.MaxCode[l] <<= 64 - l; // Left justify + this.MaxCode[l] |= (1ul << (64 - l)) - 1; + } + else + { + this.MaxCode[l] = 0; } + } - Unsafe.Add(ref maxcodeRef, k) = 0xFFFFFFFF; + this.ValOffset[18] = 0; + this.MaxCode[17] = ulong.MaxValue; // Ensures huff decode terminates - // Generate non-spec lookup tables to speed up decoding. - const int FastBits = ScanDecoder.FastBits; - ref byte lookaheadRef = ref this.Lookahead[0]; - Unsafe.InitBlockUnaligned(ref lookaheadRef, 0xFF, 1 << FastBits); // Flag for non-accelerated + // Compute lookahead tables to speed up decoding. + // First we set all the table entries to JpegConstants.Huffman.SlowBits, indicating "too long"; + // then we iterate through the Huffman codes that are short enough and + // fill in all the entries that correspond to bit sequences starting + // with that code. + ref byte lookupSizeRef = ref this.LookaheadSize[0]; + Unsafe.InitBlockUnaligned(ref lookupSizeRef, JpegConstants.Huffman.SlowBits, JpegConstants.Huffman.LookupSize); - for (int i = 0; i < si; i++) + p = 0; + for (int length = 1; length <= JpegConstants.Huffman.LookupBits; length++) + { + for (int i = 1; i <= this.Sizes[length]; i++, p++) { - int size = Unsafe.Add(ref sizesRef, i); - if (size <= FastBits) + // length = current code's length, p = its index in huffcode[] & huffval[]. + // Generate left-justified code followed by all possible bit sequences + int lookbits = (int)(huffcode[p] << (JpegConstants.Huffman.LookupBits - length)); + for (int ctr = 1 << (JpegConstants.Huffman.LookupBits - length); ctr > 0; ctr--) { - int fastOffset = FastBits - size; - int fastCode = Unsafe.Add(ref huffcodeRef, i) << fastOffset; - int fastMax = 1 << fastOffset; - for (int left = 0; left < fastMax; left++) - { - Unsafe.Add(ref lookaheadRef, fastCode + left) = (byte)i; - } + this.LookaheadSize[lookbits] = (byte)length; + this.LookaheadValue[lookbits] = this.Values[p]; + lookbits++; } } } - this.isDerived = true; + this.isConfigured = true; } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs deleted file mode 100644 index ef4b359ff..000000000 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs +++ /dev/null @@ -1,1058 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using SixLabors.ImageSharp.IO; -using SixLabors.ImageSharp.Memory; - -namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder -{ - /// - /// Decodes the Huffman encoded spectral scan. - /// Originally ported from - /// with additional fixes for both performance and common encoding errors. - /// - internal class ScanDecoder - { - // The number of bits that can be read via a LUT. - public const int FastBits = 9; - - // LUT mask for n rightmost bits. Bmask[n] = (1 << n) - 1 - private static readonly uint[] Bmask = { 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535 }; - - // LUT Bias[n] = (-1 << n) + 1 - private static readonly int[] Bias = { 0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047, -4095, -8191, -16383, -32767 }; - - private readonly JpegFrame frame; - private readonly HuffmanTable[] dcHuffmanTables; - private readonly HuffmanTable[] acHuffmanTables; - private readonly FastACTable[] fastACTables; - - private readonly DoubleBufferedStreamReader stream; - private readonly JpegComponent[] components; - private readonly ZigZag dctZigZag; - - // The restart interval. - private readonly int restartInterval; - - // The number of interleaved components. - private readonly int componentsLength; - - // The spectral selection start. - private readonly int spectralStart; - - // The spectral selection end. - private readonly int spectralEnd; - - // The successive approximation high bit end. - private readonly int successiveHigh; - - // The successive approximation low bit end. - private readonly int successiveLow; - - // The number of valid bits left to read in the buffer. - private int codeBits; - - // The entropy encoded code buffer. - private uint codeBuffer; - - // Whether there is more data to pull from the stream for the current mcu. - private bool nomore; - - // Whether we have prematurely reached the end of the file. - private bool eof; - - // The current, if any, marker in the input stream. - private byte marker; - - // Whether we have a bad marker, I.E. One that is not between RST0 and RST7 - private bool badMarker; - - // The opening position of an identified marker. - private long markerPosition; - - // How many mcu's are left to do. - private int todo; - - // The End-Of-Block countdown for ending the sequence prematurely when the remaining coefficients are zero. - private int eobrun; - - /// - /// Initializes a new instance of the class. - /// - /// The input stream. - /// The image frame. - /// The DC Huffman tables. - /// The AC Huffman tables. - /// The fast AC decoding tables. - /// The length of the components. Different to the array length. - /// The reset interval. - /// The spectral selection start. - /// The spectral selection end. - /// The successive approximation bit high end. - /// The successive approximation bit low end. - public ScanDecoder( - DoubleBufferedStreamReader stream, - JpegFrame frame, - HuffmanTable[] dcHuffmanTables, - HuffmanTable[] acHuffmanTables, - FastACTable[] fastACTables, - int componentsLength, - int restartInterval, - int spectralStart, - int spectralEnd, - int successiveHigh, - int successiveLow) - { - this.dctZigZag = ZigZag.CreateUnzigTable(); - this.stream = stream; - this.frame = frame; - this.dcHuffmanTables = dcHuffmanTables; - this.acHuffmanTables = acHuffmanTables; - this.fastACTables = fastACTables; - this.components = frame.Components; - this.marker = JpegConstants.Markers.XFF; - this.markerPosition = 0; - this.componentsLength = componentsLength; - this.restartInterval = restartInterval; - this.spectralStart = spectralStart; - this.spectralEnd = spectralEnd; - this.successiveHigh = successiveHigh; - this.successiveLow = successiveLow; - } - - /// - /// Decodes the entropy coded data. - /// - public void ParseEntropyCodedData() - { - this.Reset(); - - if (!this.frame.Progressive) - { - this.ParseBaselineData(); - } - else - { - this.ParseProgressiveData(); - } - - if (this.badMarker) - { - this.stream.Position = this.markerPosition; - } - } - - [MethodImpl(InliningOptions.ShortMethod)] - private static uint LRot(uint x, int y) => (x << y) | (x >> (32 - y)); - - private void ParseBaselineData() - { - if (this.componentsLength == 1) - { - this.ParseBaselineDataNonInterleaved(); - } - else - { - this.ParseBaselineDataInterleaved(); - } - } - - private unsafe void ParseBaselineDataInterleaved() - { - // Interleaved - int mcu = 0; - int mcusPerColumn = this.frame.McusPerColumn; - int mcusPerLine = this.frame.McusPerLine; - - // Pre-derive the huffman table to avoid in-loop checks. - for (int i = 0; i < this.componentsLength; i++) - { - int order = this.frame.ComponentOrder[i]; - JpegComponent component = this.components[order]; - - ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; - ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; - dcHuffmanTable.Derive(); - acHuffmanTable.Derive(); - - ref FastACTable fastAcTable = ref this.fastACTables[component.ACHuffmanTableId]; - fastAcTable.Derive(ref acHuffmanTable); - } - - for (int j = 0; j < mcusPerColumn; j++) - { - for (int i = 0; i < mcusPerLine; i++) - { - // Scan an interleaved mcu... process components in order - int mcuRow = mcu / mcusPerLine; - int mcuCol = mcu % mcusPerLine; - for (int k = 0; k < this.componentsLength; k++) - { - int order = this.frame.ComponentOrder[k]; - JpegComponent component = this.components[order]; - - ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; - ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; - ref FastACTable fastAcTable = ref this.fastACTables[component.ACHuffmanTableId]; - ref short fastACRef = ref fastAcTable.Lookahead[0]; - - int h = component.HorizontalSamplingFactor; - int v = component.VerticalSamplingFactor; - - // Scan out an mcu's worth of this component; that's just determined - // by the basic H and V specified for the component - for (int y = 0; y < v; y++) - { - int blockRow = (mcuRow * v) + y; - Span blockSpan = component.SpectralBlocks.GetRowSpan(blockRow); - ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); - - for (int x = 0; x < h; x++) - { - if (this.eof) - { - return; - } - - int blockCol = (mcuCol * h) + x; - - this.DecodeBlockBaseline( - component, - ref Unsafe.Add(ref blockRef, blockCol), - ref dcHuffmanTable, - ref acHuffmanTable, - ref fastACRef); - } - } - } - - // After all interleaved components, that's an interleaved MCU, - // so now count down the restart interval - mcu++; - if (!this.ContinueOnMcuComplete()) - { - return; - } - } - } - } - - /// - /// Non-interleaved data, we just need to process one block at a time in trivial scanline order - /// number of blocks to do just depends on how many actual "pixels" each component has, - /// independent of interleaved MCU blocking and such. - /// - private unsafe void ParseBaselineDataNonInterleaved() - { - JpegComponent component = this.components[this.frame.ComponentOrder[0]]; - - int w = component.WidthInBlocks; - int h = component.HeightInBlocks; - - ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; - ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; - dcHuffmanTable.Derive(); - acHuffmanTable.Derive(); - - ref FastACTable fastAcTable = ref this.fastACTables[component.ACHuffmanTableId]; - fastAcTable.Derive(ref acHuffmanTable); - ref short fastACRef = ref fastAcTable.Lookahead[0]; - - int mcu = 0; - for (int j = 0; j < h; j++) - { - int blockRow = j; - Span blockSpan = component.SpectralBlocks.GetRowSpan(j); - ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); - - for (int i = 0; i < w; i++) - { - if (this.eof) - { - return; - } - - this.DecodeBlockBaseline( - component, - ref Unsafe.Add(ref blockRef, i), - ref dcHuffmanTable, - ref acHuffmanTable, - ref fastACRef); - - // Every data block is an MCU, so countdown the restart interval - mcu++; - if (!this.ContinueOnMcuComplete()) - { - return; - } - } - } - } - - private void CheckProgressiveData() - { - // Validate successive scan parameters. - // Logic has been adapted from libjpeg. - // See Table B.3 – Scan header parameter size and values. itu-t81.pdf - bool invalid = false; - if (this.spectralStart == 0) - { - if (this.spectralEnd != 0) - { - invalid = true; - } - } - else - { - // Need not check Ss/Se < 0 since they came from unsigned bytes. - if (this.spectralEnd < this.spectralStart || this.spectralEnd > 63) - { - invalid = true; - } - - // AC scans may have only one component. - if (this.componentsLength != 1) - { - invalid = true; - } - } - - if (this.successiveHigh != 0) - { - // Successive approximation refinement scan: must have Al = Ah-1. - if (this.successiveHigh - 1 != this.successiveLow) - { - invalid = true; - } - } - - // TODO: How does this affect 12bit jpegs. - // According to libjpeg the range covers 8bit only? - if (this.successiveLow > 13) - { - invalid = true; - } - - if (invalid) - { - JpegThrowHelper.ThrowBadProgressiveScan(this.spectralStart, this.spectralEnd, this.successiveHigh, this.successiveLow); - } - } - - private void ParseProgressiveData() - { - this.CheckProgressiveData(); - - if (this.componentsLength == 1) - { - this.ParseProgressiveDataNonInterleaved(); - } - else - { - this.ParseProgressiveDataInterleaved(); - } - } - - private void ParseProgressiveDataInterleaved() - { - // Interleaved - int mcu = 0; - int mcusPerColumn = this.frame.McusPerColumn; - int mcusPerLine = this.frame.McusPerLine; - - // Pre-derive the huffman table to avoid in-loop checks. - for (int k = 0; k < this.componentsLength; k++) - { - int order = this.frame.ComponentOrder[k]; - JpegComponent component = this.components[order]; - ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; - dcHuffmanTable.Derive(); - } - - for (int j = 0; j < mcusPerColumn; j++) - { - for (int i = 0; i < mcusPerLine; i++) - { - // Scan an interleaved mcu... process components in order - int mcuRow = mcu / mcusPerLine; - int mcuCol = mcu % mcusPerLine; - for (int k = 0; k < this.componentsLength; k++) - { - int order = this.frame.ComponentOrder[k]; - JpegComponent component = this.components[order]; - ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; - - int h = component.HorizontalSamplingFactor; - int v = component.VerticalSamplingFactor; - - // Scan out an mcu's worth of this component; that's just determined - // by the basic H and V specified for the component - for (int y = 0; y < v; y++) - { - int blockRow = (mcuRow * v) + y; - Span blockSpan = component.SpectralBlocks.GetRowSpan(blockRow); - ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); - - for (int x = 0; x < h; x++) - { - if (this.eof) - { - return; - } - - int blockCol = (mcuCol * h) + x; - - this.DecodeBlockProgressiveDC( - component, - ref Unsafe.Add(ref blockRef, blockCol), - ref dcHuffmanTable); - } - } - } - - // After all interleaved components, that's an interleaved MCU, - // so now count down the restart interval - mcu++; - if (!this.ContinueOnMcuComplete()) - { - return; - } - } - } - } - - /// - /// Non-interleaved data, we just need to process one block at a time, - /// in trivial scanline order - /// number of blocks to do just depends on how many actual "pixels" this - /// component has, independent of interleaved MCU blocking and such - /// - private unsafe void ParseProgressiveDataNonInterleaved() - { - JpegComponent component = this.components[this.frame.ComponentOrder[0]]; - - int w = component.WidthInBlocks; - int h = component.HeightInBlocks; - - if (this.spectralStart == 0) - { - ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; - dcHuffmanTable.Derive(); - - int mcu = 0; - for (int j = 0; j < h; j++) - { - Span blockSpan = component.SpectralBlocks.GetRowSpan(j); - ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); - - for (int i = 0; i < w; i++) - { - if (this.eof) - { - return; - } - - this.DecodeBlockProgressiveDC( - component, - ref Unsafe.Add(ref blockRef, i), - ref dcHuffmanTable); - - // Every data block is an MCU, so countdown the restart interval - mcu++; - if (!this.ContinueOnMcuComplete()) - { - return; - } - } - } - } - else - { - ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId]; - acHuffmanTable.Derive(); - - ref FastACTable fastAcTable = ref this.fastACTables[component.ACHuffmanTableId]; - fastAcTable.Derive(ref acHuffmanTable); - ref short fastACRef = ref fastAcTable.Lookahead[0]; - - int mcu = 0; - for (int j = 0; j < h; j++) - { - Span blockSpan = component.SpectralBlocks.GetRowSpan(j); - ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); - - for (int i = 0; i < w; i++) - { - if (this.eof) - { - return; - } - - this.DecodeBlockProgressiveAC( - ref Unsafe.Add(ref blockRef, i), - ref acHuffmanTable, - ref fastACRef); - - // Every data block is an MCU, so countdown the restart interval - mcu++; - if (!this.ContinueOnMcuComplete()) - { - return; - } - } - } - } - } - - private void DecodeBlockBaseline( - JpegComponent component, - ref Block8x8 block, - ref HuffmanTable dcTable, - ref HuffmanTable acTable, - ref short fastACRef) - { - this.CheckBits(); - int t = this.DecodeHuffman(ref dcTable); - - if (t < 0) - { - JpegThrowHelper.ThrowBadHuffmanCode(); - } - - ref short blockDataRef = ref Unsafe.As(ref block); - - int diff = t != 0 ? this.ExtendReceive(t) : 0; - int dc = component.DcPredictor + diff; - component.DcPredictor = dc; - blockDataRef = (short)dc; - - // Decode AC Components, See Jpeg Spec - int k = 1; - do - { - int zig; - int s; - - this.CheckBits(); - int c = this.PeekBits(); - int r = Unsafe.Add(ref fastACRef, c); - - if (r != 0) - { - // Fast AC path - k += (r >> 4) & 15; // Run - s = r & 15; // Combined Length - this.codeBuffer <<= s; - this.codeBits -= s; - - // Decode into unzigzag location - zig = this.dctZigZag[k++]; - Unsafe.Add(ref blockDataRef, zig) = (short)(r >> 8); - } - else - { - int rs = this.DecodeHuffman(ref acTable); - - if (rs < 0) - { - JpegThrowHelper.ThrowBadHuffmanCode(); - } - - s = rs & 15; - r = rs >> 4; - - if (s == 0) - { - if (rs != 0xF0) - { - break; // End block - } - - k += 16; - } - else - { - k += r; - - // Decode into unzigzag location - zig = this.dctZigZag[k++]; - Unsafe.Add(ref blockDataRef, zig) = (short)this.ExtendReceive(s); - } - } - } - while (k < 64); - } - - private void DecodeBlockProgressiveDC( - JpegComponent component, - ref Block8x8 block, - ref HuffmanTable dcTable) - { - this.CheckBits(); - - ref short blockDataRef = ref Unsafe.As(ref block); - - if (this.successiveHigh == 0) - { - // First scan for DC coefficient, must be first - int t = this.DecodeHuffman(ref dcTable); - int diff = t != 0 ? this.ExtendReceive(t) : 0; - - int dc = component.DcPredictor + diff; - component.DcPredictor = dc; - - blockDataRef = (short)(dc << this.successiveLow); - } - else - { - // Refinement scan for DC coefficient - if (this.GetBit() != 0) - { - blockDataRef += (short)(1 << this.successiveLow); - } - } - } - - private void DecodeBlockProgressiveAC( - ref Block8x8 block, - ref HuffmanTable acTable, - ref short fastACRef) - { - ref short blockDataRef = ref Unsafe.As(ref block); - - if (this.successiveHigh == 0) - { - // MCU decoding for AC initial scan (either spectral selection, - // or first pass of successive approximation). - int shift = this.successiveLow; - - if (this.eobrun != 0) - { - this.eobrun--; - return; - } - - int k = this.spectralStart; - do - { - int zig; - int s; - - this.CheckBits(); - int c = this.PeekBits(); - int r = Unsafe.Add(ref fastACRef, c); - - if (r != 0) - { - // Fast AC path - k += (r >> 4) & 15; // Run - s = r & 15; // Combined length - this.codeBuffer <<= s; - this.codeBits -= s; - - // Decode into unzigzag location - zig = this.dctZigZag[k++]; - Unsafe.Add(ref blockDataRef, zig) = (short)((r >> 8) << shift); - } - else - { - int rs = this.DecodeHuffman(ref acTable); - - if (rs < 0) - { - JpegThrowHelper.ThrowBadHuffmanCode(); - } - - s = rs & 15; - r = rs >> 4; - - if (s == 0) - { - if (r < 15) - { - this.eobrun = 1 << r; - if (r != 0) - { - this.eobrun += this.GetBits(r); - } - - this.eobrun--; - break; - } - - k += 16; - } - else - { - k += r; - zig = this.dctZigZag[k++]; - Unsafe.Add(ref blockDataRef, zig) = (short)(this.ExtendReceive(s) << shift); - } - } - } - while (k <= this.spectralEnd); - } - else - { - // Refinement scan for these AC coefficients - this.DecodeBlockProgressiveACRefined(ref blockDataRef, ref acTable); - } - } - - private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref HuffmanTable acTable) - { - int k; - - // Refinement scan for these AC coefficients - short bit = (short)(1 << this.successiveLow); - - if (this.eobrun != 0) - { - this.eobrun--; - for (k = this.spectralStart; k <= this.spectralEnd; k++) - { - ref short p = ref Unsafe.Add(ref blockDataRef, this.dctZigZag[k]); - if (p != 0) - { - if (this.GetBit() != 0) - { - if ((p & bit) == 0) - { - if (p > 0) - { - p += bit; - } - else - { - p -= bit; - } - } - } - } - } - } - else - { - k = this.spectralStart; - do - { - int rs = this.DecodeHuffman(ref acTable); - if (rs < 0) - { - JpegThrowHelper.ThrowBadHuffmanCode(); - } - - int s = rs & 15; - int r = rs >> 4; - - if (s == 0) - { - // r=15 s=0 should write 16 0s, so we just do - // a run of 15 0s and then write s (which is 0), - // so we don't have to do anything special here - if (r < 15) - { - this.eobrun = (1 << r) - 1; - - if (r != 0) - { - this.eobrun += this.GetBits(r); - } - - r = 64; // Force end of block - } - } - else - { - if (s != 1) - { - JpegThrowHelper.ThrowBadHuffmanCode(); - } - - // Sign bit - if (this.GetBit() != 0) - { - s = bit; - } - else - { - s = -bit; - } - } - - // Advance by r - while (k <= this.spectralEnd) - { - ref short p = ref Unsafe.Add(ref blockDataRef, this.dctZigZag[k++]); - if (p != 0) - { - if (this.GetBit() != 0) - { - if ((p & bit) == 0) - { - if (p > 0) - { - p += bit; - } - else - { - p -= bit; - } - } - } - } - else - { - if (r == 0) - { - p = (short)s; - break; - } - - r--; - } - } - } - while (k <= this.spectralEnd); - } - } - - [MethodImpl(InliningOptions.ShortMethod)] - private int GetBits(int n) - { - if (this.codeBits < n) - { - this.FillBuffer(); - } - - uint k = LRot(this.codeBuffer, n); - uint mask = Bmask[n]; - this.codeBuffer = k & ~mask; - k &= mask; - this.codeBits -= n; - return (int)k; - } - - [MethodImpl(InliningOptions.ShortMethod)] - private int GetBit() - { - if (this.codeBits < 1) - { - this.FillBuffer(); - } - - uint k = this.codeBuffer; - this.codeBuffer <<= 1; - this.codeBits--; - - return (int)(k & 0x80000000); - } - - [MethodImpl(InliningOptions.ColdPath)] - private void FillBuffer() - { - // Attempt to load at least the minimum number of required bits into the buffer. - // We fail to do so only if we hit a marker or reach the end of the input stream. - do - { - int b = this.nomore ? 0 : this.stream.ReadByte(); - - if (b == -1) - { - // We've encountered the end of the file stream which means there's no EOI marker in the image - // or the SOS marker has the wrong dimensions set. - this.eof = true; - b = 0; - } - - // Found a marker. - if (b == JpegConstants.Markers.XFF) - { - this.markerPosition = this.stream.Position - 1; - int c = this.stream.ReadByte(); - while (c == JpegConstants.Markers.XFF) - { - c = this.stream.ReadByte(); - - if (c == -1) - { - this.eof = true; - c = 0; - break; - } - } - - if (c != 0) - { - this.marker = (byte)c; - this.nomore = true; - if (!this.HasRestart()) - { - this.badMarker = true; - } - - return; - } - } - - this.codeBuffer |= (uint)b << (24 - this.codeBits); - this.codeBits += 8; - } - while (this.codeBits <= 24); - } - - [MethodImpl(InliningOptions.ShortMethod)] - private unsafe int DecodeHuffman(ref HuffmanTable table) - { - this.CheckBits(); - - // Look at the top FastBits and determine what symbol ID it is, - // if the code is <= FastBits. - int c = this.PeekBits(); - int k = table.Lookahead[c]; - if (k < 0xFF) - { - int s = table.Sizes[k]; - if (s > this.codeBits) - { - return -1; - } - - this.codeBuffer <<= s; - this.codeBits -= s; - return table.Values[k]; - } - - return this.DecodeHuffmanSlow(ref table); - } - - [MethodImpl(InliningOptions.ColdPath)] - private unsafe int DecodeHuffmanSlow(ref HuffmanTable table) - { - // Naive test is to shift the code_buffer down so k bits are - // valid, then test against MaxCode. To speed this up, we've - // preshifted maxcode left so that it has (16-k) 0s at the - // end; in other words, regardless of the number of bits, it - // wants to be compared against something shifted to have 16; - // that way we don't need to shift inside the loop. - uint temp = this.codeBuffer >> 16; - int k; - for (k = FastBits + 1; ; ++k) - { - if (temp < table.MaxCode[k]) - { - break; - } - } - - if (k == 17) - { - // Error! code not found - this.codeBits -= 16; - return -1; - } - - if (k > this.codeBits) - { - return -1; - } - - // Convert the huffman code to the symbol id - int c = (int)(((this.codeBuffer >> (32 - k)) & Bmask[k]) + table.ValOffset[k]); - - // Convert the id to a symbol - this.codeBits -= k; - this.codeBuffer <<= k; - return table.Values[c]; - } - - [MethodImpl(InliningOptions.ShortMethod)] - private int ExtendReceive(int n) - { - if (this.codeBits < n) - { - this.FillBuffer(); - } - - int sgn = (int)this.codeBuffer >> 31; - uint k = LRot(this.codeBuffer, n); - this.codeBuffer = k & ~Bmask[n]; - k &= Bmask[n]; - this.codeBits -= n; - return (int)(k + (Bias[n] & ~sgn)); - } - - [MethodImpl(InliningOptions.ShortMethod)] - private void CheckBits() - { - if (this.codeBits < 16) - { - this.FillBuffer(); - } - } - - [MethodImpl(InliningOptions.ShortMethod)] - private int PeekBits() => (int)((this.codeBuffer >> (32 - FastBits)) & ((1 << FastBits) - 1)); - - [MethodImpl(InliningOptions.ShortMethod)] - private bool ContinueOnMcuComplete() - { - if (--this.todo > 0) - { - return true; - } - - if (this.codeBits < 24) - { - this.FillBuffer(); - } - - // If it's NOT a restart, then just bail, so we get corrupt data rather than no data. - // Reset the stream to before any bad markers to ensure we can read successive segments. - if (this.badMarker) - { - this.stream.Position = this.markerPosition; - } - - if (!this.HasRestart()) - { - return false; - } - - this.Reset(); - - return true; - } - - [MethodImpl(InliningOptions.ShortMethod)] - private bool HasRestart() - { - byte m = this.marker; - return m >= JpegConstants.Markers.RST0 && m <= JpegConstants.Markers.RST7; - } - - private void Reset() - { - this.codeBits = 0; - this.codeBuffer = 0; - - for (int i = 0; i < this.components.Length; i++) - { - JpegComponent c = this.components[i]; - c.DcPredictor = 0; - } - - this.nomore = false; - this.marker = JpegConstants.Markers.XFF; - this.markerPosition = 0; - this.badMarker = false; - this.eobrun = 0; - - // No more than 1<<31 MCUs if no restartInterval? that's plenty safe since we don't even allow 1<<30 pixels - this.todo = this.restartInterval > 0 ? this.restartInterval : int.MaxValue; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/JpegConstants.cs b/src/ImageSharp/Formats/Jpeg/JpegConstants.cs index 49e3b4170..a39480e12 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegConstants.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegConstants.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg public static readonly IEnumerable FileExtensions = new[] { "jpg", "jpeg", "jfif" }; /// - /// Contains marker specific constants + /// Contains marker specific constants. /// // ReSharper disable InconsistentNaming internal static class Markers @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } /// - /// Contains Adobe specific constants + /// Contains Adobe specific constants. /// internal static class Adobe { @@ -238,5 +238,32 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// public const byte ColorTransformYcck = 2; } + + /// + /// Contains Huffman specific constants. + /// + internal static class Huffman + { + /// + /// The size of the huffman decoder register. + /// + public const int RegisterSize = 64; + + /// + /// If the next Huffman code is no more than this number of bits, we can obtain its length + /// and the corresponding symbol directly from this tables. + /// + public const int LookupBits = 8; + + /// + /// If a Huffman code is this number of bits we cannot use the lookup table to determine its value. + /// + public const int SlowBits = LookupBits + 1; + + /// + /// The size of the lookup table. + /// + public const int LookupSize = 1 << LookupBits; + } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 6d6983f19..8bd6514e0 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -59,11 +59,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// private HuffmanTable[] acHuffmanTables; - /// - /// The fast AC tables used for entropy decoding - /// - private FastACTable[] fastACTables; - /// /// The reset interval determined by RST markers /// @@ -269,7 +264,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg const int maxTables = 4; this.dcHuffmanTables = new HuffmanTable[maxTables]; this.acHuffmanTables = new HuffmanTable[maxTables]; - this.fastACTables = new FastACTable[maxTables]; } // Break only when we discover a valid EOI marker. @@ -385,7 +379,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.Frame = null; this.dcHuffmanTables = null; this.acHuffmanTables = null; - this.fastACTables = null; } /// @@ -936,12 +929,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg int spectralEnd = this.temp[1]; int successiveApproximation = this.temp[2]; - var sd = new ScanDecoder( + var sd = new HuffmanScanDecoder( this.InputStream, this.Frame, this.dcHuffmanTables, this.acHuffmanTables, - this.fastACTables, selectorsCount, this.resetInterval, spectralStart, diff --git a/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs b/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs index b30da28c4..7e8384dcf 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs @@ -20,9 +20,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg [MethodImpl(InliningOptions.ColdPath)] public static void ThrowBadQuantizationTable() => throw new ImageFormatException("Bad Quantization Table index."); - [MethodImpl(InliningOptions.ColdPath)] - public static void ThrowBadHuffmanCode() => throw new ImageFormatException("Bad Huffman code."); - [MethodImpl(InliningOptions.ColdPath)] public static void ThrowBadSampling() => throw new ImageFormatException("Bad sampling factor."); diff --git a/src/ImageSharp/IO/DoubleBufferedStreamReader.cs b/src/ImageSharp/IO/DoubleBufferedStreamReader.cs index 6d5673d5a..07f892806 100644 --- a/src/ImageSharp/IO/DoubleBufferedStreamReader.cs +++ b/src/ImageSharp/IO/DoubleBufferedStreamReader.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; using System.IO; using System.Runtime.CompilerServices; @@ -13,24 +14,28 @@ namespace SixLabors.ImageSharp.IO /// A stream reader that add a secondary level buffer in addition to native stream buffered reading /// to reduce the overhead of small incremental reads. /// - internal sealed class DoubleBufferedStreamReader : IDisposable + internal sealed unsafe class DoubleBufferedStreamReader : IDisposable { /// /// The length, in bytes, of the buffering chunk. /// - public const int ChunkLength = 4096; + public const int ChunkLength = 8192; - private const int ChunkLengthMinusOne = ChunkLength - 1; + private const int MaxChunkIndex = ChunkLength - 1; private readonly Stream stream; private readonly IManagedByteBuffer managedBuffer; + private MemoryHandle handle; + + private readonly byte* pinnedChunk; + private readonly byte[] bufferChunk; private readonly int length; - private int bytesRead; + private int chunkIndex; private int position; @@ -44,8 +49,11 @@ namespace SixLabors.ImageSharp.IO this.stream = stream; this.Position = (int)stream.Position; this.length = (int)stream.Length; - this.managedBuffer = memoryAllocator.AllocateManagedByteBuffer(ChunkLength, AllocationOptions.Clean); + this.managedBuffer = memoryAllocator.AllocateManagedByteBuffer(ChunkLength); this.bufferChunk = this.managedBuffer.Array; + this.handle = this.managedBuffer.Memory.Pin(); + this.pinnedChunk = (byte*)this.handle.Pointer; + this.chunkIndex = ChunkLength; } /// @@ -62,10 +70,20 @@ namespace SixLabors.ImageSharp.IO set { - // Reset everything. It's easier than tracking. - this.position = (int)value; - this.stream.Seek(this.position, SeekOrigin.Begin); - this.bytesRead = ChunkLength; + // Only reset chunkIndex if we are out of bounds of our working chunk + // otherwise we should simply move the value by the diff. + int v = (int)value; + if (this.IsInChunk(v, out int index)) + { + this.chunkIndex = index; + this.position = v; + } + else + { + this.position = v; + this.stream.Seek(value, SeekOrigin.Begin); + this.chunkIndex = ChunkLength; + } } } @@ -74,7 +92,7 @@ namespace SixLabors.ImageSharp.IO /// byte, or returns -1 if at the end of the stream. /// /// The unsigned byte cast to an , or -1 if at the end of the stream. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public int ReadByte() { if (this.position >= this.length) @@ -82,24 +100,21 @@ namespace SixLabors.ImageSharp.IO return -1; } - if (this.position == 0 || this.bytesRead > ChunkLengthMinusOne) + if (this.chunkIndex > MaxChunkIndex) { - return this.ReadByteSlow(); + this.FillChunk(); } this.position++; - return this.bufferChunk[this.bytesRead++]; + return this.pinnedChunk[this.chunkIndex++]; } /// /// Skips the number of bytes in the stream /// - /// The number of bytes to skip - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Skip(int count) - { - this.Position += count; - } + /// The number of bytes to skip. + [MethodImpl(InliningOptions.ShortMethod)] + public void Skip(int count) => this.Position += count; /// /// Reads a sequence of bytes from the current stream and advances the position within the stream @@ -120,36 +135,46 @@ namespace SixLabors.ImageSharp.IO /// of bytes requested if that many bytes are not currently available, or zero (0) /// if the end of the stream has been reached. /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public int Read(byte[] buffer, int offset, int count) { - if (buffer.Length > ChunkLength) + if (count > ChunkLength) { return this.ReadToBufferSlow(buffer, offset, count); } - if (this.position == 0 || count + this.bytesRead > ChunkLength) + if (count + this.chunkIndex > ChunkLength) { return this.ReadToChunkSlow(buffer, offset, count); } - int n = this.GetCount(count); + int n = this.GetCopyCount(count); this.CopyBytes(buffer, offset, n); this.position += n; - this.bytesRead += n; - + this.chunkIndex += n; return n; } /// public void Dispose() { + this.handle.Dispose(); this.managedBuffer?.Dispose(); } - [MethodImpl(MethodImplOptions.NoInlining)] - private int ReadByteSlow() + [MethodImpl(InliningOptions.ShortMethod)] + private int GetPositionDifference(int p) => p - this.position; + + [MethodImpl(InliningOptions.ShortMethod)] + private bool IsInChunk(int p, out int index) + { + index = this.GetPositionDifference(p) + this.chunkIndex; + return index > -1 && index < ChunkLength; + } + + [MethodImpl(InliningOptions.ColdPath)] + private void FillChunk() { if (this.position != this.stream.Position) { @@ -157,34 +182,25 @@ namespace SixLabors.ImageSharp.IO } this.stream.Read(this.bufferChunk, 0, ChunkLength); - this.bytesRead = 0; - - this.position++; - return this.bufferChunk[this.bytesRead++]; + this.chunkIndex = 0; } - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(InliningOptions.ColdPath)] private int ReadToChunkSlow(byte[] buffer, int offset, int count) { // Refill our buffer then copy. - if (this.position != this.stream.Position) - { - this.stream.Seek(this.position, SeekOrigin.Begin); - } + this.FillChunk(); - this.stream.Read(this.bufferChunk, 0, ChunkLength); - this.bytesRead = 0; - - int n = this.GetCount(count); + int n = this.GetCopyCount(count); this.CopyBytes(buffer, offset, n); this.position += n; - this.bytesRead += n; + this.chunkIndex += n; return n; } - [MethodImpl(MethodImplOptions.NoInlining)] + [MethodImpl(InliningOptions.ColdPath)] private int ReadToBufferSlow(byte[] buffer, int offset, int count) { // Read to target but don't copy to our chunk. @@ -195,11 +211,12 @@ namespace SixLabors.ImageSharp.IO int n = this.stream.Read(buffer, offset, count); this.Position += n; + return n; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private int GetCount(int count) + [MethodImpl(InliningOptions.ShortMethod)] + private int GetCopyCount(int count) { int n = this.length - this.position; if (n > count) @@ -215,23 +232,23 @@ namespace SixLabors.ImageSharp.IO return n; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] private void CopyBytes(byte[] buffer, int offset, int count) { if (count < 9) { int byteCount = count; - int read = this.bytesRead; - byte[] chunk = this.bufferChunk; + int read = this.chunkIndex; + byte* pinned = this.pinnedChunk; while (--byteCount > -1) { - buffer[offset + byteCount] = chunk[read + byteCount]; + buffer[offset + byteCount] = pinned[read + byteCount]; } } else { - Buffer.BlockCopy(this.bufferChunk, this.bytesRead, buffer, offset, count); + Buffer.BlockCopy(this.bufferChunk, this.chunkIndex, buffer, offset, count); } } } diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index f7f9e1d5f..a124ddcac 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -38,8 +38,8 @@ - - + + diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs index 5958b9f79..5a4a9ab17 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs @@ -47,5 +47,22 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg decoder.Dispose(); } } + + // RESULTS (2019 April 23): + // + // BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17763.437 (1809/October2018Update/Redstone5) + // Intel Core i7-6600U CPU 2.60GHz (Skylake), 1 CPU, 4 logical and 2 physical cores + // .NET Core SDK=2.2.202 + // [Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3362.0 + // Core : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // + // | Method | Job | Runtime | TestImage | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | + // |---------------------------- |----- |-------- |--------------------- |---------:|---------:|----------:|------:|--------:|---------:|------:|------:|----------:| + // | 'System.Drawing FULL' | Clr | Clr | Jpg/b(...)f.jpg [28] | 18.69 ms | 8.273 ms | 0.4535 ms | 1.00 | 0.00 | 343.7500 | - | - | 757.89 KB | + // | JpegDecoderCore.ParseStream | Clr | Clr | Jpg/b(...)f.jpg [28] | 15.76 ms | 4.266 ms | 0.2339 ms | 0.84 | 0.03 | - | - | - | 11.83 KB | + // | | | | | | | | | | | | | | + // | 'System.Drawing FULL' | Core | Core | Jpg/b(...)f.jpg [28] | 17.68 ms | 2.711 ms | 0.1486 ms | 1.00 | 0.00 | 343.7500 | - | - | 757.04 KB | + // | JpegDecoderCore.ParseStream | Core | Core | Jpg/b(...)f.jpg [28] | 14.27 ms | 3.671 ms | 0.2012 ms | 0.81 | 0.00 | - | - | - | 11.76 KB | } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs index 8247ba42b..62742f729 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg public ShortClr() { this.Add( - //Job.Clr.WithLaunchCount(1).WithWarmupCount(2).WithIterationCount(3), + // Job.Clr.WithLaunchCount(1).WithWarmupCount(2).WithIterationCount(3), Job.Core.WithLaunchCount(1).WithWarmupCount(2).WithIterationCount(3) ); } @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg private byte[] jpegBytes; private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); - + [Params( TestImages.Jpeg.BenchmarkSuite.Lake_Small444YCbCr, TestImages.Jpeg.BenchmarkSuite.BadRstProgressive518_Large444YCbCr, @@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { using (var memoryStream = new MemoryStream(this.jpegBytes)) { - using (var image = Image.Load(memoryStream, new JpegDecoder(){ IgnoreMetadata = true})) + using (var image = Image.Load(memoryStream, new JpegDecoder() { IgnoreMetadata = true })) { return new CoreSize(image.Width, image.Height); } @@ -115,5 +115,24 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg // | | | | | | | | | | | // 'Decode Jpeg - System.Drawing' | Jpg/issues/issue750-exif-tranform.jpg | 95.192 ms | 3.1762 ms | 0.1795 ms | 1.00 | 0.00 | 1750.0000 | - | - | 5492.63 KB | // 'Decode Jpeg - ImageSharp' | Jpg/issues/issue750-exif-tranform.jpg | 230.158 ms | 48.8128 ms | 2.7580 ms | 2.42 | 0.02 | 312.5000 | 312.5000 | 312.5000 | 58834.66 KB | + + // RESULTS (2019 April 23): + // + //BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17763.437 (1809/October2018Update/Redstone5) + //Intel Core i7-6600U CPU 2.60GHz (Skylake), 1 CPU, 4 logical and 2 physical cores + //.NET Core SDK=2.2.202 + // [Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // Core : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // + //| Method | TestImage | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | + //|------------------------------- |--------------------- |-----------:|-----------:|-----------:|------:|--------:|----------:|------:|------:|------------:| + //| 'Decode Jpeg - System.Drawing' | Jpg/b(...)e.jpg [21] | 6.957 ms | 9.618 ms | 0.5272 ms | 1.00 | 0.00 | 93.7500 | - | - | 205.83 KB | + //| 'Decode Jpeg - ImageSharp' | Jpg/b(...)e.jpg [21] | 18.348 ms | 8.876 ms | 0.4865 ms | 2.65 | 0.23 | - | - | - | 14.49 KB | + //| | | | | | | | | | | | + //| 'Decode Jpeg - System.Drawing' | Jpg/b(...)f.jpg [28] | 18.687 ms | 11.632 ms | 0.6376 ms | 1.00 | 0.00 | 343.7500 | - | - | 757.04 KB | + //| 'Decode Jpeg - ImageSharp' | Jpg/b(...)f.jpg [28] | 41.990 ms | 25.514 ms | 1.3985 ms | 2.25 | 0.10 | - | - | - | 15.48 KB | + //| | | | | | | | | | | | + //| 'Decode Jpeg - System.Drawing' | Jpg/i(...)e.jpg [43] | 477.265 ms | 732.126 ms | 40.1303 ms | 1.00 | 0.00 | 3000.0000 | - | - | 7403.76 KB | + //| 'Decode Jpeg - ImageSharp' | Jpg/i(...)e.jpg [43] | 348.545 ms | 91.480 ms | 5.0143 ms | 0.73 | 0.06 | - | - | - | 35177.21 KB | } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DoubleBufferedStreams.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DoubleBufferedStreams.cs index d4cbe81e1..b0834eb52 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DoubleBufferedStreams.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DoubleBufferedStreams.cs @@ -19,8 +19,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg private MemoryStream stream2; private MemoryStream stream3; private MemoryStream stream4; - DoubleBufferedStreamReader reader1; - DoubleBufferedStreamReader reader2; + private DoubleBufferedStreamReader reader1; + private DoubleBufferedStreamReader reader2; [GlobalSetup] public void CreateStreams() @@ -102,6 +102,19 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg return r; } + [Benchmark] + public int SimpleReadByte() + { + byte[] b = this.buffer; + int r = 0; + for (int i = 0; i < b.Length; i++) + { + r += b[i]; + } + + return r; + } + private static byte[] CreateTestBytes() { byte[] buffer = new byte[DoubleBufferedStreamReader.ChunkLength * 3]; @@ -111,4 +124,29 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg return buffer; } } + + // RESULTS (2019 April 24): + // + //BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17763.437 (1809/October2018Update/Redstone5) + //Intel Core i7-6600U CPU 2.60GHz (Skylake), 1 CPU, 4 logical and 2 physical cores + //.NET Core SDK=2.2.202 + // [Host] : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // Clr : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3362.0 + // Core : .NET Core 2.1.9 (CoreCLR 4.6.27414.06, CoreFX 4.6.27415.01), 64bit RyuJIT + // + //IterationCount=3 LaunchCount=1 WarmupCount=3 + // + //| Method | Job | Runtime | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | + //|----------------------------- |----- |-------- |---------:|-----------:|----------:|------:|--------:|------:|------:|------:|----------:| + //| StandardStreamReadByte | Clr | Clr | 96.71 us | 5.9950 us | 0.3286 us | 1.00 | 0.00 | - | - | - | - | + //| StandardStreamRead | Clr | Clr | 77.73 us | 5.2284 us | 0.2866 us | 0.80 | 0.00 | - | - | - | - | + //| DoubleBufferedStreamReadByte | Clr | Clr | 23.17 us | 26.2354 us | 1.4381 us | 0.24 | 0.01 | - | - | - | - | + //| DoubleBufferedStreamRead | Clr | Clr | 33.35 us | 3.4071 us | 0.1868 us | 0.34 | 0.00 | - | - | - | - | + //| SimpleReadByte | Clr | Clr | 10.85 us | 0.4927 us | 0.0270 us | 0.11 | 0.00 | - | - | - | - | + //| | | | | | | | | | | | | + //| StandardStreamReadByte | Core | Core | 75.35 us | 12.9789 us | 0.7114 us | 1.00 | 0.00 | - | - | - | - | + //| StandardStreamRead | Core | Core | 55.36 us | 1.4432 us | 0.0791 us | 0.73 | 0.01 | - | - | - | - | + //| DoubleBufferedStreamReadByte | Core | Core | 21.47 us | 29.7076 us | 1.6284 us | 0.28 | 0.02 | - | - | - | - | + //| DoubleBufferedStreamRead | Core | Core | 29.67 us | 2.5988 us | 0.1424 us | 0.39 | 0.00 | - | - | - | - | + //| SimpleReadByte | Core | Core | 10.84 us | 0.7567 us | 0.0415 us | 0.14 | 0.00 | - | - | - | - | } diff --git a/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs b/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs index 75bbf21a3..84e2d0616 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs @@ -254,7 +254,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs protected void ForEachSystemDrawingImage(Func operation) { - using (MemoryStream workStream = new MemoryStream()) + using (var workStream = new MemoryStream()) { this.ForEachSystemDrawingImage( diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index e600af785..9af4d57cf 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -1,6 +1,6 @@  - netcoreapp2.1;net461 + netcoreapp2.1;net472 Exe True SixLabors.ImageSharp.Benchmarks diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 73f97bab3..0b727f30c 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -27,8 +27,8 @@ - - + + From 4197e6918ef05fb32d928250a1f0ed25dc4fbff9 Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Sat, 27 Apr 2019 16:36:23 +0200 Subject: [PATCH 095/223] Feature: adaptive histogram equalization (#673) * first version of sliding window adaptive histogram equalization * going now from top to bottom of the image, added more comments * using memory allocator to create the histogram and the cdf * mirroring rows which exceeds the borders * mirroring also left and right borders * gridsize and cliplimit are now parameters of the constructor * using Parallel.For * only applying clipping once, effect applying it multiple times is neglectable * added abstract base class for histogram equalization, added option to enable / disable clipping * small improvements * clipLimit now in percent of the total number of pixels in the grid * optimization: only calculating the cdf until the maximum histogram index * fix: using configuration from the parameter instead of the default * removed unnecessary loops in CalculateCdf, fixed typo in method name AddPixelsToHistogram * added different approach for ahe: image is split up in tiles, cdf is computed for each tile. Grey value will be determined by interpolating between 4 tiles * simplified interpolation between the tiles * number of tiles is now fixed and depended on the width and height of the image * moved calculating LUT's into separate method * number of tiles is now part of the options and will be used with the sliding window approach also, so both methods are comparable * removed no longer valid xml comment * attempt fixing the borders * refactoring to improve readability * linear interpolation in the border tiles * refactored processing the borders into separate methods * fixing corner tiles * fixed build errors * fixing mistake during merge from upstream: setting test images to "update Resize reference output because of improved ResizeKernelMap calculations" * using Parallel.ForEach for all inner tile calculations * using Parallel.ForEach to calculate the lookup tables * re-using pre allocated pixel row in GetPixelRow * fixed issue with the border tiles, when tile width != tile height * changed default value for ClipHistogram to false again * alpha channel from the original image is now preserved * added unit tests for adaptive histogram equalization * Update External * 2x faster adaptive tiled processor * Remove double indexing and bounds checks * Begin optimizing the global histogram * Parallelize GlobalHistogramEqualizationProcessor * Moving sliding window from left to right instead of from top to bottom * The tile width and height is again depended on the image width: image.Width / Tiles * Removed keeping track of the maximum histogram position * Updated reference image for sliding window AHE for moving the sliding window from left to right * Removed unnecessary call to Span.Clear(), all values are overwritten anyway * Revert "Moving sliding window from left to right instead of from top to bottom" This reverts commit 8f19e5edd23f13fd1ddf93b4e795f82e7f1334bb. # Conflicts: # src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs * Split GetPixelRow in two version: one which mirrors the edges (only needed in the borders of the images) and one which does not * Refactoring and cleanup sliding window processor * Added an upper limit of 100 tiles * Performance tweaks * Update External --- src/ImageSharp/Common/Helpers/ImageMaths.cs | 1 - .../HistogramEqualizationExtension.cs | 40 +- .../AdaptiveHistEqualizationProcessor.cs | 545 ++++++++++++++++++ .../AdaptiveHistEqualizationSWProcessor.cs | 389 +++++++++++++ .../GlobalHistogramEqualizationProcessor.cs | 106 ++++ .../HistogramEqualizationMethod.cs | 26 + .../HistogramEqualizationOptions.cs | 43 ++ .../HistogramEqualizationProcessor.cs | 138 +++-- .../General/BasicMath/Round.cs | 22 + .../HistogramEqualizationTests.cs | 87 ++- tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/External | 2 +- .../Jpg/baseline/AsianCarvingLowContrast.jpg | Bin 0 -> 187216 bytes 13 files changed, 1308 insertions(+), 92 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs create mode 100644 src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs create mode 100644 src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs create mode 100644 src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationMethod.cs create mode 100644 src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs create mode 100644 tests/ImageSharp.Benchmarks/General/BasicMath/Round.cs create mode 100644 tests/Images/Input/Jpg/baseline/AsianCarvingLowContrast.jpg diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs index 0c5b05180..64bcb11c9 100644 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs @@ -5,7 +5,6 @@ using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.Primitives; namespace SixLabors.ImageSharp diff --git a/src/ImageSharp/Processing/HistogramEqualizationExtension.cs b/src/ImageSharp/Processing/HistogramEqualizationExtension.cs index 8dabfcc05..d967ef362 100644 --- a/src/ImageSharp/Processing/HistogramEqualizationExtension.cs +++ b/src/ImageSharp/Processing/HistogramEqualizationExtension.cs @@ -12,25 +12,51 @@ namespace SixLabors.ImageSharp.Processing public static class HistogramEqualizationExtension { /// - /// Equalizes the histogram of an image to increases the global contrast using 65536 luminance levels. + /// Equalizes the histogram of an image to increases the contrast. /// /// The pixel format. /// The image this method extends. /// The . public static IImageProcessingContext HistogramEqualization(this IImageProcessingContext source) where TPixel : struct, IPixel - => HistogramEqualization(source, 65536); + => HistogramEqualization(source, HistogramEqualizationOptions.Default); /// - /// Equalizes the histogram of an image to increases the global contrast. + /// Equalizes the histogram of an image to increases the contrast. /// /// The pixel format. /// The image this method extends. - /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images - /// or 65536 for 16-bit grayscale images. + /// The histogram equalization options to use. /// The . - public static IImageProcessingContext HistogramEqualization(this IImageProcessingContext source, int luminanceLevels) + public static IImageProcessingContext HistogramEqualization(this IImageProcessingContext source, HistogramEqualizationOptions options) where TPixel : struct, IPixel - => source.ApplyProcessor(new HistogramEqualizationProcessor(luminanceLevels)); + => source.ApplyProcessor(GetProcessor(options)); + + private static HistogramEqualizationProcessor GetProcessor(HistogramEqualizationOptions options) + where TPixel : struct, IPixel + { + HistogramEqualizationProcessor processor; + + switch (options.Method) + { + case HistogramEqualizationMethod.Global: + processor = new GlobalHistogramEqualizationProcessor(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage); + break; + + case HistogramEqualizationMethod.AdaptiveTileInterpolation: + processor = new AdaptiveHistEqualizationProcessor(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage, options.Tiles); + break; + + case HistogramEqualizationMethod.AdaptiveSlidingWindow: + processor = new AdaptiveHistEqualizationSWProcessor(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage, options.Tiles); + break; + + default: + processor = new GlobalHistogramEqualizationProcessor(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage); + break; + } + + return processor; + } } } diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs new file mode 100644 index 000000000..cb52a88b7 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs @@ -0,0 +1,545 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Normalization +{ + /// + /// Applies an adaptive histogram equalization to the image. The image is split up in tiles. For each tile a cumulative distribution function (cdf) is calculated. + /// To calculate the final equalized pixel value, the cdf value of four adjacent tiles will be interpolated. + /// + /// The pixel format. + internal class AdaptiveHistEqualizationProcessor : HistogramEqualizationProcessor + where TPixel : struct, IPixel + { + /// + /// Initializes a new instance of the class. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// Indicating whether to clip the histogram bins at a specific value. + /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. + /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. + public AdaptiveHistEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int tiles) + : base(luminanceLevels, clipHistogram, clipLimitPercentage) + { + Guard.MustBeGreaterThanOrEqualTo(tiles, 2, nameof(tiles)); + Guard.MustBeLessThanOrEqualTo(tiles, 100, nameof(tiles)); + + this.Tiles = tiles; + } + + /// + /// Gets the number of tiles the image is split into (horizontal and vertically) for the adaptive histogram equalization. + /// + private int Tiles { get; } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + int sourceWidth = source.Width; + int sourceHeight = source.Height; + int numberOfPixels = sourceWidth * sourceHeight; + int tileWidth = (int)MathF.Ceiling(sourceWidth / (float)this.Tiles); + int tileHeight = (int)MathF.Ceiling(sourceHeight / (float)this.Tiles); + int pixelsInTile = tileWidth * tileHeight; + int halfTileWidth = tileWidth / 2; + int halfTileHeight = tileHeight / 2; + int luminanceLevels = this.LuminanceLevels; + + // The image is split up into tiles. For each tile the cumulative distribution function will be calculated. + using (var cdfData = new CdfTileData(configuration, sourceWidth, sourceHeight, this.Tiles, this.Tiles, tileWidth, tileHeight, luminanceLevels)) + { + cdfData.CalculateLookupTables(source, this); + + var tileYStartPositions = new List<(int y, int cdfY)>(); + int cdfY = 0; + for (int y = halfTileHeight; y < sourceHeight - halfTileHeight; y += tileHeight) + { + tileYStartPositions.Add((y, cdfY)); + cdfY++; + } + + Parallel.For( + 0, + tileYStartPositions.Count, + new ParallelOptions() { MaxDegreeOfParallelism = configuration.MaxDegreeOfParallelism }, + index => + { + int cdfX = 0; + int tileX = 0; + int tileY = 0; + int y = tileYStartPositions[index].y; + int cdfYY = tileYStartPositions[index].cdfY; + + // It's unfortunate that we have to do this per iteration. + ref TPixel sourceBase = ref source.GetPixelReference(0, 0); + + cdfX = 0; + for (int x = halfTileWidth; x < sourceWidth - halfTileWidth; x += tileWidth) + { + tileY = 0; + int yEnd = Math.Min(y + tileHeight, sourceHeight); + int xEnd = Math.Min(x + tileWidth, sourceWidth); + for (int dy = y; dy < yEnd; dy++) + { + int dyOffSet = dy * sourceWidth; + tileX = 0; + for (int dx = x; dx < xEnd; dx++) + { + ref TPixel pixel = ref Unsafe.Add(ref sourceBase, dyOffSet + dx); + float luminanceEqualized = InterpolateBetweenFourTiles( + pixel, + cdfData, + this.Tiles, + this.Tiles, + tileX, + tileY, + cdfX, + cdfYY, + tileWidth, + tileHeight, + luminanceLevels); + + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + tileX++; + } + + tileY++; + } + + cdfX++; + } + }); + + ref TPixel pixelsBase = ref source.GetPixelReference(0, 0); + + // Fix left column + ProcessBorderColumn(ref pixelsBase, cdfData, 0, sourceWidth, sourceHeight, tileWidth, tileHeight, xStart: 0, xEnd: halfTileWidth, luminanceLevels); + + // Fix right column + int rightBorderStartX = ((this.Tiles - 1) * tileWidth) + halfTileWidth; + ProcessBorderColumn(ref pixelsBase, cdfData, this.Tiles - 1, sourceWidth, sourceHeight, tileWidth, tileHeight, xStart: rightBorderStartX, xEnd: sourceWidth, luminanceLevels); + + // Fix top row + ProcessBorderRow(ref pixelsBase, cdfData, 0, sourceWidth, tileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + + // Fix bottom row + int bottomBorderStartY = ((this.Tiles - 1) * tileHeight) + halfTileHeight; + ProcessBorderRow(ref pixelsBase, cdfData, this.Tiles - 1, sourceWidth, tileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + + // Left top corner + ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, 0, 0, xStart: 0, xEnd: halfTileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + + // Left bottom corner + ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, 0, this.Tiles - 1, xStart: 0, xEnd: halfTileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + + // Right top corner + ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, this.Tiles - 1, 0, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + + // Right bottom corner + ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, this.Tiles - 1, this.Tiles - 1, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + } + } + + /// + /// Processes the part of a corner tile which was previously left out. It consists of 1 / 4 of a tile and does not need interpolation. + /// + /// The output pixels base reference. + /// The lookup table to remap the grey values. + /// The source image width. + /// The x-position in the CDF lookup map. + /// The y-position in the CDF lookup map. + /// X start position. + /// X end position. + /// Y start position. + /// Y end position. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + private static void ProcessCornerTile( + ref TPixel pixelsBase, + CdfTileData cdfData, + int sourceWidth, + int cdfX, + int cdfY, + int xStart, + int xEnd, + int yStart, + int yEnd, + int luminanceLevels) + { + for (int dy = yStart; dy < yEnd; dy++) + { + int dyOffSet = dy * sourceWidth; + for (int dx = xStart; dx < xEnd; dx++) + { + ref TPixel pixel = ref Unsafe.Add(ref pixelsBase, dyOffSet + dx); + float luminanceEqualized = cdfData.RemapGreyValue(cdfX, cdfY, GetLuminance(pixel, luminanceLevels)); + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + } + } + } + + /// + /// Processes a border column of the image which is half the size of the tile width. + /// + /// The output pixels reference. + /// The pre-computed lookup tables to remap the grey values for each tiles. + /// The X index of the lookup table to use. + /// The source image width. + /// The source image height. + /// The width of a tile. + /// The height of a tile. + /// X start position in the image. + /// X end position of the image. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + private static void ProcessBorderColumn( + ref TPixel pixelBase, + CdfTileData cdfData, + int cdfX, + int sourceWidth, + int sourceHeight, + int tileWidth, + int tileHeight, + int xStart, + int xEnd, + int luminanceLevels) + { + int halfTileWidth = tileWidth / 2; + int halfTileHeight = tileHeight / 2; + + int cdfY = 0; + for (int y = halfTileHeight; y < sourceHeight - halfTileHeight; y += tileHeight) + { + int yLimit = Math.Min(y + tileHeight, sourceHeight - 1); + int tileY = 0; + for (int dy = y; dy < yLimit; dy++) + { + int dyOffSet = dy * sourceWidth; + int tileX = halfTileWidth; + for (int dx = xStart; dx < xEnd; dx++) + { + ref TPixel pixel = ref Unsafe.Add(ref pixelBase, dyOffSet + dx); + float luminanceEqualized = InterpolateBetweenTwoTiles(pixel, cdfData, cdfX, cdfY, cdfX, cdfY + 1, tileY, tileHeight, luminanceLevels); + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + tileX++; + } + + tileY++; + } + + cdfY++; + } + } + + /// + /// Processes a border row of the image which is half of the size of the tile height. + /// + /// The output pixels base reference. + /// The pre-computed lookup tables to remap the grey values for each tiles. + /// The Y index of the lookup table to use. + /// The source image width. + /// The width of a tile. + /// Y start position in the image. + /// Y end position of the image. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + private static void ProcessBorderRow( + ref TPixel pixelBase, + CdfTileData cdfData, + int cdfY, + int sourceWidth, + int tileWidth, + int yStart, + int yEnd, + int luminanceLevels) + { + int halfTileWidth = tileWidth / 2; + + int cdfX = 0; + for (int x = halfTileWidth; x < sourceWidth - halfTileWidth; x += tileWidth) + { + int tileY = 0; + for (int dy = yStart; dy < yEnd; dy++) + { + int dyOffSet = dy * sourceWidth; + int tileX = 0; + int xLimit = Math.Min(x + tileWidth, sourceWidth - 1); + for (int dx = x; dx < xLimit; dx++) + { + ref TPixel pixel = ref Unsafe.Add(ref pixelBase, dyOffSet + dx); + float luminanceEqualized = InterpolateBetweenTwoTiles(pixel, cdfData, cdfX, cdfY, cdfX + 1, cdfY, tileX, tileWidth, luminanceLevels); + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + tileX++; + } + + tileY++; + } + + cdfX++; + } + } + + /// + /// Bilinear interpolation between four adjacent tiles. + /// + /// The pixel to remap the grey value from. + /// The pre-computed lookup tables to remap the grey values for each tiles. + /// The number of tiles in the x-direction. + /// The number of tiles in the y-direction. + /// X position inside the tile. + /// Y position inside the tile. + /// X index of the top left lookup table to use. + /// Y index of the top left lookup table to use. + /// Width of one tile in pixels. + /// Height of one tile in pixels. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + /// A re-mapped grey value. + [MethodImpl(InliningOptions.ShortMethod)] + private static float InterpolateBetweenFourTiles( + TPixel sourcePixel, + CdfTileData cdfData, + int tileCountX, + int tileCountY, + int tileX, + int tileY, + int cdfX, + int cdfY, + int tileWidth, + int tileHeight, + int luminanceLevels) + { + int luminance = GetLuminance(sourcePixel, luminanceLevels); + float tx = tileX / (float)(tileWidth - 1); + float ty = tileY / (float)(tileHeight - 1); + + int yTop = cdfY; + int yBottom = Math.Min(tileCountY - 1, yTop + 1); + int xLeft = cdfX; + int xRight = Math.Min(tileCountX - 1, xLeft + 1); + + float cdfLeftTopLuminance = cdfData.RemapGreyValue(xLeft, yTop, luminance); + float cdfRightTopLuminance = cdfData.RemapGreyValue(xRight, yTop, luminance); + float cdfLeftBottomLuminance = cdfData.RemapGreyValue(xLeft, yBottom, luminance); + float cdfRightBottomLuminance = cdfData.RemapGreyValue(xRight, yBottom, luminance); + return BilinearInterpolation(tx, ty, cdfLeftTopLuminance, cdfRightTopLuminance, cdfLeftBottomLuminance, cdfRightBottomLuminance); + } + + /// + /// Linear interpolation between two tiles. + /// + /// The pixel to remap the grey value from. + /// The CDF lookup map. + /// X position inside the first tile. + /// Y position inside the first tile. + /// X position inside the second tile. + /// Y position inside the second tile. + /// Position inside the tile. + /// Width of the tile. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + /// A re-mapped grey value. + [MethodImpl(InliningOptions.ShortMethod)] + private static float InterpolateBetweenTwoTiles( + TPixel sourcePixel, + CdfTileData cdfData, + int tileX1, + int tileY1, + int tileX2, + int tileY2, + int tilePos, + int tileWidth, + int luminanceLevels) + { + int luminance = GetLuminance(sourcePixel, luminanceLevels); + float tx = tilePos / (float)(tileWidth - 1); + + float cdfLuminance1 = cdfData.RemapGreyValue(tileX1, tileY1, luminance); + float cdfLuminance2 = cdfData.RemapGreyValue(tileX2, tileY2, luminance); + return LinearInterpolation(cdfLuminance1, cdfLuminance2, tx); + } + + /// + /// Bilinear interpolation between four tiles. + /// + /// The interpolation value in x direction in the range of [0, 1]. + /// The interpolation value in y direction in the range of [0, 1]. + /// Luminance from top left tile. + /// Luminance from right top tile. + /// Luminance from left bottom tile. + /// Luminance from right bottom tile. + /// Interpolated Luminance. + [MethodImpl(InliningOptions.ShortMethod)] + private static float BilinearInterpolation(float tx, float ty, float lt, float rt, float lb, float rb) + => LinearInterpolation(LinearInterpolation(lt, rt, tx), LinearInterpolation(lb, rb, tx), ty); + + /// + /// Linear interpolation between two grey values. + /// + /// The left value. + /// The right value. + /// The interpolation value between the two values in the range of [0, 1]. + /// The interpolated value. + [MethodImpl(InliningOptions.ShortMethod)] + private static float LinearInterpolation(float left, float right, float t) + => left + ((right - left) * t); + + /// + /// Contains the results of the cumulative distribution function for all tiles. + /// + private sealed class CdfTileData : IDisposable + { + private readonly Configuration configuration; + private readonly MemoryAllocator memoryAllocator; + + // Used for storing the minimum value for each CDF entry. + private readonly Buffer2D cdfMinBuffer2D; + + // Used for storing the LUT for each CDF entry. + private readonly Buffer2D cdfLutBuffer2D; + private readonly int pixelsInTile; + private readonly int sourceWidth; + private readonly int sourceHeight; + private readonly int tileWidth; + private readonly int tileHeight; + private readonly int luminanceLevels; + private readonly List<(int y, int cdfY)> tileYStartPositions; + + public CdfTileData( + Configuration configuration, + int sourceWidth, + int sourceHeight, + int tileCountX, + int tileCountY, + int tileWidth, + int tileHeight, + int luminanceLevels) + { + this.configuration = configuration; + this.memoryAllocator = configuration.MemoryAllocator; + this.luminanceLevels = luminanceLevels; + this.cdfMinBuffer2D = this.memoryAllocator.Allocate2D(tileCountX, tileCountY); + this.cdfLutBuffer2D = this.memoryAllocator.Allocate2D(tileCountX * luminanceLevels, tileCountY); + this.sourceWidth = sourceWidth; + this.sourceHeight = sourceHeight; + this.tileWidth = tileWidth; + this.tileHeight = tileHeight; + this.pixelsInTile = tileWidth * tileHeight; + + // Calculate the start positions and rent buffers. + this.tileYStartPositions = new List<(int y, int cdfY)>(); + int cdfY = 0; + for (int y = 0; y < sourceHeight; y += tileHeight) + { + this.tileYStartPositions.Add((y, cdfY)); + cdfY++; + } + } + + public void CalculateLookupTables(ImageFrame source, HistogramEqualizationProcessor processor) + { + int sourceWidth = this.sourceWidth; + int sourceHeight = this.sourceHeight; + int tileWidth = this.tileWidth; + int tileHeight = this.tileHeight; + int luminanceLevels = this.luminanceLevels; + MemoryAllocator memoryAllocator = this.memoryAllocator; + + Parallel.For( + 0, + this.tileYStartPositions.Count, + new ParallelOptions() { MaxDegreeOfParallelism = this.configuration.MaxDegreeOfParallelism }, + index => + { + int cdfX = 0; + int cdfY = this.tileYStartPositions[index].cdfY; + int y = this.tileYStartPositions[index].y; + int endY = Math.Min(y + tileHeight, sourceHeight); + ref TPixel sourceBase = ref source.GetPixelReference(0, 0); + ref int cdfMinBase = ref MemoryMarshal.GetReference(this.cdfMinBuffer2D.GetRowSpan(cdfY)); + + using (IMemoryOwner histogramBuffer = this.memoryAllocator.Allocate(luminanceLevels)) + { + Span histogram = histogramBuffer.GetSpan(); + ref int histogramBase = ref MemoryMarshal.GetReference(histogram); + + for (int x = 0; x < sourceWidth; x += tileWidth) + { + histogram.Clear(); + ref int cdfBase = ref MemoryMarshal.GetReference(this.GetCdfLutSpan(cdfX, index)); + + int xlimit = Math.Min(x + tileWidth, sourceWidth); + for (int dy = y; dy < endY; dy++) + { + int dyOffset = dy * sourceWidth; + for (int dx = x; dx < xlimit; dx++) + { + int luminace = GetLuminance(Unsafe.Add(ref sourceBase, dyOffset + dx), luminanceLevels); + histogram[luminace]++; + } + } + + if (processor.ClipHistogramEnabled) + { + processor.ClipHistogram(histogram, processor.ClipLimitPercentage, this.pixelsInTile); + } + + Unsafe.Add(ref cdfMinBase, cdfX) = processor.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); + + cdfX++; + } + } + }); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public Span GetCdfLutSpan(int tileX, int tileY) => this.cdfLutBuffer2D.GetRowSpan(tileY).Slice(tileX * this.luminanceLevels, this.luminanceLevels); + + /// + /// Remaps the grey value with the cdf. + /// + /// The tiles x-position. + /// The tiles y-position. + /// The original luminance. + /// The remapped luminance. + [MethodImpl(InliningOptions.ShortMethod)] + public float RemapGreyValue(int tilesX, int tilesY, int luminance) + { + int cdfMin = this.cdfMinBuffer2D[tilesX, tilesY]; + Span cdfSpan = this.GetCdfLutSpan(tilesX, tilesY); + return (this.pixelsInTile - cdfMin) == 0 + ? cdfSpan[luminance] / this.pixelsInTile + : cdfSpan[luminance] / (float)(this.pixelsInTile - cdfMin); + } + + public void Dispose() + { + this.cdfMinBuffer2D.Dispose(); + this.cdfLutBuffer2D.Dispose(); + } + } + } +} diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs new file mode 100644 index 000000000..aa9b530c6 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs @@ -0,0 +1,389 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Normalization +{ + /// + /// Applies an adaptive histogram equalization to the image using an sliding window approach. + /// + /// The pixel format. + internal class AdaptiveHistEqualizationSWProcessor : HistogramEqualizationProcessor + where TPixel : struct, IPixel + { + /// + /// Initializes a new instance of the class. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// Indicating whether to clip the histogram bins at a specific value. + /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. + /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. + public AdaptiveHistEqualizationSWProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int tiles) + : base(luminanceLevels, clipHistogram, clipLimitPercentage) + { + Guard.MustBeGreaterThanOrEqualTo(tiles, 2, nameof(tiles)); + Guard.MustBeLessThanOrEqualTo(tiles, 100, nameof(tiles)); + + this.Tiles = tiles; + } + + /// + /// Gets the number of tiles the image is split into (horizontal and vertically) for the adaptive histogram equalization. + /// + private int Tiles { get; } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + MemoryAllocator memoryAllocator = configuration.MemoryAllocator; + int numberOfPixels = source.Width * source.Height; + Span pixels = source.GetPixelSpan(); + + var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = configuration.MaxDegreeOfParallelism }; + int tileWidth = source.Width / this.Tiles; + int tileHeight = tileWidth; + int pixeInTile = tileWidth * tileHeight; + int halfTileHeight = tileHeight / 2; + int halfTileWidth = halfTileHeight; + var slidingWindowInfos = new SlidingWindowInfos(tileWidth, tileHeight, halfTileWidth, halfTileHeight, pixeInTile); + + using (Buffer2D targetPixels = configuration.MemoryAllocator.Allocate2D(source.Width, source.Height)) + { + // Process the inner tiles, which do not require to check the borders. + Parallel.For( + halfTileWidth, + source.Width - halfTileWidth, + parallelOptions, + this.ProcessSlidingWindow( + source, + memoryAllocator, + targetPixels, + slidingWindowInfos, + yStart: halfTileHeight, + yEnd: source.Height - halfTileHeight, + useFastPath: true, + configuration)); + + // Process the left border of the image. + Parallel.For( + 0, + halfTileWidth, + parallelOptions, + this.ProcessSlidingWindow( + source, + memoryAllocator, + targetPixels, + slidingWindowInfos, + yStart: 0, + yEnd: source.Height, + useFastPath: false, + configuration)); + + // Process the right border of the image. + Parallel.For( + source.Width - halfTileWidth, + source.Width, + parallelOptions, + this.ProcessSlidingWindow( + source, + memoryAllocator, + targetPixels, + slidingWindowInfos, + yStart: 0, + yEnd: source.Height, + useFastPath: false, + configuration)); + + // Process the top border of the image. + Parallel.For( + halfTileWidth, + source.Width - halfTileWidth, + parallelOptions, + this.ProcessSlidingWindow( + source, + memoryAllocator, + targetPixels, + slidingWindowInfos, + yStart: 0, + yEnd: halfTileHeight, + useFastPath: false, + configuration)); + + // Process the bottom border of the image. + Parallel.For( + halfTileWidth, + source.Width - halfTileWidth, + parallelOptions, + this.ProcessSlidingWindow( + source, + memoryAllocator, + targetPixels, + slidingWindowInfos, + yStart: source.Height - halfTileHeight, + yEnd: source.Height, + useFastPath: false, + configuration)); + + Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); + } + } + + /// + /// Applies the sliding window equalization to one column of the image. The window is moved from top to bottom. + /// Moving the window one pixel down requires to remove one row from the top of the window from the histogram and + /// adding a new row at the bottom. + /// + /// The source image. + /// The memory allocator. + /// The target pixels. + /// Informations about the sliding window dimensions. + /// The y start position. + /// The y end position. + /// if set to true the borders of the image will not be checked. + /// The configuration. + /// Action Delegate. + private Action ProcessSlidingWindow( + ImageFrame source, + MemoryAllocator memoryAllocator, + Buffer2D targetPixels, + SlidingWindowInfos swInfos, + int yStart, + int yEnd, + bool useFastPath, + Configuration configuration) + { + return x => + { + using (IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + using (IMemoryOwner histogramBufferCopy = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + using (IMemoryOwner cdfBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + using (IMemoryOwner pixelRowBuffer = memoryAllocator.Allocate(swInfos.TileWidth, AllocationOptions.Clean)) + { + Span histogram = histogramBuffer.GetSpan(); + ref int histogramBase = ref MemoryMarshal.GetReference(histogram); + + Span histogramCopy = histogramBufferCopy.GetSpan(); + ref int histogramCopyBase = ref MemoryMarshal.GetReference(histogramCopy); + + ref int cdfBase = ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()); + + Span pixelRow = pixelRowBuffer.GetSpan(); + ref Vector4 pixelRowBase = ref MemoryMarshal.GetReference(pixelRow); + + // Build the initial histogram of grayscale values. + for (int dy = yStart - swInfos.HalfTileHeight; dy < yStart + swInfos.HalfTileHeight; dy++) + { + if (useFastPath) + { + this.CopyPixelRowFast(source, pixelRow, x - swInfos.HalfTileWidth, dy, swInfos.TileWidth, configuration); + } + else + { + this.CopyPixelRow(source, pixelRow, x - swInfos.HalfTileWidth, dy, swInfos.TileWidth, configuration); + } + + this.AddPixelsToHistogram(ref pixelRowBase, ref histogramBase, this.LuminanceLevels, pixelRow.Length); + } + + for (int y = yStart; y < yEnd; y++) + { + if (this.ClipHistogramEnabled) + { + // Clipping the histogram, but doing it on a copy to keep the original un-clipped values for the next iteration. + histogram.CopyTo(histogramCopy); + this.ClipHistogram(histogramCopy, this.ClipLimitPercentage, swInfos.PixeInTile); + } + + // Calculate the cumulative distribution function, which will map each input pixel in the current tile to a new value. + int cdfMin = this.ClipHistogramEnabled + ? this.CalculateCdf(ref cdfBase, ref histogramCopyBase, histogram.Length - 1) + : this.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); + + float numberOfPixelsMinusCdfMin = swInfos.PixeInTile - cdfMin; + + // Map the current pixel to the new equalized value. + int luminance = GetLuminance(source[x, y], this.LuminanceLevels); + float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / numberOfPixelsMinusCdfMin; + targetPixels[x, y].FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, source[x, y].ToVector4().W)); + + // Remove top most row from the histogram, mirroring rows which exceeds the borders. + if (useFastPath) + { + this.CopyPixelRowFast(source, pixelRow, x - swInfos.HalfTileWidth, y - swInfos.HalfTileWidth, swInfos.TileWidth, configuration); + } + else + { + this.CopyPixelRow(source, pixelRow, x - swInfos.HalfTileWidth, y - swInfos.HalfTileWidth, swInfos.TileWidth, configuration); + } + + this.RemovePixelsFromHistogram(ref pixelRowBase, ref histogramBase, this.LuminanceLevels, pixelRow.Length); + + // Add new bottom row to the histogram, mirroring rows which exceeds the borders. + if (useFastPath) + { + this.CopyPixelRowFast(source, pixelRow, x - swInfos.HalfTileWidth, y + swInfos.HalfTileWidth, swInfos.TileWidth, configuration); + } + else + { + this.CopyPixelRow(source, pixelRow, x - swInfos.HalfTileWidth, y + swInfos.HalfTileWidth, swInfos.TileWidth, configuration); + } + + this.AddPixelsToHistogram(ref pixelRowBase, ref histogramBase, this.LuminanceLevels, pixelRow.Length); + } + } + }; + } + + /// + /// Get the a pixel row at a given position with a length of the tile width. Mirrors pixels which exceeds the edges. + /// + /// The source image. + /// Pre-allocated pixel row span of the size of a the tile width. + /// The x position. + /// The y position. + /// The width in pixels of a tile. + /// The configuration. + private void CopyPixelRow( + ImageFrame source, + Span rowPixels, + int x, + int y, + int tileWidth, + Configuration configuration) + { + if (y < 0) + { + y = ImageMaths.FastAbs(y); + } + else if (y >= source.Height) + { + int diff = y - source.Height; + y = source.Height - diff - 1; + } + + // Special cases for the left and the right border where GetPixelRowSpan can not be used. + if (x < 0) + { + rowPixels.Clear(); + int idx = 0; + for (int dx = x; dx < x + tileWidth; dx++) + { + rowPixels[idx] = source[ImageMaths.FastAbs(dx), y].ToVector4(); + idx++; + } + + return; + } + else if (x + tileWidth > source.Width) + { + rowPixels.Clear(); + int idx = 0; + for (int dx = x; dx < x + tileWidth; dx++) + { + if (dx >= source.Width) + { + int diff = dx - source.Width; + rowPixels[idx] = source[dx - diff - 1, y].ToVector4(); + } + else + { + rowPixels[idx] = source[dx, y].ToVector4(); + } + + idx++; + } + + return; + } + + this.CopyPixelRowFast(source, rowPixels, x, y, tileWidth, configuration); + } + + /// + /// Get the a pixel row at a given position with a length of the tile width. + /// + /// The source image. + /// Pre-allocated pixel row span of the size of a the tile width. + /// The x position. + /// The y position. + /// The width in pixels of a tile. + /// The configuration. + [MethodImpl(InliningOptions.ShortMethod)] + private void CopyPixelRowFast( + ImageFrame source, + Span rowPixels, + int x, + int y, + int tileWidth, + Configuration configuration) + => PixelOperations.Instance.ToVector4(configuration, source.GetPixelRowSpan(y).Slice(start: x, length: tileWidth), rowPixels); + + /// + /// Adds a column of grey values to the histogram. + /// + /// The reference to the span of grey values to add. + /// The reference to the histogram span. + /// The number of different luminance levels. + /// The grey values span length. + [MethodImpl(InliningOptions.ShortMethod)] + private void AddPixelsToHistogram(ref Vector4 greyValuesBase, ref int histogramBase, int luminanceLevels, int length) + { + for (int idx = 0; idx < length; idx++) + { + int luminance = GetLuminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels); + Unsafe.Add(ref histogramBase, luminance)++; + } + } + + /// + /// Removes a column of grey values from the histogram. + /// + /// The reference to the span of grey values to remove. + /// The reference to the histogram span. + /// The number of different luminance levels. + /// The grey values span length. + [MethodImpl(InliningOptions.ShortMethod)] + private void RemovePixelsFromHistogram(ref Vector4 greyValuesBase, ref int histogramBase, int luminanceLevels, int length) + { + for (int idx = 0; idx < length; idx++) + { + int luminance = GetLuminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels); + Unsafe.Add(ref histogramBase, luminance)--; + } + } + + private class SlidingWindowInfos + { + public SlidingWindowInfos(int tileWidth, int tileHeight, int halfTileWidth, int halfTileHeight, int pixeInTile) + { + this.TileWidth = tileWidth; + this.TileHeight = tileHeight; + this.HalfTileWidth = halfTileWidth; + this.HalfTileHeight = halfTileHeight; + this.PixeInTile = pixeInTile; + } + + public int TileWidth { get; private set; } + + public int TileHeight { get; private set; } + + public int PixeInTile { get; private set; } + + public int HalfTileWidth { get; private set; } + + public int HalfTileHeight { get; private set; } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs new file mode 100644 index 000000000..aadde2424 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs @@ -0,0 +1,106 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Normalization +{ + /// + /// Applies a global histogram equalization to the image. + /// + /// The pixel format. + internal class GlobalHistogramEqualizationProcessor : HistogramEqualizationProcessor + where TPixel : struct, IPixel + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + /// Indicating whether to clip the histogram bins at a specific value. + /// Histogram clip limit in percent of the total pixels. Histogram bins which exceed this limit, will be capped at this value. + public GlobalHistogramEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage) + : base(luminanceLevels, clipHistogram, clipLimitPercentage) + { + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + MemoryAllocator memoryAllocator = configuration.MemoryAllocator; + int numberOfPixels = source.Width * source.Height; + Span pixels = source.GetPixelSpan(); + var workingRect = new Rectangle(0, 0, source.Width, source.Height); + + using (IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + using (IMemoryOwner cdfBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + { + // Build the histogram of the grayscale levels. + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + ref int histogramBase = ref MemoryMarshal.GetReference(histogramBuffer.GetSpan()); + for (int y = rows.Min; y < rows.Max; y++) + { + ref TPixel pixelBase = ref MemoryMarshal.GetReference(source.GetPixelRowSpan(y)); + + for (int x = 0; x < workingRect.Width; x++) + { + int luminance = GetLuminance(Unsafe.Add(ref pixelBase, x), this.LuminanceLevels); + Unsafe.Add(ref histogramBase, luminance)++; + } + } + }); + + Span histogram = histogramBuffer.GetSpan(); + if (this.ClipHistogramEnabled) + { + this.ClipHistogram(histogram, this.ClipLimitPercentage, numberOfPixels); + } + + // Calculate the cumulative distribution function, which will map each input pixel to a new value. + int cdfMin = this.CalculateCdf( + ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()), + ref MemoryMarshal.GetReference(histogram), + histogram.Length - 1); + + float numberOfPixelsMinusCdfMin = numberOfPixels - cdfMin; + + // Apply the cdf to each pixel of the image + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + ref int cdfBase = ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()); + for (int y = rows.Min; y < rows.Max; y++) + { + ref TPixel pixelBase = ref MemoryMarshal.GetReference(source.GetPixelRowSpan(y)); + + for (int x = 0; x < workingRect.Width; x++) + { + ref TPixel pixel = ref Unsafe.Add(ref pixelBase, x); + int luminance = GetLuminance(pixel, this.LuminanceLevels); + float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / numberOfPixelsMinusCdfMin; + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + } + } + }); + } + } + } +} diff --git a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationMethod.cs b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationMethod.cs new file mode 100644 index 000000000..641587c39 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationMethod.cs @@ -0,0 +1,26 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Processing.Processors.Normalization +{ + /// + /// Enumerates the different types of defined histogram equalization methods. + /// + public enum HistogramEqualizationMethod : int + { + /// + /// A global histogram equalization. + /// + Global, + + /// + /// Adaptive histogram equalization using a tile interpolation approach. + /// + AdaptiveTileInterpolation, + + /// + /// Adaptive histogram equalization using sliding window. Slower then the tile interpolation mode, but can yield to better results. + /// + AdaptiveSlidingWindow, + } +} diff --git a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs new file mode 100644 index 000000000..0d1a37836 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs @@ -0,0 +1,43 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Processing.Processors.Normalization +{ + /// + /// Data container providing the different options for the histogram equalization. + /// + public class HistogramEqualizationOptions + { + /// + /// Gets the default instance. + /// + public static HistogramEqualizationOptions Default { get; } = new HistogramEqualizationOptions(); + + /// + /// Gets or sets the histogram equalization method to use. Defaults to global histogram equalization. + /// + public HistogramEqualizationMethod Method { get; set; } = HistogramEqualizationMethod.Global; + + /// + /// Gets or sets the number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. Defaults to 256. + /// + public int LuminanceLevels { get; set; } = 256; + + /// + /// Gets or sets a value indicating whether to clip the histogram bins at a specific value. Defaults to false. + /// + public bool ClipHistogram { get; set; } = false; + + /// + /// Gets or sets the histogram clip limit in percent of the total pixels in a tile. Histogram bins which exceed this limit, will be capped at this value. + /// Defaults to 0.035f. + /// + public float ClipLimitPercentage { get; set; } = 0.035f; + + /// + /// Gets or sets the number of tiles the image is split into (horizontal and vertically) for the adaptive histogram equalization. Defaults to 10. + /// + public int Tiles { get; set; } = 10; + } +} diff --git a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs index 580adc7fe..fd1b6b978 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs @@ -2,34 +2,38 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Normalization { /// - /// Applies a global histogram equalization to the image. + /// Defines a processor that normalizes the histogram of an image. /// /// The pixel format. - internal class HistogramEqualizationProcessor : ImageProcessor + internal abstract class HistogramEqualizationProcessor : ImageProcessor where TPixel : struct, IPixel { + private readonly float luminanceLevelsFloat; + /// /// Initializes a new instance of the class. /// /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images /// or 65536 for 16-bit grayscale images. - public HistogramEqualizationProcessor(int luminanceLevels) + /// Indicates, if histogram bins should be clipped. + /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. + protected HistogramEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage) { Guard.MustBeGreaterThan(luminanceLevels, 0, nameof(luminanceLevels)); + Guard.MustBeGreaterThan(clipLimitPercentage, 0F, nameof(clipLimitPercentage)); this.LuminanceLevels = luminanceLevels; + this.luminanceLevelsFloat = luminanceLevels; + this.ClipHistogramEnabled = clipHistogram; + this.ClipLimitPercentage = clipLimitPercentage; } /// @@ -37,77 +41,77 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// public int LuminanceLevels { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + /// Gets a value indicating whether to clip the histogram bins at a specific value. + /// + public bool ClipHistogramEnabled { get; } + + /// + /// Gets the histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. + /// + public float ClipLimitPercentage { get; } + + /// + /// Calculates the cumulative distribution function. + /// + /// The reference to the array holding the cdf. + /// The reference to the histogram of the input image. + /// Index of the maximum of the histogram. + /// The first none zero value of the cdf. + public int CalculateCdf(ref int cdfBase, ref int histogramBase, int maxIdx) { - MemoryAllocator memoryAllocator = configuration.MemoryAllocator; - int numberOfPixels = source.Width * source.Height; - Span pixels = source.GetPixelSpan(); + int histSum = 0; + int cdfMin = 0; + bool cdfMinFound = false; - // Build the histogram of the grayscale levels. - using (IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) - using (IMemoryOwner cdfBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + for (int i = 0; i <= maxIdx; i++) { - Span histogram = histogramBuffer.GetSpan(); - for (int i = 0; i < pixels.Length; i++) + histSum += Unsafe.Add(ref histogramBase, i); + if (!cdfMinFound && histSum != 0) { - TPixel sourcePixel = pixels[i]; - int luminance = this.GetLuminance(sourcePixel, this.LuminanceLevels); - histogram[luminance]++; + cdfMin = histSum; + cdfMinFound = true; } - // Calculate the cumulative distribution function, which will map each input pixel to a new value. - Span cdf = cdfBuffer.GetSpan(); - int cdfMin = this.CalculateCdf(cdf, histogram); - - // Apply the cdf to each pixel of the image - float numberOfPixelsMinusCdfMin = numberOfPixels - cdfMin; - for (int i = 0; i < pixels.Length; i++) - { - TPixel sourcePixel = pixels[i]; - - int luminance = this.GetLuminance(sourcePixel, this.LuminanceLevels); - float luminanceEqualized = cdf[luminance] / numberOfPixelsMinusCdfMin; - - pixels[i].FromVector4(new Vector4(luminanceEqualized)); - } + // Creating the lookup table: subtracting cdf min, so we do not need to do that inside the for loop. + Unsafe.Add(ref cdfBase, i) = Math.Max(0, histSum - cdfMin); } + + return cdfMin; } /// - /// Calculates the cumulative distribution function. + /// AHE tends to over amplify the contrast in near-constant regions of the image, since the histogram in such regions is highly concentrated. + /// Clipping the histogram is meant to reduce this effect, by cutting of histogram bin's which exceed a certain amount and redistribute + /// the values over the clip limit to all other bins equally. /// - /// The array holding the cdf. - /// The histogram of the input image. - /// The first none zero value of the cdf. - private int CalculateCdf(Span cdf, Span histogram) + /// The histogram to apply the clipping. + /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. + /// The numbers of pixels inside the tile. + public void ClipHistogram(Span histogram, float clipLimitPercentage, int pixelCount) { - // Calculate the cumulative histogram - int histSum = 0; - for (int i = 0; i < histogram.Length; i++) - { - histSum += histogram[i]; - cdf[i] = histSum; - } + int clipLimit = (int)MathF.Round(pixelCount * clipLimitPercentage); + int sumOverClip = 0; + ref int histogramBase = ref MemoryMarshal.GetReference(histogram); - // Get the first none zero value of the cumulative histogram - int cdfMin = 0; for (int i = 0; i < histogram.Length; i++) { - if (cdf[i] != 0) + ref int histogramLevel = ref Unsafe.Add(ref histogramBase, i); + if (histogramLevel > clipLimit) { - cdfMin = cdf[i]; - break; + sumOverClip += histogramLevel - clipLimit; + histogramLevel = clipLimit; } } - // Creating the lookup table: subtracting cdf min, so we do not need to do that inside the for loop - for (int i = 0; i < histogram.Length; i++) + int addToEachBin = sumOverClip > 0 ? (int)MathF.Floor(sumOverClip / this.luminanceLevelsFloat) : 0; + if (addToEachBin > 0) { - cdf[i] = Math.Max(0, cdf[i] - cdfMin); + for (int i = 0; i < histogram.Length; i++) + { + Unsafe.Add(ref histogramBase, i) += addToEachBin; + } } - - return cdfMin; } /// @@ -116,13 +120,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// The pixel to get the luminance from /// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images) [MethodImpl(InliningOptions.ShortMethod)] - private int GetLuminance(TPixel sourcePixel, int luminanceLevels) + public static int GetLuminance(TPixel sourcePixel, int luminanceLevels) { - // Convert to grayscale using ITU-R Recommendation BT.709 var vector = sourcePixel.ToVector4(); - int luminance = Convert.ToInt32(((.2126F * vector.X) + (.7152F * vector.Y) + (.0722F * vector.Y)) * (luminanceLevels - 1)); - - return luminance; + return GetLuminance(ref vector, luminanceLevels); } + + /// + /// Convert the pixel values to grayscale using ITU-R Recommendation BT.709. + /// + /// The vector to get the luminance from + /// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images) + [MethodImpl(InliningOptions.ShortMethod)] + public static int GetLuminance(ref Vector4 vector, int luminanceLevels) + => (int)MathF.Round(((.2126F * vector.X) + (.7152F * vector.Y) + (.0722F * vector.Y)) * (luminanceLevels - 1)); } -} +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/BasicMath/Round.cs b/tests/ImageSharp.Benchmarks/General/BasicMath/Round.cs new file mode 100644 index 000000000..2c18b2972 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/General/BasicMath/Round.cs @@ -0,0 +1,22 @@ +using System; +using BenchmarkDotNet.Attributes; + +namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath +{ + public class Round + { + private const float input = .51F; + + [Benchmark] + public int ConvertTo() => Convert.ToInt32(input); + + [Benchmark] + public int MathRound() => (int)Math.Round(input); + + // Results 20th Jan 2019 + // Method | Mean | Error | StdDev | Median | + //---------- |----------:|----------:|----------:|----------:| + // ConvertTo | 3.1967 ns | 0.1234 ns | 0.2129 ns | 3.2340 ns | + // MathRound | 0.0528 ns | 0.0374 ns | 0.1079 ns | 0.0000 ns | + } +} diff --git a/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs b/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs index 1595ed32c..84d592bd9 100644 --- a/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs +++ b/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs @@ -3,12 +3,16 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Normalization; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Normalization { public class HistogramEqualizationTests { + private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.0456F); + [Theory] [InlineData(256)] [InlineData(65536)] @@ -27,18 +31,19 @@ namespace SixLabors.ImageSharp.Tests.Processing.Normalization 70, 87, 69, 68, 65, 73, 78, 90 }; - var image = new Image(8, 8); - for (int y = 0; y < 8; y++) + using (var image = new Image(8, 8)) { - for (int x = 0; x < 8; x++) + for (int y = 0; y < 8; y++) { - byte luminance = pixels[y * 8 + x]; - image[x, y] = new Rgba32(luminance, luminance, luminance); + for (int x = 0; x < 8; x++) + { + byte luminance = pixels[(y * 8) + x]; + image[x, y] = new Rgba32(luminance, luminance, luminance); + } } - } - byte[] expected = new byte[] - { + byte[] expected = new byte[] + { 0, 12, 53, 32, 146, 53, 174, 53, 57, 32, 12, 227, 219, 202, 32, 154, 65, 85, 93, 239, 251, 227, 65, 158, @@ -47,22 +52,66 @@ namespace SixLabors.ImageSharp.Tests.Processing.Normalization 117, 190, 36, 190, 178, 93, 20, 170, 130, 202, 73, 20, 12, 53, 85, 194, 146, 206, 130, 117, 85, 166, 182, 215 - }; + }; - // Act - image.Mutate(x => x.HistogramEqualization(luminanceLevels)); + // Act + image.Mutate(x => x.HistogramEqualization(new HistogramEqualizationOptions() + { + LuminanceLevels = luminanceLevels + })); - // Assert - for (int y = 0; y < 8; y++) - { - for (int x = 0; x < 8; x++) + // Assert + for (int y = 0; y < 8; y++) { - Rgba32 actual = image[x, y]; - Assert.Equal(expected[y * 8 + x], actual.R); - Assert.Equal(expected[y * 8 + x], actual.G); - Assert.Equal(expected[y * 8 + x], actual.B); + for (int x = 0; x < 8; x++) + { + Rgba32 actual = image[x, y]; + Assert.Equal(expected[(y * 8) + x], actual.R); + Assert.Equal(expected[(y * 8) + x], actual.G); + Assert.Equal(expected[(y * 8) + x], actual.B); + } } } } + + [Theory] + [WithFile(TestImages.Jpeg.Baseline.LowContrast, PixelTypes.Rgba32)] + public void Adaptive_SlidingWindow_15Tiles_WithClipping(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var options = new HistogramEqualizationOptions() + { + Method = HistogramEqualizationMethod.AdaptiveSlidingWindow, + LuminanceLevels = 256, + ClipHistogram = true, + Tiles = 15 + }; + image.Mutate(x => x.HistogramEqualization(options)); + image.DebugSave(provider); + image.CompareToReferenceOutput(ValidatorComparer, provider); + } + } + + [Theory] + [WithFile(TestImages.Jpeg.Baseline.LowContrast, PixelTypes.Rgba32)] + public void Adaptive_TileInterpolation_10Tiles_WithClipping(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var options = new HistogramEqualizationOptions() + { + Method = HistogramEqualizationMethod.AdaptiveTileInterpolation, + LuminanceLevels = 256, + ClipHistogram = true, + Tiles = 10 + }; + image.Mutate(x => x.HistogramEqualization(options)); + image.DebugSave(provider); + image.CompareToReferenceOutput(ValidatorComparer, provider); + } + } } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 8b2fd2e7f..23bebd621 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -141,6 +141,7 @@ namespace SixLabors.ImageSharp.Tests public const string Testorig420 = "Jpg/baseline/testorig.jpg"; public const string MultiScanBaselineCMYK = "Jpg/baseline/MultiScanBaselineCMYK.jpg"; public const string Ratio1x1 = "Jpg/baseline/ratio-1x1.jpg"; + public const string LowContrast = "Jpg/baseline/AsianCarvingLowContrast.jpg"; public const string Testorig12bit = "Jpg/baseline/testorig12.jpg"; public const string YcckSubsample1222 = "Jpg/baseline/ycck-subsample-1222.jpg"; diff --git a/tests/Images/External b/tests/Images/External index 8693e2fd4..1ca515499 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 8693e2fd4577a9ac1a749da8db564095b5a05389 +Subproject commit 1ca515499663e8b0b7c924a49b8d212f7447bdb0 diff --git a/tests/Images/Input/Jpg/baseline/AsianCarvingLowContrast.jpg b/tests/Images/Input/Jpg/baseline/AsianCarvingLowContrast.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c1b13352a06d7933237fc1e6420f462a1df02fbe GIT binary patch literal 187216 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 b;13CXqfz~^8b@DN)fyU5R^Q4$(*gh4w{<6& literal 0 HcmV?d00001 From 02d04c81db538e6a3763c37bba077bda951e4f5b Mon Sep 17 00:00:00 2001 From: BorisTheBrave Date: Sat, 27 Apr 2019 23:27:04 +0100 Subject: [PATCH 096/223] ImageBrush shouldn't Dispose of the image it is using. (#883) Fixes #881 --- .../Processing/ImageBrush{TPixel}.cs | 1 - .../Drawing/FillImageBrushTests.cs | 36 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs index 1ef4bb9ec..cfb3b2ea4 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs @@ -113,7 +113,6 @@ namespace SixLabors.ImageSharp.Processing /// public override void Dispose() { - this.source.Dispose(); } /// diff --git a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs new file mode 100644 index 000000000..772f62d5c --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs @@ -0,0 +1,36 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.Primitives; +using SixLabors.Shapes; + +using Xunit; + +// ReSharper disable InconsistentNaming + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class FillImageBrushTests + { + [Fact] + public void DoesNotDisposeImage() + { + using (var src = new Image(5, 5)) + { + var brush = new ImageBrush(src); + using (var dest = new Image(10, 10)) + { + dest.Mutate(c => c.Fill(brush, new Rectangle(0, 0, 10, 10))); + dest.Mutate(c => c.Fill(brush, new Rectangle(0, 0, 10, 10))); + } + } + } + } +} \ No newline at end of file From ff269db0bdb8c38941acef7f35a55fe3ae3dd92b Mon Sep 17 00:00:00 2001 From: Anthony Truskinger Date: Tue, 30 Apr 2019 21:55:44 +1000 Subject: [PATCH 097/223] Now throws a better excpetion DrawImage source does not overlap target (#877) * No longer throws when DrawImage source does not overlap target Previously, when DrawImage was used to overlay an image, in cases where the source image did not overlap the target image, a very confusing error was reported: "System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: MaxDegreeOfParallelism" Now, when this case happens, the DrawImage method will simply not affect the target image, which is the same way FillRegionProcessor handles such cases. ParallelHelper.IterRows also now does more validation of the input rectangle so that any further cases of this kind of problem throw a more relvant exception. Note I switched from DebugGuard to Guard because IterRows is a public API and thus should always validate its inputs. Fixes #875 * Refines DrawImage non-overlap error logic Adresses PR feedback in #877. Changes DrawImage shortcut to be less than or equal to. Also changes maxX calculation to use `Right` over `Width`. This is a semantic change that reflects intention better. No actual change because Top,Left for that rectanngle should always be 0,0. And adds more informative argument names to ParallelHelper.IterRows error message. * Non-overlapping DrawImage now throws Adressing PR feedback from #877 DrawImage now throws when the source image does not overlap, with a useful error message. Also improved the error messages for IterRows (and added validation to the other IterRows method) * DrawImage overlap test changed to support RELEASE The tests on the CI server are run in RELEASE which wrap the expected exception with an ImageProcessingException. * Adress feedback for DrawImage exception DrawImage throws an ImageProcessor exception which makes it easier to catch. And reverted IterRows to use Guard helpers --- .../Processors/Drawing/DrawImageProcessor.cs | 8 +++- .../Common/ParallelUtils/ParallelHelper.cs | 17 +++++++- .../ImageSharp.Tests/Drawing/DrawImageTest.cs | 42 +++++++++++++++++++ .../Helpers/ParallelHelperTests.cs | 35 ++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs index 0957904c6..6c03537eb 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing Rectangle bounds = targetImage.Bounds(); int minX = Math.Max(this.Location.X, sourceRectangle.X); - int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width); + int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Right); int targetX = minX - this.Location.X; int minY = Math.Max(this.Location.Y, sourceRectangle.Y); @@ -81,6 +81,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + // not a valid operation because rectangle does not overlap with this image. + if (workingRect.Width <= 0 || workingRect.Height <= 0) + { + throw new ImageProcessingException("Cannot draw image because the source image does not overlap the target image."); + } + ParallelHelper.IterateRows( workingRect, configuration, diff --git a/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs b/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs index a930b8390..2c2d045a5 100644 --- a/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs +++ b/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.ParallelUtils in ParallelExecutionSettings parallelSettings, Action body) { - DebugGuard.MustBeGreaterThan(rectangle.Width, 0, nameof(rectangle)); + ValidateRectangle(rectangle); int maxSteps = DivideCeil(rectangle.Width * rectangle.Height, parallelSettings.MinimumPixelsProcessedPerTask); @@ -87,6 +87,8 @@ namespace SixLabors.ImageSharp.ParallelUtils Action> body) where T : unmanaged { + ValidateRectangle(rectangle); + int maxSteps = DivideCeil(rectangle.Width * rectangle.Height, parallelSettings.MinimumPixelsProcessedPerTask); int numOfSteps = Math.Min(parallelSettings.MaxDegreeOfParallelism, maxSteps); @@ -142,5 +144,18 @@ namespace SixLabors.ImageSharp.ParallelUtils [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int DivideCeil(int dividend, int divisor) => 1 + ((dividend - 1) / divisor); + + private static void ValidateRectangle(Rectangle rectangle) + { + Guard.MustBeGreaterThan( + rectangle.Width, + 0, + $"{nameof(rectangle)}.{nameof(rectangle.Width)}"); + + Guard.MustBeGreaterThan( + rectangle.Height, + 0, + $"{nameof(rectangle)}.{nameof(rectangle.Height)}"); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs index 374454afb..b07f50883 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs @@ -131,6 +131,48 @@ namespace SixLabors.ImageSharp.Tests background.DebugSave(provider, testOutputDetails: "Positive"); } } + [Theory] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] + public void ImageShouldHandlePositiveLocationTruncatedOverlay(TestImageProvider provider) + { + using (Image background = provider.GetImage()) + using (var overlay = new Image(50, 50)) + { + overlay.Mutate(x => x.Fill(Rgba32.Black)); + + const int xy = 75; + Rgba32 backgroundPixel = background[xy - 1, xy - 1]; + Rgba32 overlayPixel = overlay[0, 0]; + + background.Mutate(x => x.DrawImage(overlay, new Point(xy, xy), PixelColorBlendingMode.Normal, 1F)); + + Assert.Equal(Rgba32.White, backgroundPixel); + Assert.Equal(overlayPixel, background[xy, xy]); + + background.DebugSave(provider, testOutputDetails: "PositiveTruncated"); + } + } + + [Theory] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, -30)] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, -30)] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, 130)] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, 130)] + public void NonOverlappingImageThrows(TestImageProvider provider, int x, int y) + { + using (Image background = provider.GetImage()) + using (var overlay = new Image(Configuration.Default, 10, 10, Rgba32.Black)) + { + ImageProcessingException ex = Assert.Throws(Test); + + Assert.Contains("does not overlap", ex.ToString()); + + void Test() + { + background.Mutate(context => context.DrawImage(overlay, new Point(x, y), GraphicsOptions.Default)); + } + } + } private static void VerifyImage( TestImageProvider provider, diff --git a/tests/ImageSharp.Tests/Helpers/ParallelHelperTests.cs b/tests/ImageSharp.Tests/Helpers/ParallelHelperTests.cs index ef6b133f7..ee309e0e3 100644 --- a/tests/ImageSharp.Tests/Helpers/ParallelHelperTests.cs +++ b/tests/ImageSharp.Tests/Helpers/ParallelHelperTests.cs @@ -9,6 +9,7 @@ using System.Threading; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; using SixLabors.Primitives; @@ -334,5 +335,39 @@ namespace SixLabors.ImageSharp.Tests.Helpers TestImageExtensions.CompareBuffers(expected.Span, actual.Span); } } + + [Theory] + [InlineData(0, 10)] + [InlineData(10, 0)] + [InlineData(-10, 10)] + [InlineData(10, -10)] + public void IterateRowsRequiresValidRectangle(int width, int height) + { + var parallelSettings = new ParallelExecutionSettings(); + + var rect = new Rectangle(0, 0, width, height); + + ArgumentOutOfRangeException ex = Assert.Throws( + () => ParallelHelper.IterateRows(rect, parallelSettings, (rows) => { })); + + Assert.Contains(width <= 0 ? "Width" : "Height", ex.Message); + } + + [Theory] + [InlineData(0, 10)] + [InlineData(10, 0)] + [InlineData(-10, 10)] + [InlineData(10, -10)] + public void IterateRowsWithTempBufferRequiresValidRectangle(int width, int height) + { + var parallelSettings = new ParallelExecutionSettings(); + + var rect = new Rectangle(0, 0, width, height); + + ArgumentOutOfRangeException ex = Assert.Throws( + () => ParallelHelper.IterateRowsWithTempBuffer(rect, parallelSettings, (rows, memory) => { })); + + Assert.Contains(width <= 0 ? "Width" : "Height", ex.Message); + } } } \ No newline at end of file From fcc7e5b257dfd6ed58048e4635e5d5798468b9ca Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Wed, 1 May 2019 16:03:50 +0200 Subject: [PATCH 098/223] Bitmap encoder writes V3 header as default (#889) * Bitmap encoder will now write a V3 header as default. Introduces a new encoder option `SupportTransparency`: With this option a V4 header will be written with BITFIELDS compression. * Add 4 and 16 bit images to the Identify test * Add some useful links for bitmap documentation * Add 32 bpp images to the Identify test * Added further information on what will change for the encoder, if SupportTransparency is used. --- src/ImageSharp/Formats/Bmp/BmpEncoder.cs | 8 ++++ src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 45 ++++++++++++------- .../Formats/Bmp/IBmpEncoderOptions.cs | 10 ++++- src/ImageSharp/Formats/Bmp/README.md | 19 +++++--- .../Formats/Bmp/BmpDecoderTests.cs | 7 ++- .../Formats/Bmp/BmpEncoderTests.cs | 38 ++++++++++++++-- 6 files changed, 100 insertions(+), 27 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs index b1a66acce..4efdedb34 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs @@ -18,6 +18,14 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public BmpBitsPerPixel? BitsPerPixel { get; set; } + /// + /// Gets or sets a value indicating whether the encoder should support transparency. + /// Note: Transparency support only works together with 32 bits per pixel. This option will + /// change the default behavior of the encoder of writing a bitmap version 3 info header with no compression. + /// Instead a bitmap version 4 info header will be written with the BITFIELDS compression. + /// + public bool SupportTransparency { get; set; } + /// public void Encode(Image image, Stream stream) where TPixel : struct, IPixel diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index ad526f668..c4c51b78e 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -24,22 +24,22 @@ namespace SixLabors.ImageSharp.Formats.Bmp private int padding; /// - /// The mask for the alpha channel of the color for a 32 bit rgba bitmaps. + /// The mask for the alpha channel of the color for 32 bit rgba bitmaps. /// private const int Rgba32AlphaMask = 0xFF << 24; /// - /// The mask for the red part of the color for a 32 bit rgba bitmaps. + /// The mask for the red part of the color for 32 bit rgba bitmaps. /// private const int Rgba32RedMask = 0xFF << 16; /// - /// The mask for the green part of the color for a 32 bit rgba bitmaps. + /// The mask for the green part of the color for 32 bit rgba bitmaps. /// private const int Rgba32GreenMask = 0xFF << 8; /// - /// The mask for the blue part of the color for a 32 bit rgba bitmaps. + /// The mask for the blue part of the color for 32 bit rgba bitmaps. /// private const int Rgba32BlueMask = 0xFF; @@ -49,15 +49,23 @@ namespace SixLabors.ImageSharp.Formats.Bmp private BmpBitsPerPixel? bitsPerPixel; + /// + /// A bitmap v4 header will only be written, if the user explicitly wants support for transparency. + /// In this case the compression type BITFIELDS will be used. + /// Otherwise a bitmap v3 header will be written, which is supported by almost all decoders. + /// + private readonly bool writeV4Header; + /// /// Initializes a new instance of the class. /// - /// The encoder options - /// The memory manager + /// The encoder options. + /// The memory manager. public BmpEncoderCore(IBmpEncoderOptions options, MemoryAllocator memoryAllocator) { this.memoryAllocator = memoryAllocator; this.bitsPerPixel = options.BitsPerPixel; + this.writeV4Header = options.SupportTransparency; } /// @@ -112,7 +120,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp } } - int infoHeaderSize = BmpInfoHeader.SizeV4; + int infoHeaderSize = this.writeV4Header ? BmpInfoHeader.SizeV4 : BmpInfoHeader.SizeV3; var infoHeader = new BmpInfoHeader( headerSize: infoHeaderSize, height: image.Height, @@ -123,17 +131,15 @@ namespace SixLabors.ImageSharp.Formats.Bmp clrUsed: 0, clrImportant: 0, xPelsPerMeter: hResolution, - yPelsPerMeter: vResolution) - { - RedMask = Rgba32RedMask, - GreenMask = Rgba32GreenMask, - BlueMask = Rgba32BlueMask, - Compression = BmpCompression.BitFields - }; + yPelsPerMeter: vResolution); - if (this.bitsPerPixel == BmpBitsPerPixel.Pixel32) + if (this.writeV4Header && this.bitsPerPixel == BmpBitsPerPixel.Pixel32) { infoHeader.AlphaMask = Rgba32AlphaMask; + infoHeader.RedMask = Rgba32RedMask; + infoHeader.GreenMask = Rgba32GreenMask; + infoHeader.BlueMask = Rgba32BlueMask; + infoHeader.Compression = BmpCompression.BitFields; } var fileHeader = new BmpFileHeader( @@ -151,7 +157,14 @@ namespace SixLabors.ImageSharp.Formats.Bmp stream.Write(buffer, 0, BmpFileHeader.Size); - infoHeader.WriteV4Header(buffer); + if (this.writeV4Header) + { + infoHeader.WriteV4Header(buffer); + } + else + { + infoHeader.WriteV3Header(buffer); + } stream.Write(buffer, 0, infoHeaderSize); diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs index f62504d08..a3a056bfa 100644 --- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs +++ b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs @@ -6,12 +6,20 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Configuration options for use during bmp encoding /// - /// The encoder can currently only write 24-bit rgb images to streams. + /// The encoder can currently only write 24-bit and 32-bit rgb images to streams. internal interface IBmpEncoderOptions { /// /// Gets the number of bits per pixel. /// BmpBitsPerPixel? BitsPerPixel { get; } + + /// + /// Gets a value indicating whether the encoder should support transparency. + /// Note: Transparency support only works together with 32 bits per pixel. This option will + /// change the default behavior of the encoder of writing a bitmap version 3 info header with no compression. + /// Instead a bitmap version 4 info header will be written with the BITFIELDS compression. + /// + bool SupportTransparency { get; } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/README.md b/src/ImageSharp/Formats/Bmp/README.md index d07283843..f41830733 100644 --- a/src/ImageSharp/Formats/Bmp/README.md +++ b/src/ImageSharp/Formats/Bmp/README.md @@ -1,8 +1,17 @@ -Encoder/Decoder adapted from: +### Encoder/Decoder adapted from: -https://github.com/yufeih/Nine.Imaging/ -https://imagetools.codeplex.com/ +- [Nine.Imaging](https://github.com/yufeih/Nine.Imaging/) +- [imagetools.codeplex](https://imagetools.codeplex.com/) -TODO: +### Some useful links for documentation about the bitmap format: -- Add support for all bitmap formats. +- [Microsoft Windows Bitmap File](http://www.fileformat.info/format/bmp/egff.htm) +- [OS/2 Bitmap File Format Summary](http://www.fileformat.info/format/os2bmp/egff.htm) +- [The DIB File Format](https://www-user.tu-chemnitz.de/~heha/viewchm.php/hs/petzold.chm/petzoldi/ch15b.htm) +- [Dr.Dobbs: The BMP File Format, Part 1](http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517) +- [Windows Bitmap File Format Specifications](ftp://ftp.nada.kth.se/pub/hacks/sgi/src/libwmf/doc/Bmpfrmat.html) + +### A set of bitmap test images: + +- [bmpsuite](http://entropymine.com/jason/bmpsuite/bmpsuite/html/bmpsuite.html) +- [eclecticgeek](http://eclecticgeek.com/dompdf/core_tests/image_bmp.html) \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 05fadd458..5f3cc7db4 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -130,7 +130,7 @@ namespace SixLabors.ImageSharp.Tests [Theory] [WithFile(LessThanFullSizedPalette, PixelTypes.Rgba32)] - public void BmpDecoder_CanDecodeLessThanFullPalete(TestImageProvider provider) + public void BmpDecoder_CanDecodeLessThanFullPalette(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage(new BmpDecoder())) @@ -213,11 +213,16 @@ namespace SixLabors.ImageSharp.Tests } [Theory] + [InlineData(Bit32Rgb, 32)] + [InlineData(Bit32Rgba, 32)] [InlineData(Car, 24)] [InlineData(F, 24)] [InlineData(NegHeight, 24)] + [InlineData(Bit16, 16)] + [InlineData(Bit16Inverted, 16)] [InlineData(Bit8, 8)] [InlineData(Bit8Inverted, 8)] + [InlineData(Bit4, 4)] public void Identify(string imagePath, int expectedPixelSize) { var testFile = TestFile.Create(imagePath); diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index c9745ef4f..c7558ab42 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -11,6 +11,8 @@ using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests { + using static TestImages.Bmp; + public class BmpEncoderTests : FileTestBase { public static readonly TheoryData BitsPerPixel = @@ -102,15 +104,43 @@ namespace SixLabors.ImageSharp.Tests public void Encode_WorksWithDifferentSizes(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel); - private static void TestBmpEncoderCore(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + [Theory] + [WithFile(Bit32Rgb, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] + [WithFile(Bit32Rgba, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] + [WithFile(WinBmpv4, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] + [WithFile(WinBmpv5, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] + // WinBmpv3 is a 24 bits per pixel image + [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] + public void Encode_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + // if supportTransparency is false, a v3 bitmap header will be written + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); + + [Theory] + [WithFile(Bit32Rgb, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] + [WithFile(Bit32Rgba, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] + [WithFile(WinBmpv4, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] + [WithFile(WinBmpv5, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] + [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] + public void Encode_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); + + [Theory] + [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] + public void Encode_PreservesAlpha(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); + + private static void TestBmpEncoderCore(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel, bool supportTransparency = true) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { - // there is no alpha in bmp! - image.Mutate(c => c.MakeOpaque()); + // There is no alpha in bmp with 24 bits per pixels, so the reference image will be made opaque. + if (bitsPerPixel == BmpBitsPerPixel.Pixel24) + { + image.Mutate(c => c.MakeOpaque()); + } - var encoder = new BmpEncoder { BitsPerPixel = bitsPerPixel }; + var encoder = new BmpEncoder { BitsPerPixel = bitsPerPixel, SupportTransparency = supportTransparency }; // Does DebugSave & load reference CompareToReferenceInput(): image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder); From b0f6b73faaaf304e47dec9e58ca6be90b2e740bc Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Fri, 3 May 2019 17:10:40 +0200 Subject: [PATCH 099/223] Add support for encoding 16 bit per pixel bitmaps (#899) * Implemented encoding of 16 bits per pixel bitmaps * Add unit tests for 16 bit encoding and Bgra5551 conversion * Add additional Bgra5551 pixel conversion tests * Add Bgra5551 tests for Short2/4 and HalfVector2/4 * Use scaled vector conversion --- src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs | 5 + src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 3 +- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 30 ++++ .../Formats/Bmp/IBmpEncoderOptions.cs | 2 +- src/ImageSharp/PixelFormats/IPixel.cs | 6 + .../PixelImplementations/Alpha8.cs | 4 + .../PixelImplementations/Argb32.cs | 4 + .../PixelImplementations/Bgr24.cs | 4 + .../PixelImplementations/Bgr565.cs | 4 + .../PixelImplementations/Bgra32.cs | 4 + .../PixelImplementations/Bgra4444.cs | 4 + .../PixelImplementations/Bgra5551.cs | 4 + .../PixelImplementations/Byte4.cs | 4 + .../PixelImplementations/Gray16.cs | 4 + .../PixelImplementations/Gray8.cs | 4 + .../PixelImplementations/HalfSingle.cs | 4 + .../PixelImplementations/HalfVector2.cs | 4 + .../PixelImplementations/HalfVector4.cs | 4 + .../PixelImplementations/NormalizedByte2.cs | 11 +- .../PixelImplementations/NormalizedByte4.cs | 4 + .../PixelImplementations/NormalizedShort2.cs | 4 + .../PixelImplementations/NormalizedShort4.cs | 4 + .../PixelFormats/PixelImplementations/Rg32.cs | 4 + .../PixelImplementations/Rgb24.cs | 4 + .../PixelImplementations/Rgb48.cs | 4 + .../PixelImplementations/Rgba1010102.cs | 4 + .../PixelImplementations/Rgba32.cs | 4 + .../PixelImplementations/Rgba64.cs | 6 +- .../PixelImplementations/RgbaVector.cs | 9 +- .../PixelImplementations/Short2.cs | 9 +- .../PixelImplementations/Short4.cs | 4 + .../PixelOperations{TPixel}.Generated.cs | 72 ++++++++++ .../PixelOperations{TPixel}.Generated.tt | 3 + .../Formats/Bmp/BmpDecoderTests.cs | 2 +- .../Formats/Bmp/BmpEncoderTests.cs | 17 ++- .../PixelFormats/Alpha8Tests.cs | 14 ++ .../PixelFormats/Argb32Tests.cs | 14 ++ .../PixelFormats/Bgr24Tests.cs | 15 ++ .../PixelFormats/Bgr565Tests.cs | 14 ++ .../PixelFormats/Bgra32Tests.cs | 14 ++ .../PixelFormats/Bgra4444Tests.cs | 14 ++ .../PixelFormats/Bgra5551Tests.cs | 129 +++++++++++++++++- .../PixelFormats/Byte4Tests.cs | 14 ++ .../PixelFormats/Gray16Tests.cs | 14 ++ .../PixelFormats/Gray8Tests.cs | 14 ++ .../PixelFormats/HalfVector2Tests.cs | 17 +++ .../PixelFormats/HalfVector4Tests.cs | 14 ++ .../PixelFormats/NormalizedByte2Tests.cs | 14 ++ .../PixelFormats/NormalizedByte4Tests.cs | 14 ++ .../PixelFormats/NormalizedShort2Tests.cs | 14 ++ .../PixelFormats/NormalizedShort4Tests.cs | 14 ++ .../PixelFormats/Rg32Tests.cs | 14 ++ .../PixelFormats/Rgb24Tests.cs | 22 ++- .../PixelFormats/Rgb48Tests.cs | 16 +++ .../PixelFormats/Rgba1010102Tests.cs | 14 ++ .../PixelFormats/Rgba32Tests.cs | 14 ++ .../PixelFormats/Rgba64Tests.cs | 17 +++ .../PixelFormats/Short2Tests.cs | 17 +++ .../PixelFormats/Short4Tests.cs | 14 ++ tests/ImageSharp.Tests/TestImages.cs | 1 + .../TestUtilities/PixelTypes.cs | 2 + tests/Images/Input/Bmp/rgb16.bmp | Bin 0 -> 16438 bytes 62 files changed, 712 insertions(+), 25 deletions(-) create mode 100644 tests/Images/Input/Bmp/rgb16.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs b/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs index 618999c87..38f5c1d66 100644 --- a/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs +++ b/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs @@ -8,6 +8,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public enum BmpBitsPerPixel : short { + /// + /// 16 bits per pixel. Each pixel consists of 2 bytes. + /// + Pixel16 = 16, + /// /// 24 bits per pixel. Each pixel consists of 3 bytes. /// diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index b52c3754e..9d9c7b624 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -1022,7 +1022,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.bmpMetadata.InfoHeaderType = infoHeaderType; // We can only encode at these bit rates so far. - if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24) + if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel16) + || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24) || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel32)) { this.bmpMetadata.BitsPerPixel = (BmpBitsPerPixel)bitsPerPixel; diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index c4c51b78e..82483e390 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -194,6 +194,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp case BmpBitsPerPixel.Pixel24: this.Write24Bit(stream, pixels); break; + + case BmpBitsPerPixel.Pixel16: + this.Write16Bit(stream, pixels); + break; } } @@ -246,5 +250,31 @@ namespace SixLabors.ImageSharp.Formats.Bmp } } } + + /// + /// Writes the 16bit color palette to the stream. + /// + /// The type of the pixel. + /// The to write to. + /// The containing pixel data. + private void Write16Bit(Stream stream, Buffer2D pixels) + where TPixel : struct, IPixel + { + using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 2)) + { + for (int y = pixels.Height - 1; y >= 0; y--) + { + Span pixelSpan = pixels.GetRowSpan(y); + + PixelOperations.Instance.ToBgra5551Bytes( + this.configuration, + pixelSpan, + row.GetSpan(), + pixelSpan.Length); + + stream.Write(row.Array, 0, row.Length()); + } + } + } } } diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs index a3a056bfa..96ec423e7 100644 --- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs +++ b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs @@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Configuration options for use during bmp encoding /// - /// The encoder can currently only write 24-bit and 32-bit rgb images to streams. + /// The encoder can currently only write 16-bit, 24-bit and 32-bit rgb images to streams. internal interface IBmpEncoderOptions { /// diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs index 127740686..21ec2a3fd 100644 --- a/src/ImageSharp/PixelFormats/IPixel.cs +++ b/src/ImageSharp/PixelFormats/IPixel.cs @@ -61,6 +61,12 @@ namespace SixLabors.ImageSharp.PixelFormats /// The value. void FromArgb32(Argb32 source); + /// + /// Initializes the pixel instance from an value. + /// + /// The value. + void FromBgra5551(Bgra5551 source); + /// /// Initializes the pixel instance from an value. /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Alpha8.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Alpha8.cs index 75b7ede82..cd864b545 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Alpha8.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Alpha8.cs @@ -87,6 +87,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.PackedValue = source.A; + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.PackedValue = byte.MaxValue; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs index 8fc301631..075df01cd 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs @@ -187,6 +187,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromArgb32(Argb32 source) => this.PackedValue = source.PackedValue; + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgr24(Bgr24 source) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs index 96ff7da6f..3ba6436a0 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs @@ -109,6 +109,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgr24(Bgr24 source) => this = source; + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs index a2e4dc880..9e42de388 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs @@ -87,6 +87,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromArgb32(Argb32 source) => this.FromVector4(source.ToVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromVector4(source.ToVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgr24(Bgr24 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs index 1d156222f..758be8043 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs @@ -159,6 +159,10 @@ namespace SixLabors.ImageSharp.PixelFormats this.A = byte.MaxValue; } + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this = source; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs index 110b51822..6fcac6291 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs @@ -90,6 +90,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromArgb32(Argb32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgr24(Bgr24 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs index dcfb25a64..abb3eb19e 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs @@ -87,6 +87,10 @@ namespace SixLabors.ImageSharp.PixelFormats (this.PackedValue >> 15) & 0x01); } + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this = source; + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromArgb32(Argb32 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs index 43a03dc5d..a07cd5213 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs @@ -111,6 +111,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb24(Rgb24 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba32(Rgba32 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Gray16.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Gray16.cs index 2e98a28ad..6fce1c757 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Gray16.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Gray16.cs @@ -106,6 +106,10 @@ namespace SixLabors.ImageSharp.PixelFormats ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); } + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.PackedValue = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs index 512bee39d..1c278b434 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs @@ -97,6 +97,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.PackedValue = source.PackedValue; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs b/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs index 8323cf3e8..580cc5399 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs @@ -88,6 +88,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs index cb915459b..e2ed931b7 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs @@ -99,6 +99,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs index 9f60ca8c7..3b30ebd1e 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs @@ -107,6 +107,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs index d39cfd402..cd95e87ec 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs @@ -8,7 +8,7 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.PixelFormats { /// - /// Packed packed pixel type containing two 8-bit signed normalized values, ranging from −1 to 1. + /// Packed pixel type containing two 8-bit signed normalized values, ranging from −1 to 1. /// /// Ranges from [-1, -1, 0, 1] to [1, 1, 0, 1] in vector form. /// @@ -107,10 +107,11 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void ToRgba32(ref Rgba32 dest) - { - dest.FromScaledVector4(this.ToScaledVector4()); - } + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void ToRgba32(ref Rgba32 dest) => dest.FromScaledVector4(this.ToScaledVector4()); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs index 8a9368463..73a3d3262 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs @@ -110,6 +110,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs index b9cab1e7d..8d7c400b4 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs @@ -105,6 +105,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs index 3bc74e6c6..453b1c1b7 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs @@ -112,6 +112,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs index 6dc623518..0411f8f3e 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs @@ -93,6 +93,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs index 86565731d..1255f66d1 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs @@ -156,6 +156,10 @@ namespace SixLabors.ImageSharp.PixelFormats this.B = rgb; } + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb24(Rgb24 source) => this = source; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs index eda116a46..f59036ec7 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs @@ -126,6 +126,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba64(Rgba64 source) => this = source.Rgb; + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs index 895added1..38f61d56c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs @@ -99,6 +99,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs index 5a16704ef..7367c4463 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs @@ -266,6 +266,10 @@ namespace SixLabors.ImageSharp.PixelFormats this.A = source.A; } + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs index 5ae5492e2..87d1b235b 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.PixelFormats { /// - /// Packed pixel type containing four 16-bit unsigned normalized values ranging from 0 to 635535. + /// Packed pixel type containing four 16-bit unsigned normalized values ranging from 0 to 65535. /// /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. /// @@ -154,6 +154,10 @@ namespace SixLabors.ImageSharp.PixelFormats this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); } + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs index d65a5ade7..96003cc5b 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs @@ -134,6 +134,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); @@ -152,10 +156,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void ToRgba32(ref Rgba32 dest) - { - dest.FromScaledVector4(this.ToScaledVector4()); - } + public void ToRgba32(ref Rgba32 dest) => dest.FromScaledVector4(this.ToScaledVector4()); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs index 96fe15ed6..803a77b23 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs @@ -111,6 +111,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); @@ -129,10 +133,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void ToRgba32(ref Rgba32 dest) - { - dest.FromScaledVector4(this.ToScaledVector4()); - } + public void ToRgba32(ref Rgba32 dest) => dest.FromScaledVector4(this.ToScaledVector4()); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs index d224f8eb4..c52b29347 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs @@ -116,6 +116,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); + /// [MethodImpl(InliningOptions.ShortMethod)] public void FromGray8(Gray8 source) => this.FromScaledVector4(source.ToScaledVector4()); diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs index 207a8767d..700281992 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.cs @@ -657,5 +657,77 @@ namespace SixLabors.ImageSharp.PixelFormats { this.ToRgba64(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); } + + /// + /// Converts all pixels in 'source` span of into a span of -s. + /// + /// A to configure internal operations + /// The source of data. + /// The to the destination pixels. + internal virtual void FromBgra5551(Configuration configuration, ReadOnlySpan source, Span destPixels) + { + Guard.DestinationShouldNotBeTooShort(source, destPixels, nameof(destPixels)); + + ref Bgra5551 sourceBaseRef = ref MemoryMarshal.GetReference(source); + ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels); + + for (int i = 0; i < source.Length; i++) + { + ref Bgra5551 sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i); + + dp.FromBgra5551(sp); + } + } + + /// + /// A helper for that expects a byte span. + /// The layout of the data in 'sourceBytes' must be compatible with layout. + /// + /// A to configure internal operations + /// The to the source bytes. + /// The to the destination pixels. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void FromBgra5551Bytes(Configuration configuration, ReadOnlySpan sourceBytes, Span destPixels, int count) + { + this.FromBgra5551(configuration, MemoryMarshal.Cast(sourceBytes).Slice(0, count), destPixels); + } + + /// + /// Converts all pixels of the 'sourcePixels` span to a span of -s. + /// + /// A to configure internal operations + /// The span of source pixels + /// The destination span of data. + internal virtual void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + { + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels); + ref Bgra5551 destBaseRef = ref MemoryMarshal.GetReference(destPixels); + + for (int i = 0; i < sourcePixels.Length; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Bgra5551 dp = ref Unsafe.Add(ref destBaseRef, i); + + dp.FromScaledVector4(sp.ToScaledVector4()); + } + } + + /// + /// A helper for that expects a byte span as destination. + /// The layout of the data in 'destBytes' must be compatible with layout. + /// + /// A to configure internal operations + /// The to the source pixels. + /// The to the destination bytes. + /// The number of pixels to convert. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void ToBgra5551Bytes(Configuration configuration, ReadOnlySpan sourcePixels, Span destBytes, int count) + { + this.ToBgra5551(configuration, sourcePixels.Slice(0, count), MemoryMarshal.Cast(destBytes)); + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt index 8579423b3..860301232 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.Generated.tt @@ -136,5 +136,8 @@ namespace SixLabors.ImageSharp.PixelFormats GenerateFromMethods("Rgba64"); GenerateToDestFormatMethods("Rgba64"); + GenerateFromMethods("Bgra5551"); + GenerateToDestFormatMethods("Bgra5551"); + #> } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 5f3cc7db4..e615dbe56 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -11,7 +11,7 @@ using Xunit; // ReSharper disable InconsistentNaming -namespace SixLabors.ImageSharp.Tests +namespace SixLabors.ImageSharp.Tests.Formats.Bmp { using SixLabors.ImageSharp.Metadata; using static TestImages.Bmp; diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index c7558ab42..7e054734e 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -6,10 +6,11 @@ using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; + using Xunit; using Xunit.Abstractions; -namespace SixLabors.ImageSharp.Tests +namespace SixLabors.ImageSharp.Tests.Formats.Bmp { using static TestImages.Bmp; @@ -25,16 +26,16 @@ namespace SixLabors.ImageSharp.Tests public static readonly TheoryData RatioFiles = new TheoryData { - { TestImages.Bmp.Car, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, - { TestImages.Bmp.V5Header, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, - { TestImages.Bmp.RLE8, 2835, 2835, PixelResolutionUnit.PixelsPerMeter } + { Car, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, + { V5Header, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, + { RLE8, 2835, 2835, PixelResolutionUnit.PixelsPerMeter } }; public static readonly TheoryData BmpBitsPerPixelFiles = new TheoryData { - { TestImages.Bmp.Car, BmpBitsPerPixel.Pixel24 }, - { TestImages.Bmp.Bit32Rgb, BmpBitsPerPixel.Pixel32 } + { Car, BmpBitsPerPixel.Pixel24 }, + { Bit32Rgb, BmpBitsPerPixel.Pixel32 } }; public BmpEncoderTests(ITestOutputHelper output) => this.Output = output; @@ -111,6 +112,8 @@ namespace SixLabors.ImageSharp.Tests [WithFile(WinBmpv5, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] // WinBmpv3 is a 24 bits per pixel image [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] + [WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] + [WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] public void Encode_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) // if supportTransparency is false, a v3 bitmap header will be written where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); @@ -121,6 +124,8 @@ namespace SixLabors.ImageSharp.Tests [WithFile(WinBmpv4, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] [WithFile(WinBmpv5, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] + [WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] + [WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] public void Encode_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); diff --git a/tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs index 8f68c9d03..b6e87626b 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs @@ -94,5 +94,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats input.ToRgba32(ref actual); Assert.Equal(expected, actual); } + + [Fact] + public void Alpha8_FromBgra5551() + { + // arrange + var alpha = default(Alpha8); + byte expected = byte.MaxValue; + + // act + alpha.FromBgra5551(new Bgra5551(0.0f, 0.0f, 0.0f, 1.0f)); + + // assert + Assert.Equal(expected, alpha.PackedValue); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs index b9f741490..4f3394e69 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs @@ -60,6 +60,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual); } + [Fact] + public void Argb32_FromBgra5551() + { + // arrange + var argb = default(Argb32); + uint expected = uint.MaxValue; + + // act + argb.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, argb.PackedValue); + } + [Fact] public void Argb32_Clamping() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs index 2295fbe56..f145e6928 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs @@ -95,5 +95,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(Vec(1, 2, 3), rgb.ToVector4()); } + + [Fact] + public void Bgr24_FromBgra5551() + { + // arrange + var bgr = default(Bgr24); + + // act + bgr.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(255, bgr.R); + Assert.Equal(255, bgr.G); + Assert.Equal(255, bgr.B); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs index 967e358e1..4419fe898 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs @@ -63,6 +63,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual); } + [Fact] + public void Bgr565_FromBgra5551() + { + // arrange + var bgr = default(Bgr565); + ushort expected = ushort.MaxValue; + + // act + bgr.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, bgr.PackedValue); + } + [Fact] public void Bgr565_Clamping() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs index a5c53ed8b..171a3dfa0 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs @@ -102,5 +102,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(Vec(1, 2, 3, 4), rgb.ToVector4()); } + + [Fact] + public void Bgra32_FromBgra5551() + { + // arrange + var bgra = default(Bgra32); + uint expected = uint.MaxValue; + + // act + bgra.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, bgra.PackedValue); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs index 8b56ec19f..b6019016c 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs @@ -64,6 +64,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual); } + [Fact] + public void Bgra4444_FromBgra5551() + { + // arrange + var bgra = default(Bgra4444); + ushort expected = ushort.MaxValue; + + // act + bgra.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, bgra.PackedValue); + } + [Fact] public void Bgra4444_Clamping() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs index 76edee8a7..f5abca59a 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -18,6 +19,13 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats float w = 0x1; Assert.Equal(0xeacd, new Bgra5551(x / 0x1f, y / 0x1f, z / 0x1f, w).PackedValue); Assert.Equal(3088, new Bgra5551(0.1f, -0.3f, 0.5f, -0.7f).PackedValue); + + Assert.Equal(0xFFFF, new Bgra5551(Vector4.One).PackedValue); + Assert.Equal(0x7C00, new Bgra5551(Vector4.UnitX).PackedValue); + Assert.Equal(0x03E0, new Bgra5551(Vector4.UnitY).PackedValue); + Assert.Equal(0x001F, new Bgra5551(Vector4.UnitZ).PackedValue); + Assert.Equal(0x8000, new Bgra5551(Vector4.UnitW).PackedValue); + // Test the limits. Assert.Equal(0x0, new Bgra5551(Vector4.Zero).PackedValue); Assert.Equal(0xFFFF, new Bgra5551(Vector4.One).PackedValue); @@ -53,7 +61,6 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Vector4 scaled = new Bgra5551(Vector4.One).ToScaledVector4(); int expected = 0xFFFF; var pixel = default(Bgra5551); - pixel.FromScaledVector4(scaled); // act pixel.FromScaledVector4(scaled); @@ -63,6 +70,126 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual); } + [Fact] + public void Bgra5551_FromRgba32() + { + // arrange + var bgra1 = default(Bgra5551); + var bgra2 = default(Bgra5551); + ushort expectedPackedValue1 = ushort.MaxValue; + ushort expectedPackedValue2 = 0xFC1F; + + // act + bgra1.FromRgba32(new Rgba32(255, 255, 255, 255)); + bgra2.FromRgba32(new Rgba32(255, 0, 255, 255)); + + // assert + Assert.Equal(expectedPackedValue1, bgra1.PackedValue); + Assert.Equal(expectedPackedValue2, bgra2.PackedValue); + } + + [Fact] + public void Bgra5551_FromBgra32() + { + // arrange + var bgra1 = default(Bgra5551); + var bgra2 = default(Bgra5551); + ushort expectedPackedValue1 = ushort.MaxValue; + ushort expectedPackedValue2 = 0xFC1F; + + // act + bgra1.FromBgra32(new Bgra32(255, 255, 255, 255)); + bgra2.FromBgra32(new Bgra32(255, 0, 255, 255)); + + // assert + Assert.Equal(expectedPackedValue1, bgra1.PackedValue); + Assert.Equal(expectedPackedValue2, bgra2.PackedValue); + } + + [Fact] + public void Bgra5551_FromArgb32() + { + // arrange + var bgra = default(Bgra5551); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromArgb32(new Argb32(255, 255, 255, 255)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra5551_FromRgba64() + { + // arrange + var bgra = default(Bgra5551); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromRgba64(new Rgba64(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra5551_FromGrey16() + { + // arrange + var bgra = default(Bgra5551); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromGray16(new Gray16(ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra5551_FromGrey8() + { + // arrange + var bgra = default(Bgra5551); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromGray8(new Gray8(byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra5551_FromBgr24() + { + // arrange + var bgra = default(Bgra5551); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromBgr24(new Bgr24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra5551_FromRgb24() + { + // arrange + var bgra = default(Bgra5551); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromRgb24(new Rgb24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + [Fact] public void Bgra5551_Clamping() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs index 8391ef25a..9174a6abd 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs @@ -61,6 +61,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual); } + [Fact] + public void Byte4_FromBgra5551() + { + // arrange + var rgb = default(Byte4); + uint expected = 0xFFFFFFFF; + + // act + rgb.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, rgb.PackedValue); + } + [Fact] public void Byte4_Clamping() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs index cb19c031d..01b60832e 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs @@ -126,5 +126,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual.B); Assert.Equal(byte.MaxValue, actual.A); } + + [Fact] + public void Gray16_FromBgra5551() + { + // arrange + var gray = default(Gray16); + ushort expected = ushort.MaxValue; + + // act + gray.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, gray.PackedValue); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs index 1e17985e6..159f97cde 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs @@ -148,6 +148,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(byte.MaxValue, actual.A); } + [Fact] + public void Gray8_FromBgra5551() + { + // arrange + var grey = default(Gray8); + byte expected = byte.MaxValue; + + // act + grey.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, grey.PackedValue); + } + public class Rgba32Compatibility { // ReSharper disable once MemberHidesStaticFromOuterClass diff --git a/tests/ImageSharp.Tests/PixelFormats/HalfVector2Tests.cs b/tests/ImageSharp.Tests/PixelFormats/HalfVector2Tests.cs index ccdd23e8f..57da5438c 100644 --- a/tests/ImageSharp.Tests/PixelFormats/HalfVector2Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/HalfVector2Tests.cs @@ -71,5 +71,22 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void HalfVector2_FromBgra5551() + { + // arrange + var halfVector2 = default(HalfVector2); + + // act + halfVector2.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Vector4 actual = halfVector2.ToScaledVector4(); + Assert.Equal(1F, actual.X); + Assert.Equal(1F, actual.Y); + Assert.Equal(0, actual.Z); + Assert.Equal(1, actual.W); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/HalfVector4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/HalfVector4Tests.cs index c61dd97d2..ed1a0b720 100644 --- a/tests/ImageSharp.Tests/PixelFormats/HalfVector4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/HalfVector4Tests.cs @@ -65,5 +65,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void HalfVector4_FromBgra5551() + { + // arrange + var halfVector4 = default(HalfVector4); + Vector4 expected = Vector4.One; + + // act + halfVector4.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, halfVector4.ToScaledVector4()); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/NormalizedByte2Tests.cs b/tests/ImageSharp.Tests/PixelFormats/NormalizedByte2Tests.cs index 506ebe0fe..1533f9cf9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/NormalizedByte2Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/NormalizedByte2Tests.cs @@ -66,5 +66,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void NormalizedByte2_FromBgra5551() + { + // arrange + var normalizedByte2 = default(NormalizedByte2); + var expected = new Vector4(1, 1, 0, 1); + + // act + normalizedByte2.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, normalizedByte2.ToVector4()); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs index 19a49e5d8..1cb404a00 100644 --- a/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs @@ -60,5 +60,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void NormalizedByte4_FromBgra5551() + { + // arrange + var normalizedByte4 = default(NormalizedByte4); + Vector4 expected = Vector4.One; + + // act + normalizedByte4.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, normalizedByte4.ToVector4()); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/NormalizedShort2Tests.cs b/tests/ImageSharp.Tests/PixelFormats/NormalizedShort2Tests.cs index 216ed4ad7..ff9350b70 100644 --- a/tests/ImageSharp.Tests/PixelFormats/NormalizedShort2Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/NormalizedShort2Tests.cs @@ -69,5 +69,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void NormalizedShort2_FromBgra5551() + { + // arrange + var normalizedShort2 = default(NormalizedShort2); + var expected = new Vector4(1, 1, 0, 1); + + // act + normalizedShort2.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, normalizedShort2.ToVector4()); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs index d06d46d06..cea7e3146 100644 --- a/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs @@ -61,5 +61,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void NormalizedShort4_FromBgra5551() + { + // arrange + var normalizedShort4 = default(NormalizedShort4); + Vector4 expected = Vector4.One; + + // act + normalizedShort4.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, normalizedShort4.ToVector4()); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/Rg32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rg32Tests.cs index 46e5fbc3c..bccaaf816 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rg32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rg32Tests.cs @@ -62,6 +62,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual); } + [Fact] + public void Rg32_FromBgra5551() + { + // arrange + var rg32 = new Rg32(Vector2.One); + uint expected = 0xFFFFFFFF; + + // act + rg32.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, rg32.PackedValue); + } + [Fact] public void Rg32_Clamping() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs index 92e8d302d..df459422c 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs @@ -103,11 +103,31 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats [Fact] public void ToRgba32() { + // arrange var rgb = new Rgb24(1, 2, 3); Rgba32 rgba = default; + var expected = new Rgba32(1, 2, 3, 255); + + // act rgb.ToRgba32(ref rgba); - Assert.Equal(new Rgba32(1, 2, 3, 255), rgba); + // assert + Assert.Equal(expected, rgba); + } + + [Fact] + public void Rgb24_FromBgra5551() + { + // arrange + var rgb = new Rgb24(255, 255, 255); + + // act + rgb.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(255, rgb.R); + Assert.Equal(255, rgb.G); + Assert.Equal(255, rgb.B); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs index d30e49860..3bddc21ab 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs @@ -58,5 +58,21 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void Rgb48_FromBgra5551() + { + // arrange + var rgb = default(Rgb48); + ushort expected = ushort.MaxValue; + + // act + rgb.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, rgb.R); + Assert.Equal(expected, rgb.G); + Assert.Equal(expected, rgb.B); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs index a897dd4cd..0dbed2d2c 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs @@ -64,6 +64,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual.PackedValue); } + [Fact] + public void Rgba1010102_FromBgra5551() + { + // arrange + var rgba = new Rgba1010102(Vector4.One); + uint expected = 0xFFFFFFFF; + + // act + rgba.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, rgba.PackedValue); + } + [Fact] public void Rgba1010102_Clamping() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs index ad1d13740..275afa35d 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs @@ -276,5 +276,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void Rgba32_FromBgra5551() + { + // arrange + var rgb = default(Rgba32); + uint expected = 0xFFFFFFFF; + + // act + rgb.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, rgb.PackedValue); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs index 3e5d7a56e..51f80e0e1 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs @@ -91,5 +91,22 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void Rgba64_FromBgra5551() + { + // arrange + var rgba = default(Rgba64); + ushort expected = ushort.MaxValue; + + // act + rgba.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, rgba.R); + Assert.Equal(expected, rgba.G); + Assert.Equal(expected, rgba.B); + Assert.Equal(expected, rgba.A); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs index c9a3b33c9..4ae172ed4 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs @@ -141,5 +141,22 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void Short2_FromBgra5551() + { + // arrange + var short2 = default(Short2); + + // act + short2.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Vector4 actual = short2.ToScaledVector4(); + Assert.Equal(1, actual.X); + Assert.Equal(1, actual.Y); + Assert.Equal(0, actual.Z); + Assert.Equal(1, actual.W); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs index 247342a05..1cb7d8998 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs @@ -181,5 +181,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void Short4_FromBgra5551() + { + // arrange + var short4 = default(Short4); + Vector4 expected = Vector4.One; + + // act + short4.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, short4.ToScaledVector4()); + } } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 23bebd621..f82278ef5 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -241,6 +241,7 @@ namespace SixLabors.ImageSharp.Tests public const string Bit16Inverted = "Bmp/test16-inverted.bmp"; public const string Bit32Rgb = "Bmp/rgb32.bmp"; public const string Bit32Rgba = "Bmp/rgba32.bmp"; + public const string Rgb16 = "Bmp/rgb16.bmp"; // Note: This format can be called OS/2 BMPv1, or Windows BMPv2 public const string WinBmpv2 = "Bmp/pal8os2v1_winv2.bmp"; diff --git a/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs b/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs index a051e577d..e4a7572d6 100644 --- a/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs +++ b/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs @@ -58,6 +58,8 @@ namespace SixLabors.ImageSharp.Tests Rgb48 = 1 << 21, + Bgra5551 = 1 << 22, + // TODO: Add multi-flag entries by rules defined in PackedPixelConverterHelper // "All" is handled as a separate, individual case instead of using bitwise OR diff --git a/tests/Images/Input/Bmp/rgb16.bmp b/tests/Images/Input/Bmp/rgb16.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6bfe47af4f72866315bed53d0f6f8591bc372ccb GIT binary patch literal 16438 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 Uj~x9MU;iu9uNMDG^-ll)081sZ{r~^~ literal 0 HcmV?d00001 From 36320c66d3e3bf9bd28ae408ca0c08e3097cc9ad Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 1 May 2019 17:41:36 +0200 Subject: [PATCH 100/223] define IImageVisitor --- src/ImageSharp/IImage.cs | 2 +- src/ImageSharp/Image.cs | 40 +++++++++++++++++++ src/ImageSharp/Image{TPixel}.cs | 5 +++ .../IImageProcessingContext{TPixel}.cs | 5 +++ .../Processing/ProcessingExtensions.cs | 5 +++ .../Processing/Processors/IImageProcessor.cs | 6 +++ 6 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/ImageSharp/Image.cs diff --git a/src/ImageSharp/IImage.cs b/src/ImageSharp/IImage.cs index b9e2cee61..fb251cfd5 100644 --- a/src/ImageSharp/IImage.cs +++ b/src/ImageSharp/IImage.cs @@ -4,7 +4,7 @@ using System; namespace SixLabors.ImageSharp -{ +{ /// /// Encapsulates the properties and methods that describe an image. /// diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs new file mode 100644 index 000000000..6bea675b9 --- /dev/null +++ b/src/ImageSharp/Image.cs @@ -0,0 +1,40 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Metadata; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + internal interface IImageVisitor + { + void Visit(Image image) + where TPixel : struct, IPixel; + } + + public abstract partial class Image : IImage + { + /// + public PixelTypeInfo PixelType { get; } + + /// + public abstract int Width { get; } + + /// + public abstract int Height { get; } + + /// + public ImageMetadata Metadata { get; } + + protected Image(PixelTypeInfo pixelType, ImageMetadata metadata) + { + this.PixelType = pixelType; + this.Metadata = metadata ?? new ImageMetadata(); + } + + public abstract void Dispose(); + + internal abstract void ApplyVisitor(IImageVisitor visitor); + } +} \ No newline at end of file diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index f2bef78e1..2cf389d37 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -220,6 +220,11 @@ namespace SixLabors.ImageSharp /// public void Dispose() => this.Frames.Dispose(); + internal override void ApplyVisitor(IImageVisitor visitor) + { + visitor.Visit(this); + } + /// public override string ToString() => $"Image<{typeof(TPixel).Name}>: {this.Width}x{this.Height}"; diff --git a/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs b/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs index 4897cc58b..72b78b32a 100644 --- a/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs +++ b/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs @@ -8,6 +8,11 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { + public interface IImageProcessingContext + { + + } + /// /// An interface to queue up image operations to apply to an image. /// diff --git a/src/ImageSharp/Processing/ProcessingExtensions.cs b/src/ImageSharp/Processing/ProcessingExtensions.cs index 9d06c61d4..c96b97111 100644 --- a/src/ImageSharp/Processing/ProcessingExtensions.cs +++ b/src/ImageSharp/Processing/ProcessingExtensions.cs @@ -13,6 +13,11 @@ namespace SixLabors.ImageSharp.Processing /// public static class ProcessingExtensions { + public static void Mutate(this Image source, Action operation) + { + + } + /// /// Applies the given operation to the mutable image. /// Useful when we need to extract information like Width/Height to parametrize the next operation working on the chain. diff --git a/src/ImageSharp/Processing/Processors/IImageProcessor.cs b/src/ImageSharp/Processing/Processors/IImageProcessor.cs index d7fe0465b..78800affb 100644 --- a/src/ImageSharp/Processing/Processors/IImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/IImageProcessor.cs @@ -6,6 +6,12 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors { + public interface IImageProcessor + { + IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel; + } + /// /// Encapsulates methods to alter the pixels of an image. /// From 740c2b5400f14c65613532985650033fbc378277 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 1 May 2019 21:26:35 +0200 Subject: [PATCH 101/223] pixel agnostic Mutate/Clone defined --- src/ImageSharp/Image.cs | 15 ++++++-- src/ImageSharp/Image{TPixel}.cs | 19 ++++------- .../IImageProcessingContext{TPixel}.cs | 20 +++++------ .../Processing/ProcessingExtensions.cs | 34 ++++++++++++++++++- 4 files changed, 60 insertions(+), 28 deletions(-) diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index 6bea675b9..00a9a2075 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; @@ -13,8 +14,10 @@ namespace SixLabors.ImageSharp where TPixel : struct, IPixel; } - public abstract partial class Image : IImage + public abstract partial class Image : IImage, IConfigurable { + protected readonly Configuration configuration; + /// public PixelTypeInfo PixelType { get; } @@ -27,14 +30,20 @@ namespace SixLabors.ImageSharp /// public ImageMetadata Metadata { get; } - protected Image(PixelTypeInfo pixelType, ImageMetadata metadata) + /// + /// Gets the pixel buffer. + /// + Configuration IConfigurable.Configuration => this.configuration; + + protected Image(Configuration configuration, PixelTypeInfo pixelType, ImageMetadata metadata) { + this.configuration = configuration ?? Configuration.Default; this.PixelType = pixelType; this.Metadata = metadata ?? new ImageMetadata(); } public abstract void Dispose(); - internal abstract void ApplyVisitor(IImageVisitor visitor); + internal abstract void AcceptVisitor(IImageVisitor visitor); } } \ No newline at end of file diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 2cf389d37..64ec87c4d 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -18,11 +18,9 @@ namespace SixLabors.ImageSharp /// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes. /// /// The pixel format. - public sealed class Image : IImage, IConfigurable + public sealed class Image : Image where TPixel : struct, IPixel { - private readonly Configuration configuration; - /// /// Initializes a new instance of the class /// with the height and the width of the image. @@ -68,8 +66,8 @@ namespace SixLabors.ImageSharp /// The height of the image in pixels. /// The images metadata. internal Image(Configuration configuration, int width, int height, ImageMetadata metadata) + : base(configuration, PixelTypeInfo.Create(), metadata) { - this.configuration = configuration ?? Configuration.Default; this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); this.Metadata = metadata ?? new ImageMetadata(); this.Frames = new ImageFrameCollection(this, width, height, default(TPixel)); @@ -85,8 +83,8 @@ namespace SixLabors.ImageSharp /// The height of the image in pixels. /// The images metadata. internal Image(Configuration configuration, MemorySource memorySource, int width, int height, ImageMetadata metadata) + : base(configuration, PixelTypeInfo.Create(), metadata) { - this.configuration = configuration; this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); this.Metadata = metadata; this.Frames = new ImageFrameCollection(this, width, height, memorySource); @@ -102,8 +100,8 @@ namespace SixLabors.ImageSharp /// The color to initialize the pixels with. /// The images metadata. internal Image(Configuration configuration, int width, int height, TPixel backgroundColor, ImageMetadata metadata) + : base(configuration, PixelTypeInfo.Create(), metadata) { - this.configuration = configuration ?? Configuration.Default; this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); this.Metadata = metadata ?? new ImageMetadata(); this.Frames = new ImageFrameCollection(this, width, height, backgroundColor); @@ -117,18 +115,14 @@ namespace SixLabors.ImageSharp /// The images metadata. /// The frames that will be owned by this image instance. internal Image(Configuration configuration, ImageMetadata metadata, IEnumerable> frames) + : base(configuration,PixelTypeInfo.Create(), metadata) { - this.configuration = configuration ?? Configuration.Default; this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); this.Metadata = metadata ?? new ImageMetadata(); this.Frames = new ImageFrameCollection(this, frames); } - /// - /// Gets the pixel buffer. - /// - Configuration IConfigurable.Configuration => this.configuration; /// public PixelTypeInfo PixelType { get; } @@ -142,7 +136,6 @@ namespace SixLabors.ImageSharp /// public ImageMetadata Metadata { get; } - /// /// Gets the frames. /// public ImageFrameCollection Frames { get; } @@ -220,7 +213,7 @@ namespace SixLabors.ImageSharp /// public void Dispose() => this.Frames.Dispose(); - internal override void ApplyVisitor(IImageVisitor visitor) + internal override void AcceptVisitor(IImageVisitor visitor) { visitor.Visit(this); } diff --git a/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs b/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs index 72b78b32a..1b4fbd3be 100644 --- a/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs +++ b/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs @@ -9,16 +9,6 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { public interface IImageProcessingContext - { - - } - - /// - /// An interface to queue up image operations to apply to an image. - /// - /// The pixel format - public interface IImageProcessingContext - where TPixel : struct, IPixel { /// /// Gets a reference to the used to allocate buffers @@ -31,7 +21,15 @@ namespace SixLabors.ImageSharp.Processing /// /// The Size GetCurrentSize(); - + } + + /// + /// An interface to queue up image operations to apply to an image. + /// + /// The pixel format + public interface IImageProcessingContext : IImageProcessingContext + where TPixel : struct, IPixel + { /// /// Adds the processor to the current set of image operations to be applied. /// diff --git a/src/ImageSharp/Processing/ProcessingExtensions.cs b/src/ImageSharp/Processing/ProcessingExtensions.cs index c96b97111..a1acf3aa0 100644 --- a/src/ImageSharp/Processing/ProcessingExtensions.cs +++ b/src/ImageSharp/Processing/ProcessingExtensions.cs @@ -13,9 +13,41 @@ namespace SixLabors.ImageSharp.Processing /// public static class ProcessingExtensions { - public static void Mutate(this Image source, Action operation) + class ProcessingVisitor : IImageVisitor { + private readonly Action operation; + + private readonly bool mutate; + public Image ResultImage { get; private set; } + + public ProcessingVisitor(Action operation, bool mutate) + { + this.operation = operation; + this.mutate = mutate; + } + + public void Visit(Image image) + where TPixel : struct, IPixel + { + IInternalImageProcessingContext operationsRunner = image.GetConfiguration() + .ImageOperationsProvider.CreateImageProcessingContext(image, this.mutate); + this.operation(operationsRunner); + this.ResultImage = operationsRunner.Apply(); + } + } + + public static void Mutate(this Image source, Action operation) + { + ProcessingVisitor visitor = new ProcessingVisitor(operation, true); + source.AcceptVisitor(visitor); + } + + public static Image Clone(this Image source, Action operation) + { + ProcessingVisitor visitor = new ProcessingVisitor(operation, false); + source.AcceptVisitor(visitor); + return visitor.ResultImage; } /// From 75973d470b7b9dc5cac50da46696b8ca2bbf50f0 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 1 May 2019 21:56:21 +0200 Subject: [PATCH 102/223] pixel-agnostic ResizeProcessor --- .../DefaultInternalImageProcessorContext.cs | 12 + .../IImageProcessingContext{TPixel}.cs | 6 +- src/ImageSharp/Processing/PadExtensions.cs | 3 +- .../Transforms/Resize/ResizeProcessor.cs | 260 ++++-------------- .../Resize/ResizeProcessorImplementation.cs | 188 +++++++++++++ src/ImageSharp/Processing/ResizeExtensions.cs | 40 +-- .../FakeImageOperationsProvider.cs | 10 + .../Image/ImageProcessingContextTests.cs | 74 ++--- 8 files changed, 326 insertions(+), 267 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs diff --git a/src/ImageSharp/Processing/DefaultInternalImageProcessorContext.cs b/src/ImageSharp/Processing/DefaultInternalImageProcessorContext.cs index 43ba25972..091da003a 100644 --- a/src/ImageSharp/Processing/DefaultInternalImageProcessorContext.cs +++ b/src/ImageSharp/Processing/DefaultInternalImageProcessorContext.cs @@ -53,6 +53,18 @@ namespace SixLabors.ImageSharp.Processing /// public Size GetCurrentSize() => this.GetCurrentBounds().Size; + public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle) + { + var processorImplementation = processor.CreatePixelSpecificProcessor(); + return this.ApplyProcessor(processorImplementation, rectangle); + } + + public IImageProcessingContext ApplyProcessor(IImageProcessor processor) + { + var processorImplementation = processor.CreatePixelSpecificProcessor(); + return this.ApplyProcessor(processorImplementation); + } + /// public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle) { diff --git a/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs b/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs index 1b4fbd3be..fefa973f7 100644 --- a/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs +++ b/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs @@ -21,8 +21,12 @@ namespace SixLabors.ImageSharp.Processing /// /// The Size GetCurrentSize(); + + IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle); + + IImageProcessingContext ApplyProcessor(IImageProcessor processor); } - + /// /// An interface to queue up image operations to apply to an image. /// diff --git a/src/ImageSharp/Processing/PadExtensions.cs b/src/ImageSharp/Processing/PadExtensions.cs index f73033968..2db219795 100644 --- a/src/ImageSharp/Processing/PadExtensions.cs +++ b/src/ImageSharp/Processing/PadExtensions.cs @@ -19,8 +19,7 @@ namespace SixLabors.ImageSharp.Processing /// The new width. /// The new height. /// The . - public static IImageProcessingContext Pad(this IImageProcessingContext source, int width, int height) - where TPixel : struct, IPixel + public static IImageProcessingContext Pad(this IImageProcessingContext source, int width, int height) { var options = new ResizeOptions { diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index e75f6014a..4348ecdab 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -1,98 +1,40 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. using System; -using System.Buffers; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { - /// - /// Provides methods that allow the resizing of images using various algorithms. - /// Adapted from - /// - /// The pixel format. - internal class ResizeProcessor : TransformProcessorBase - where TPixel : struct, IPixel + public class ResizeProcessor : IImageProcessor { - // The following fields are not immutable but are optionally created on demand. - private ResizeKernelMap horizontalKernelMap; - private ResizeKernelMap verticalKernelMap; - /// - /// Initializes a new instance of the class. + /// Gets the sampler to perform the resize operation. /// - /// The resize options - /// The source image size - public ResizeProcessor(ResizeOptions options, Size sourceSize) - { - Guard.NotNull(options, nameof(options)); - Guard.NotNull(options.Sampler, nameof(options.Sampler)); - - int targetWidth = options.Size.Width; - int targetHeight = options.Size.Height; - - // Ensure size is populated across both dimensions. - // These dimensions are used to calculate the final dimensions determined by the mode algorithm. - // If only one of the incoming dimensions is 0, it will be modified here to maintain aspect ratio. - // If it is not possible to keep aspect ratio, make sure at least the minimum is is kept. - const int min = 1; - if (targetWidth == 0 && targetHeight > 0) - { - targetWidth = (int)MathF.Max(min, MathF.Round(sourceSize.Width * targetHeight / (float)sourceSize.Height)); - } - - if (targetHeight == 0 && targetWidth > 0) - { - targetHeight = (int)MathF.Max(min, MathF.Round(sourceSize.Height * targetWidth / (float)sourceSize.Width)); - } - - Guard.MustBeGreaterThan(targetWidth, 0, nameof(targetWidth)); - Guard.MustBeGreaterThan(targetHeight, 0, nameof(targetHeight)); + public IResampler Sampler { get; } - (Size size, Rectangle rectangle) = ResizeHelper.CalculateTargetLocationAndBounds(sourceSize, options, targetWidth, targetHeight); + /// + /// Gets the target width. + /// + public int Width { get; } - this.Sampler = options.Sampler; - this.Width = size.Width; - this.Height = size.Height; - this.TargetRectangle = rectangle; - this.Compand = options.Compand; - } + /// + /// Gets the target height. + /// + public int Height { get; } /// - /// Initializes a new instance of the class. + /// Gets the resize rectangle. /// - /// The sampler to perform the resize operation. - /// The target width. - /// The target height. - /// The source image size - public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize) - : this(sampler, width, height, sourceSize, new Rectangle(0, 0, width, height), false) - { - } + public Rectangle TargetRectangle { get; } /// - /// Initializes a new instance of the class. + /// Gets a value indicating whether to compress or expand individual pixel color values on processing. /// - /// The sampler to perform the resize operation. - /// The target width. - /// The target height. - /// The source image size - /// - /// The structure that specifies the portion of the target image object to draw to. - /// - /// Whether to compress or expand individual pixel color values on processing. + public bool Compand { get; } + public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize, Rectangle targetRectangle, bool compand) { Guard.NotNull(sampler, nameof(sampler)); @@ -122,149 +64,63 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.TargetRectangle = targetRectangle; this.Compand = compand; } - - /// - /// Gets the sampler to perform the resize operation. - /// - public IResampler Sampler { get; } - - /// - /// Gets the target width. - /// - public int Width { get; } - + /// - /// Gets the target height. + /// Initializes a new instance of the class. /// - public int Height { get; } - - /// - /// Gets the resize rectangle. - /// - public Rectangle TargetRectangle { get; } - - /// - /// Gets a value indicating whether to compress or expand individual pixel color values on processing. - /// - public bool Compand { get; } - - /// - protected override Image CreateDestination(Image source, Rectangle sourceRectangle) - { - // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.Width, this.Height, x.Metadata.DeepClone())); - - // Use the overload to prevent an extra frame being added - return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); - } - - /// - protected override void BeforeImageApply(Image source, Image destination, Rectangle sourceRectangle) + /// The resize options + /// The source image size + public ResizeProcessor(ResizeOptions options, Size sourceSize) { - if (!(this.Sampler is NearestNeighborResampler)) - { - // Since all image frame dimensions have to be the same we can calculate this for all frames. - MemoryAllocator memoryAllocator = source.GetMemoryAllocator(); - this.horizontalKernelMap = ResizeKernelMap.Calculate( - this.Sampler, - this.TargetRectangle.Width, - sourceRectangle.Width, - memoryAllocator); + Guard.NotNull(options, nameof(options)); + Guard.NotNull(options.Sampler, nameof(options.Sampler)); - this.verticalKernelMap = ResizeKernelMap.Calculate( - this.Sampler, - this.TargetRectangle.Height, - sourceRectangle.Height, - memoryAllocator); - } - } + int targetWidth = options.Size.Width; + int targetHeight = options.Size.Height; - /// - protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) - { - // Handle resize dimensions identical to the original - if (source.Width == destination.Width && source.Height == destination.Height && sourceRectangle == this.TargetRectangle) + // Ensure size is populated across both dimensions. + // These dimensions are used to calculate the final dimensions determined by the mode algorithm. + // If only one of the incoming dimensions is 0, it will be modified here to maintain aspect ratio. + // If it is not possible to keep aspect ratio, make sure at least the minimum is is kept. + const int min = 1; + if (targetWidth == 0 && targetHeight > 0) { - // The cloned will be blank here copy all the pixel data over - source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); - return; + targetWidth = (int)MathF.Max(min, MathF.Round(sourceSize.Width * targetHeight / (float)sourceSize.Height)); } - int width = this.Width; - int height = this.Height; - int sourceX = sourceRectangle.X; - int sourceY = sourceRectangle.Y; - int startY = this.TargetRectangle.Y; - int startX = this.TargetRectangle.X; - - var targetWorkingRect = Rectangle.Intersect( - this.TargetRectangle, - new Rectangle(0, 0, width, height)); - - if (this.Sampler is NearestNeighborResampler) + if (targetHeight == 0 && targetWidth > 0) { - // Scaling factors - float widthFactor = sourceRectangle.Width / (float)this.TargetRectangle.Width; - float heightFactor = sourceRectangle.Height / (float)this.TargetRectangle.Height; - - ParallelHelper.IterateRows( - targetWorkingRect, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - // Y coordinates of source points - Span sourceRow = - source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); - Span targetRow = destination.GetPixelRowSpan(y); - - for (int x = targetWorkingRect.Left; x < targetWorkingRect.Right; x++) - { - // X coordinates of source points - targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; - } - } - }); - - return; + targetHeight = (int)MathF.Max(min, MathF.Round(sourceSize.Height * targetWidth / (float)sourceSize.Width)); } - int sourceHeight = source.Height; - - PixelConversionModifiers conversionModifiers = - PixelConversionModifiers.Premultiply.ApplyCompanding(this.Compand); - - BufferArea sourceArea = source.PixelBuffer.GetArea(sourceRectangle); + Guard.MustBeGreaterThan(targetWidth, 0, nameof(targetWidth)); + Guard.MustBeGreaterThan(targetHeight, 0, nameof(targetHeight)); - // To reintroduce parallel processing, we to launch multiple workers - // for different row intervals of the image. - using (var worker = new ResizeWorker( - configuration, - sourceArea, - conversionModifiers, - this.horizontalKernelMap, - this.verticalKernelMap, - width, - targetWorkingRect, - this.TargetRectangle.Location)) - { - worker.Initialize(); + (Size size, Rectangle rectangle) = ResizeHelper.CalculateTargetLocationAndBounds(sourceSize, options, targetWidth, targetHeight); - var workingInterval = new RowInterval(targetWorkingRect.Top, targetWorkingRect.Bottom); - worker.FillDestinationPixels(workingInterval, destination.PixelBuffer); - } + this.Sampler = options.Sampler; + this.Width = size.Width; + this.Height = size.Height; + this.TargetRectangle = rectangle; + this.Compand = options.Compand; } - protected override void AfterImageApply(Image source, Image destination, Rectangle sourceRectangle) + /// + /// Initializes a new instance of the class. + /// + /// The sampler to perform the resize operation. + /// The target width. + /// The target height. + /// The source image size + public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize) + : this(sampler, width, height, sourceSize, new Rectangle(0, 0, width, height), false) { - base.AfterImageApply(source, destination, sourceRectangle); + } - // TODO: An exception in the processing chain can leave these buffers undisposed. We should consider making image processors IDisposable! - this.horizontalKernelMap?.Dispose(); - this.horizontalKernelMap = null; - this.verticalKernelMap?.Dispose(); - this.verticalKernelMap = null; + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + return new ResizeProcessorImplementation(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs new file mode 100644 index 000000000..6c3db3da7 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs @@ -0,0 +1,188 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + // The non-generic processor is responsible for: + // - Encapsulating the parameters of the processor + // - Implementing a factory method to create the pixel-specific processor that contains the implementation + + /// + /// Provides methods that allow the resizing of images using various algorithms. + /// Adapted from + /// + /// The pixel format. + internal class ResizeProcessorImplementation : TransformProcessorBase + where TPixel : struct, IPixel + { + // The following fields are not immutable but are optionally created on demand. + private ResizeKernelMap horizontalKernelMap; + private ResizeKernelMap verticalKernelMap; + + private readonly ResizeProcessor parameterSource; + + public ResizeProcessorImplementation(ResizeProcessor parameterSource) + { + this.parameterSource = parameterSource; + } + + /// + /// Gets the sampler to perform the resize operation. + /// + public IResampler Sampler => this.parameterSource.Sampler; + + /// + /// Gets the target width. + /// + public int Width => this.parameterSource.Width; + + /// + /// Gets the target height. + /// + public int Height => this.parameterSource.Height; + + /// + /// Gets the resize rectangle. + /// + public Rectangle TargetRectangle => this.parameterSource.TargetRectangle; + + /// + /// Gets a value indicating whether to compress or expand individual pixel color values on processing. + /// + public bool Compand => this.parameterSource.Compand; + + /// + protected override Image CreateDestination(Image source, Rectangle sourceRectangle) + { + // We will always be creating the clone even for mutate because we may need to resize the canvas + IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.Width, this.Height, x.Metadata.DeepClone())); + + // Use the overload to prevent an extra frame being added + return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); + } + + /// + protected override void BeforeImageApply(Image source, Image destination, Rectangle sourceRectangle) + { + if (!(this.Sampler is NearestNeighborResampler)) + { + // Since all image frame dimensions have to be the same we can calculate this for all frames. + MemoryAllocator memoryAllocator = source.GetMemoryAllocator(); + this.horizontalKernelMap = ResizeKernelMap.Calculate( + this.Sampler, + this.TargetRectangle.Width, + sourceRectangle.Width, + memoryAllocator); + + this.verticalKernelMap = ResizeKernelMap.Calculate( + this.Sampler, + this.TargetRectangle.Height, + sourceRectangle.Height, + memoryAllocator); + } + } + + /// + protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) + { + // Handle resize dimensions identical to the original + if (source.Width == destination.Width && source.Height == destination.Height && sourceRectangle == this.TargetRectangle) + { + // The cloned will be blank here copy all the pixel data over + source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); + return; + } + + int width = this.Width; + int height = this.Height; + int sourceX = sourceRectangle.X; + int sourceY = sourceRectangle.Y; + int startY = this.TargetRectangle.Y; + int startX = this.TargetRectangle.X; + + var targetWorkingRect = Rectangle.Intersect( + this.TargetRectangle, + new Rectangle(0, 0, width, height)); + + if (this.Sampler is NearestNeighborResampler) + { + // Scaling factors + float widthFactor = sourceRectangle.Width / (float)this.TargetRectangle.Width; + float heightFactor = sourceRectangle.Height / (float)this.TargetRectangle.Height; + + ParallelHelper.IterateRows( + targetWorkingRect, + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + // Y coordinates of source points + Span sourceRow = + source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); + Span targetRow = destination.GetPixelRowSpan(y); + + for (int x = targetWorkingRect.Left; x < targetWorkingRect.Right; x++) + { + // X coordinates of source points + targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; + } + } + }); + + return; + } + + int sourceHeight = source.Height; + + PixelConversionModifiers conversionModifiers = + PixelConversionModifiers.Premultiply.ApplyCompanding(this.Compand); + + BufferArea sourceArea = source.PixelBuffer.GetArea(sourceRectangle); + + // To reintroduce parallel processing, we to launch multiple workers + // for different row intervals of the image. + using (var worker = new ResizeWorker( + configuration, + sourceArea, + conversionModifiers, + this.horizontalKernelMap, + this.verticalKernelMap, + width, + targetWorkingRect, + this.TargetRectangle.Location)) + { + worker.Initialize(); + + var workingInterval = new RowInterval(targetWorkingRect.Top, targetWorkingRect.Bottom); + worker.FillDestinationPixels(workingInterval, destination.PixelBuffer); + } + } + + protected override void AfterImageApply(Image source, Image destination, Rectangle sourceRectangle) + { + base.AfterImageApply(source, destination, sourceRectangle); + + // TODO: An exception in the processing chain can leave these buffers undisposed. We should consider making image processors IDisposable! + this.horizontalKernelMap?.Dispose(); + this.horizontalKernelMap = null; + this.verticalKernelMap?.Dispose(); + this.verticalKernelMap = null; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/ResizeExtensions.cs b/src/ImageSharp/Processing/ResizeExtensions.cs index 7b6c14d7d..cf029eb15 100644 --- a/src/ImageSharp/Processing/ResizeExtensions.cs +++ b/src/ImageSharp/Processing/ResizeExtensions.cs @@ -20,9 +20,8 @@ namespace SixLabors.ImageSharp.Processing /// The resize options. /// The /// Passing zero for one of height or width within the resize options will automatically preserve the aspect ratio of the original image or the nearest possible ratio. - public static IImageProcessingContext Resize(this IImageProcessingContext source, ResizeOptions options) - where TPixel : struct, IPixel - => source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize())); + public static IImageProcessingContext Resize(this IImageProcessingContext source, ResizeOptions options) + => source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize())); /// /// Resizes an image to the given . @@ -32,8 +31,7 @@ namespace SixLabors.ImageSharp.Processing /// The target image size. /// The /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. - public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size) - where TPixel : struct, IPixel + public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size) => Resize(source, size.Width, size.Height, KnownResamplers.Bicubic, false); /// @@ -45,8 +43,7 @@ namespace SixLabors.ImageSharp.Processing /// Whether to compress and expand the image color-space to gamma correct the image during processing. /// The /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. - public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size, bool compand) - where TPixel : struct, IPixel + public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size, bool compand) => Resize(source, size.Width, size.Height, KnownResamplers.Bicubic, compand); /// @@ -58,8 +55,7 @@ namespace SixLabors.ImageSharp.Processing /// The target image height. /// The /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. - public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height) - where TPixel : struct, IPixel + public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height) => Resize(source, width, height, KnownResamplers.Bicubic, false); /// @@ -72,8 +68,7 @@ namespace SixLabors.ImageSharp.Processing /// Whether to compress and expand the image color-space to gamma correct the image during processing. /// The /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. - public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, bool compand) - where TPixel : struct, IPixel + public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, bool compand) => Resize(source, width, height, KnownResamplers.Bicubic, compand); /// @@ -86,8 +81,7 @@ namespace SixLabors.ImageSharp.Processing /// The to perform the resampling. /// The /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. - public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, IResampler sampler) - where TPixel : struct, IPixel + public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, IResampler sampler) => Resize(source, width, height, sampler, false); /// @@ -100,8 +94,7 @@ namespace SixLabors.ImageSharp.Processing /// Whether to compress and expand the image color-space to gamma correct the image during processing. /// The /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. - public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size, IResampler sampler, bool compand) - where TPixel : struct, IPixel + public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size, IResampler sampler, bool compand) => Resize(source, size.Width, size.Height, sampler, new Rectangle(0, 0, size.Width, size.Height), compand); /// @@ -115,8 +108,7 @@ namespace SixLabors.ImageSharp.Processing /// Whether to compress and expand the image color-space to gamma correct the image during processing. /// The /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. - public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, IResampler sampler, bool compand) - where TPixel : struct, IPixel + public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, IResampler sampler, bool compand) => Resize(source, width, height, sampler, new Rectangle(0, 0, width, height), compand); /// @@ -137,16 +129,15 @@ namespace SixLabors.ImageSharp.Processing /// Whether to compress and expand the image color-space to gamma correct the image during processing. /// The /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. - public static IImageProcessingContext Resize( - this IImageProcessingContext source, + public static IImageProcessingContext Resize( + this IImageProcessingContext source, int width, int height, IResampler sampler, Rectangle sourceRectangle, Rectangle targetRectangle, bool compand) - where TPixel : struct, IPixel - => source.ApplyProcessor(new ResizeProcessor(sampler, width, height, source.GetCurrentSize(), targetRectangle, compand), sourceRectangle); + => source.ApplyProcessor(new ResizeProcessor(sampler, width, height, source.GetCurrentSize(), targetRectangle, compand), sourceRectangle); /// /// Resizes an image to the given width and height with the given sampler and source rectangle. @@ -162,14 +153,13 @@ namespace SixLabors.ImageSharp.Processing /// Whether to compress and expand the image color-space to gamma correct the image during processing. /// The /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. - public static IImageProcessingContext Resize( - this IImageProcessingContext source, + public static IImageProcessingContext Resize( + this IImageProcessingContext source, int width, int height, IResampler sampler, Rectangle targetRectangle, bool compand) - where TPixel : struct, IPixel - => source.ApplyProcessor(new ResizeProcessor(sampler, width, height, source.GetCurrentSize(), targetRectangle, compand)); + => source.ApplyProcessor(new ResizeProcessor(sampler, width, height, source.GetCurrentSize(), targetRectangle, compand)); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs b/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs index ff4014e61..276cc5da8 100644 --- a/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs +++ b/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs @@ -67,6 +67,16 @@ namespace SixLabors.ImageSharp.Tests return this.Source.Size(); } + public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle) + { + throw new System.NotImplementedException(); + } + + public IImageProcessingContext ApplyProcessor(IImageProcessor processor) + { + throw new System.NotImplementedException(); + } + public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle) { this.Applied.Add(new AppliedOperation diff --git a/tests/ImageSharp.Tests/Image/ImageProcessingContextTests.cs b/tests/ImageSharp.Tests/Image/ImageProcessingContextTests.cs index 041b6c846..6dadc6e7a 100644 --- a/tests/ImageSharp.Tests/Image/ImageProcessingContextTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageProcessingContextTests.cs @@ -10,43 +10,43 @@ namespace SixLabors.ImageSharp.Tests { public class ImageProcessingContextTests { - [Fact] - public void MutatedSizeIsAccuratePerOperation() - { - var x500 = new Size(500, 500); - var x400 = new Size(400, 400); - var x300 = new Size(300, 300); - var x200 = new Size(200, 200); - var x100 = new Size(100, 100); - using (var image = new Image(500, 500)) - { - image.Mutate(x => - x.AssertSize(x500) - .Resize(x400).AssertSize(x400) - .Resize(x300).AssertSize(x300) - .Resize(x200).AssertSize(x200) - .Resize(x100).AssertSize(x100)); - } - } - - [Fact] - public void ClonedSizeIsAccuratePerOperation() - { - var x500 = new Size(500, 500); - var x400 = new Size(400, 400); - var x300 = new Size(300, 300); - var x200 = new Size(200, 200); - var x100 = new Size(100, 100); - using (var image = new Image(500, 500)) - { - image.Clone(x => - x.AssertSize(x500) - .Resize(x400).AssertSize(x400) - .Resize(x300).AssertSize(x300) - .Resize(x200).AssertSize(x200) - .Resize(x100).AssertSize(x100)); - } - } + // [Fact] + // public void MutatedSizeIsAccuratePerOperation() + // { + // var x500 = new Size(500, 500); + // var x400 = new Size(400, 400); + // var x300 = new Size(300, 300); + // var x200 = new Size(200, 200); + // var x100 = new Size(100, 100); + // using (var image = new Image(500, 500)) + // { + // image.Mutate(x => + // x.AssertSize(x500) + // .Resize(x400).AssertSize(x400) + // .Resize(x300).AssertSize(x300) + // .Resize(x200).AssertSize(x200) + // .Resize(x100).AssertSize(x100)); + // } + // } + // + // [Fact] + // public void ClonedSizeIsAccuratePerOperation() + // { + // var x500 = new Size(500, 500); + // var x400 = new Size(400, 400); + // var x300 = new Size(300, 300); + // var x200 = new Size(200, 200); + // var x100 = new Size(100, 100); + // using (var image = new Image(500, 500)) + // { + // image.Clone(x => + // x.AssertSize(x500) + // .Resize(x400).AssertSize(x400) + // .Resize(x300).AssertSize(x300) + // .Resize(x200).AssertSize(x200) + // .Resize(x100).AssertSize(x100)); + // } + // } } public static class SizeAssertationExtensions From 91a547beb9ca946d024db47da710433b138458b9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 1 May 2019 22:25:37 +0200 Subject: [PATCH 103/223] pixel-agnostic decoder API --- .../Advanced/AdvancedImageExtensions.cs | 3 +- src/ImageSharp/Formats/Bmp/BmpDecoder.cs | 2 + src/ImageSharp/Formats/Gif/GifDecoder.cs | 2 + src/ImageSharp/Formats/IImageDecoder.cs | 2 + src/ImageSharp/Formats/Jpeg/JpegDecoder.cs | 2 + src/ImageSharp/Formats/Png/PngDecoder.cs | 2 + src/ImageSharp/Image.Decode.cs | 12 ++++++ src/ImageSharp/Image.FromFile.cs | 30 ++++++-------- src/ImageSharp/Image.FromStream.cs | 41 ++++++++++++------- src/ImageSharp/Image.cs | 36 ++++++++++++++++ src/ImageSharp/ImageExtensions.cs | 9 ++-- src/ImageSharp/Image{TPixel}.cs | 14 ------- .../Processors/Transforms/ResizeTests.cs | 16 ++++++++ tests/ImageSharp.Tests/TestFormat.cs | 2 + .../ReferenceCodecs/MagickReferenceDecoder.cs | 2 + .../SystemDrawingReferenceDecoder.cs | 2 + .../Tests/TestImageProviderTests.cs | 4 ++ 17 files changed, 127 insertions(+), 54 deletions(-) diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs index bdcb4c10f..378b6e8b9 100644 --- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs +++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs @@ -21,8 +21,7 @@ namespace SixLabors.ImageSharp.Advanced /// The Pixel format. /// The source image. /// Returns the configuration. - public static Configuration GetConfiguration(this Image source) - where TPixel : struct, IPixel + public static Configuration GetConfiguration(this Image source) => GetConfiguration((IConfigurable)source); /// diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs index 82af2a671..4922a9200 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs @@ -30,6 +30,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp return new BmpDecoderCore(configuration, this).Decode(stream); } + public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); + /// public IImageInfo Identify(Configuration configuration, Stream stream) { diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs index 6af75f2d0..6498f4aa2 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoder.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs @@ -44,5 +44,7 @@ namespace SixLabors.ImageSharp.Formats.Gif var decoder = new GifDecoderCore(configuration, this); return decoder.Identify(stream); } + + public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } } diff --git a/src/ImageSharp/Formats/IImageDecoder.cs b/src/ImageSharp/Formats/IImageDecoder.cs index ffc40314d..625c4efb6 100644 --- a/src/ImageSharp/Formats/IImageDecoder.cs +++ b/src/ImageSharp/Formats/IImageDecoder.cs @@ -20,5 +20,7 @@ namespace SixLabors.ImageSharp.Formats /// The decoded image Image Decode(Configuration configuration, Stream stream) where TPixel : struct, IPixel; + + Image Decode(Configuration configuration, Stream stream); } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs index 57b70dd26..7459abec5 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs @@ -38,5 +38,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg return decoder.Identify(stream); } } + + public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/PngDecoder.cs b/src/ImageSharp/Formats/Png/PngDecoder.cs index 39dfb1d0b..e8c5ac8e8 100644 --- a/src/ImageSharp/Formats/Png/PngDecoder.cs +++ b/src/ImageSharp/Formats/Png/PngDecoder.cs @@ -59,5 +59,7 @@ namespace SixLabors.ImageSharp.Formats.Png var decoder = new PngDecoderCore(configuration, this); return decoder.Identify(stream); } + + public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } } \ No newline at end of file diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index 9e83d173f..36944dc2c 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -102,6 +102,18 @@ namespace SixLabors.ImageSharp Image img = decoder.Decode(config, stream); return (img, format); } + + private static (Image img, IImageFormat format) Decode(Stream stream, Configuration config) + { + IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format); + if (decoder is null) + { + return (null, null); + } + + Image img = decoder.Decode(config, stream); + return (img, format); + } /// /// Reads the raw image information from the specified stream. diff --git a/src/ImageSharp/Image.FromFile.cs b/src/ImageSharp/Image.FromFile.cs index b13cef482..80267146d 100644 --- a/src/ImageSharp/Image.FromFile.cs +++ b/src/ImageSharp/Image.FromFile.cs @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(string path) => Load(path); + public static Image Load(string path) => Load(path); /// /// Create a new instance of the class from the given file. @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(string path, out IImageFormat format) => Load(path, out format); + public static Image Load(string path, out IImageFormat format) => Load(path, out format); /// /// Create a new instance of the class from the given file. @@ -68,19 +68,7 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(Configuration config, string path) => Load(config, path); - - /// - /// Create a new instance of the class from the given file. - /// - /// The config for the decoder. - /// The file path to the image. - /// The mime type of the decoded image. - /// - /// Thrown if the stream is not readable nor seekable. - /// - /// A new . - public static Image Load(Configuration config, string path, out IImageFormat format) => Load(config, path, out format); + public static Image Load(Configuration config, string path) => Load(config, path); /// /// Create a new instance of the class from the given file. @@ -92,7 +80,7 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(Configuration config, string path, IImageDecoder decoder) => Load(config, path, decoder); + public static Image Load(Configuration config, string path, IImageDecoder decoder) => Load(config, path, decoder); /// /// Create a new instance of the class from the given file. @@ -103,7 +91,7 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(string path, IImageDecoder decoder) => Load(path, decoder); + public static Image Load(string path, IImageDecoder decoder) => Load(path, decoder); /// /// Create a new instance of the class from the given file. @@ -174,6 +162,14 @@ namespace SixLabors.ImageSharp return Load(config, stream, out format); } } + + public static Image Load(Configuration config, string path, out IImageFormat format) + { + using (Stream stream = config.FileSystem.OpenRead(path)) + { + return Load(config, stream, out format); + } + } /// /// Create a new instance of the class from the given file. diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index 3236e0007..8848225f5 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp /// the mime type of the decoded image. /// Thrown if the stream is not readable. /// A new .> - public static Image Load(Stream stream, out IImageFormat format) => Load(stream, out format); + public static Image Load(Stream stream, out IImageFormat format) => Load(stream, out format); /// /// Create a new instance of the class from the given stream. @@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp /// The stream containing image information. /// Thrown if the stream is not readable. /// A new .> - public static Image Load(Stream stream) => Load(stream); + public static Image Load(Stream stream) => Load(stream); /// /// Create a new instance of the class from the given stream. @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp /// The decoder. /// Thrown if the stream is not readable. /// A new .> - public static Image Load(Stream stream, IImageDecoder decoder) => Load(stream, decoder); + public static Image Load(Stream stream, IImageDecoder decoder) => Load(stream, decoder); /// /// Create a new instance of the class from the given stream. @@ -88,18 +88,7 @@ namespace SixLabors.ImageSharp /// The stream containing image information. /// Thrown if the stream is not readable. /// A new .> - public static Image Load(Configuration config, Stream stream) => Load(config, stream); - - /// - /// Create a new instance of the class from the given stream. - /// - /// The config for the decoder. - /// The stream containing image information. - /// the mime type of the decoded image. - /// Thrown if the stream is not readable. - /// A new .> - public static Image Load(Configuration config, Stream stream, out IImageFormat format) - => Load(config, stream, out format); + public static Image Load(Configuration config, Stream stream) => Load(config, stream); /// /// Create a new instance of the class from the given stream. @@ -193,6 +182,28 @@ namespace SixLabors.ImageSharp throw new NotSupportedException(sb.ToString()); } + private static Image Load(Configuration config, Stream stream, out IImageFormat format) + { + config = config ?? Configuration.Default; + (Image img, IImageFormat format) data = WithSeekableStream(config, stream, s => Decode(s, config)); + + format = data.format; + + if (data.img != null) + { + return data.img; + } + + var sb = new StringBuilder(); + sb.AppendLine("Image cannot be loaded. Available decoders:"); + + foreach (KeyValuePair val in config.ImageFormatsManager.ImageDecoders) + { + sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}"); + } + + throw new NotSupportedException(sb.ToString()); + } private static T WithSeekableStream(Configuration config, Stream stream, Func action) { diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index 00a9a2075..a27f16ab3 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System.IO; + using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Metadata; @@ -45,5 +47,39 @@ namespace SixLabors.ImageSharp public abstract void Dispose(); internal abstract void AcceptVisitor(IImageVisitor visitor); + + /// + /// Saves the image to the given stream using the given image encoder. + /// + /// The stream to save the image to. + /// The encoder to save the image with. + /// Thrown if the stream or encoder is null. + public void Save(Stream stream, IImageEncoder encoder) + { + Guard.NotNull(stream, nameof(stream)); + Guard.NotNull(encoder, nameof(encoder)); + + EncodeVisitor visitor = new EncodeVisitor(encoder, stream); + this.AcceptVisitor(visitor); + } + + class EncodeVisitor : IImageVisitor + { + private readonly IImageEncoder encoder; + + private readonly Stream stream; + + public EncodeVisitor(IImageEncoder encoder, Stream stream) + { + this.encoder = encoder; + this.stream = stream; + } + + public void Visit(Image image) + where TPixel : struct, IPixel + { + this.encoder.Encode(image, this.stream); + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs index 5010451b8..3bd60694d 100644 --- a/src/ImageSharp/ImageExtensions.cs +++ b/src/ImageSharp/ImageExtensions.cs @@ -23,8 +23,7 @@ namespace SixLabors.ImageSharp /// The source image. /// The file path to save the image to. /// Thrown if the stream is null. - public static void Save(this Image source, string filePath) - where TPixel : struct, IPixel + public static void Save(this Image source, string filePath) { Guard.NotNullOrWhiteSpace(filePath, nameof(filePath)); @@ -67,8 +66,7 @@ namespace SixLabors.ImageSharp /// The file path to save the image to. /// The encoder to save the image with. /// Thrown if the encoder is null. - public static void Save(this Image source, string filePath, IImageEncoder encoder) - where TPixel : struct, IPixel + public static void Save(this Image source, string filePath, IImageEncoder encoder) { Guard.NotNull(encoder, nameof(encoder)); using (Stream fs = source.GetConfiguration().FileSystem.Create(filePath)) @@ -85,8 +83,7 @@ namespace SixLabors.ImageSharp /// The stream to save the image to. /// The format to save the image in. /// Thrown if the stream is null. - public static void Save(this Image source, Stream stream, IImageFormat format) - where TPixel : struct, IPixel + public static void Save(this Image source, Stream stream, IImageFormat format) { Guard.NotNull(format, nameof(format)); IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 64ec87c4d..e37f3e4c1 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -158,20 +158,6 @@ namespace SixLabors.ImageSharp set => this.PixelSource.PixelBuffer[x, y] = value; } - /// - /// Saves the image to the given stream using the given image encoder. - /// - /// The stream to save the image to. - /// The encoder to save the image with. - /// Thrown if the stream or encoder is null. - public void Save(Stream stream, IImageEncoder encoder) - { - Guard.NotNull(stream, nameof(stream)); - Guard.NotNull(encoder, nameof(encoder)); - - encoder.Encode(this, stream); - } - /// /// Clones the current image /// diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index e3a43a652..c7af8d468 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -42,6 +42,22 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.07F); + [Fact] + public void Resize_PixelAgnostic() + { + var filePath = TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora); + + using (Image image = Image.Load(filePath)) + { + image.Mutate(x => x.Resize(image.Size() / 2)); + string path = System.IO.Path.Combine( + TestEnvironment.CreateOutputDirectory(nameof(ResizeTests)), + nameof(this.Resize_PixelAgnostic) + ".png"); + + image.Save(path); + } + } + [Theory( Skip = "Debug only, enable manually" )] diff --git a/tests/ImageSharp.Tests/TestFormat.cs b/tests/ImageSharp.Tests/TestFormat.cs index 64357a17e..91e31b356 100644 --- a/tests/ImageSharp.Tests/TestFormat.cs +++ b/tests/ImageSharp.Tests/TestFormat.cs @@ -199,6 +199,8 @@ namespace SixLabors.ImageSharp.Tests } public bool IsSupportedFileFormat(Span header) => testFormat.IsSupportedFileFormat(header); + + public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } public class TestEncoder : ImageSharp.Formats.IImageEncoder diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index 3dd330e4d..e81714ddc 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -57,5 +57,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs return result; } } + + public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs index 7a775c081..2de3c03aa 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs @@ -51,5 +51,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs return new ImageInfo(pixelType, sourceBitmap.Width, sourceBitmap.Height, new ImageMetadata()); } } + + public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 4ef6a582c..b49baa5c4 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -379,6 +379,8 @@ namespace SixLabors.ImageSharp.Tests this.callerName = name; invocationCounts[name] = 0; } + + public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } private class TestDecoderWithParameters : IImageDecoder @@ -416,6 +418,8 @@ namespace SixLabors.ImageSharp.Tests this.callerName = name; invocationCounts[name] = 0; } + + public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } } } \ No newline at end of file From 442e22cf07299b450c496d06e62daeb9afecb47a Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 1 May 2019 22:38:25 +0200 Subject: [PATCH 104/223] refactor FilterProcessor stuff --- src/ImageSharp/IImage.cs | 2 +- .../Processing/BlackWhiteExtensions.cs | 12 ++-- src/ImageSharp/Processing/FilterExtensions.cs | 12 ++-- .../Processing/OpacityExtensions.cs | 12 ++-- .../Processors/Filters/BlackWhiteProcessor.cs | 3 +- .../Processors/Filters/FilterProcessor.cs | 43 ++------------- .../Filters/FilterProcessorImplementation.cs | 55 +++++++++++++++++++ .../Processors/Filters/OpacityProcessor.cs | 3 +- .../Transforms/Resize/ResizeProcessor.cs | 7 ++- .../Resize/ResizeProcessorImplementation.cs | 4 -- .../Processors/Transforms/ResizeTests.cs | 1 + 11 files changed, 82 insertions(+), 72 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs diff --git a/src/ImageSharp/IImage.cs b/src/ImageSharp/IImage.cs index fb251cfd5..b9e2cee61 100644 --- a/src/ImageSharp/IImage.cs +++ b/src/ImageSharp/IImage.cs @@ -4,7 +4,7 @@ using System; namespace SixLabors.ImageSharp -{ +{ /// /// Encapsulates the properties and methods that describe an image. /// diff --git a/src/ImageSharp/Processing/BlackWhiteExtensions.cs b/src/ImageSharp/Processing/BlackWhiteExtensions.cs index 0484fa84e..5dc2341e5 100644 --- a/src/ImageSharp/Processing/BlackWhiteExtensions.cs +++ b/src/ImageSharp/Processing/BlackWhiteExtensions.cs @@ -15,24 +15,20 @@ namespace SixLabors.ImageSharp.Processing /// /// Applies black and white toning to the image. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext BlackWhite(this IImageProcessingContext source) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BlackWhiteProcessor()); + public static IImageProcessingContext BlackWhite(this IImageProcessingContext source) + => source.ApplyProcessor(new BlackWhiteProcessor()); /// /// Applies black and white toning to the image. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext BlackWhite(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BlackWhiteProcessor(), rectangle); + public static IImageProcessingContext BlackWhite(this IImageProcessingContext source, Rectangle rectangle) + => source.ApplyProcessor(new BlackWhiteProcessor(), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/FilterExtensions.cs b/src/ImageSharp/Processing/FilterExtensions.cs index 70ac23286..2a1c6bc7f 100644 --- a/src/ImageSharp/Processing/FilterExtensions.cs +++ b/src/ImageSharp/Processing/FilterExtensions.cs @@ -16,26 +16,22 @@ namespace SixLabors.ImageSharp.Processing /// /// Filters an image but the given color matrix /// - /// The pixel format. /// The image this method extends. /// The filter color matrix /// The . - public static IImageProcessingContext Filter(this IImageProcessingContext source, ColorMatrix matrix) - where TPixel : struct, IPixel - => source.ApplyProcessor(new FilterProcessor(matrix)); + public static IImageProcessingContext Filter(this IImageProcessingContext source, ColorMatrix matrix) + => source.ApplyProcessor(new FilterProcessor(matrix)); /// /// Filters an image but the given color matrix /// - /// The pixel format. /// The image this method extends. /// The filter color matrix /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Filter(this IImageProcessingContext source, ColorMatrix matrix, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new FilterProcessor(matrix), rectangle); + public static IImageProcessingContext Filter(this IImageProcessingContext source, ColorMatrix matrix, Rectangle rectangle) + => source.ApplyProcessor(new FilterProcessor(matrix), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/OpacityExtensions.cs b/src/ImageSharp/Processing/OpacityExtensions.cs index fc3fd331d..6d9198648 100644 --- a/src/ImageSharp/Processing/OpacityExtensions.cs +++ b/src/ImageSharp/Processing/OpacityExtensions.cs @@ -15,26 +15,22 @@ namespace SixLabors.ImageSharp.Processing /// /// Multiplies the alpha component of the image. /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be between 0 and 1. /// The . - public static IImageProcessingContext Opacity(this IImageProcessingContext source, float amount) - where TPixel : struct, IPixel - => source.ApplyProcessor(new OpacityProcessor(amount)); + public static IImageProcessingContext Opacity(this IImageProcessingContext source, float amount) + => source.ApplyProcessor(new OpacityProcessor(amount)); /// /// Multiplies the alpha component of the image. /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be between 0 and 1. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Opacity(this IImageProcessingContext source, float amount, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new OpacityProcessor(amount), rectangle); + public static IImageProcessingContext Opacity(this IImageProcessingContext source, float amount, Rectangle rectangle) + => source.ApplyProcessor(new OpacityProcessor(amount), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs index 9925ce5c2..8bf925cf0 100644 --- a/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs @@ -9,8 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// Applies a black and white filter matrix to the image /// /// The pixel format. - internal class BlackWhiteProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class BlackWhiteProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs index dbd843341..3f9f58687 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs @@ -1,25 +1,15 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Numerics; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Filters { - /// - /// Provides methods that accept a matrix to apply free-form filters to images. - /// - /// The pixel format. - internal class FilterProcessor : ImageProcessor - where TPixel : struct, IPixel + public class FilterProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The matrix used to apply the image filter public FilterProcessor(ColorMatrix matrix) => this.Matrix = matrix; @@ -29,31 +19,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// public ColorMatrix Matrix { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); - int startX = interest.X; - - ColorMatrix matrix = this.Matrix; - - ParallelHelper.IterateRowsWithTempBuffer( - interest, - configuration, - (rows, vectorBuffer) => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span vectorSpan = vectorBuffer.Span; - int length = vectorSpan.Length; - Span rowSpan = source.GetPixelRowSpan(y).Slice(startX, length); - PixelOperations.Instance.ToVector4(configuration, rowSpan, vectorSpan); - - Vector4Utils.Transform(vectorSpan, ref matrix); - - PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, rowSpan); - } - }); + return new FilterProcessorImplementation(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs new file mode 100644 index 000000000..1eaaf1ea5 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs @@ -0,0 +1,55 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Filters +{ + /// + /// Provides methods that accept a matrix to apply free-form filters to images. + /// + /// The pixel format. + internal class FilterProcessorImplementation : ImageProcessor + where TPixel : struct, IPixel + { + private readonly FilterProcessor paramterSource; + + public FilterProcessorImplementation(FilterProcessor paramterSource) + { + this.paramterSource = paramterSource; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); + int startX = interest.X; + + ColorMatrix matrix = this.paramterSource.Matrix; + + ParallelHelper.IterateRowsWithTempBuffer( + interest, + configuration, + (rows, vectorBuffer) => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span vectorSpan = vectorBuffer.Span; + int length = vectorSpan.Length; + Span rowSpan = source.GetPixelRowSpan(y).Slice(startX, length); + PixelOperations.Instance.ToVector4(configuration, rowSpan, vectorSpan); + + Vector4Utils.Transform(vectorSpan, ref matrix); + + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, rowSpan); + } + }); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs index 0fea61cad..2d6bf6e83 100644 --- a/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs @@ -9,8 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// Applies an opacity filter matrix using the given amount. /// /// The pixel format. - internal class OpacityProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class OpacityProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 4348ecdab..d3077b7e6 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -1,5 +1,5 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. using System; @@ -8,6 +8,9 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { + // The non-generic processor is responsible for: + // - Encapsulating the parameters of the processor + // - Implementing a factory method to create the pixel-specific processor that contains the implementation public class ResizeProcessor : IImageProcessor { /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs index 6c3db3da7..1a8bb931e 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs @@ -18,10 +18,6 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { - // The non-generic processor is responsible for: - // - Encapsulating the parameters of the processor - // - Implementing a factory method to create the pixel-specific processor that contains the implementation - /// /// Provides methods that allow the resizing of images using various algorithms. /// Adapted from diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index c7af8d468..9bf9079d4 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -40,6 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms nameof(KnownResamplers.Lanczos5), }; + private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.07F); [Fact] From 87495d7a6361c1deb5d77e22c0d01c41aa7dece2 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 00:15:12 +0200 Subject: [PATCH 105/223] basic fixes after rebase + temporarily comment out target frameworks --- src/ImageSharp/Formats/PixelTypeInfo.cs | 8 ++++++++ src/ImageSharp/Image.Decode.cs | 2 +- src/ImageSharp/Image.FromBytes.cs | 2 +- src/ImageSharp/Image.FromFile.cs | 2 +- src/ImageSharp/Image.FromStream.cs | 2 +- src/ImageSharp/Image.LoadPixelData.cs | 2 +- src/ImageSharp/Image.WrapMemory.cs | 2 +- src/ImageSharp/ImageSharp.csproj | 5 ++++- src/ImageSharp/Image{TPixel}.cs | 6 +++--- 9 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/ImageSharp/Formats/PixelTypeInfo.cs b/src/ImageSharp/Formats/PixelTypeInfo.cs index ed21b91bf..66d04f39f 100644 --- a/src/ImageSharp/Formats/PixelTypeInfo.cs +++ b/src/ImageSharp/Formats/PixelTypeInfo.cs @@ -1,6 +1,10 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System.Runtime.CompilerServices; + +using SixLabors.ImageSharp.PixelFormats; + namespace SixLabors.ImageSharp.Formats { /// @@ -21,5 +25,9 @@ namespace SixLabors.ImageSharp.Formats /// Gets color depth, in number of bits per pixel. /// public int BitsPerPixel { get; } + + internal static PixelTypeInfo Create() + where TPixel : struct, IPixel => + new PixelTypeInfo(Unsafe.SizeOf() * 8); } } diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index 36944dc2c..17a15a916 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp /// /// Adds static methods allowing the decoding of new images. /// - public static partial class Image + public abstract partial class Image { /// /// Creates an instance backed by an uninitialized memory buffer. diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs index 7ceeea949..24a169f6e 100644 --- a/src/ImageSharp/Image.FromBytes.cs +++ b/src/ImageSharp/Image.FromBytes.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp /// /// Adds static methods allowing the creation of new image from a byte array. /// - public static partial class Image + public abstract partial class Image { /// /// By reading the header on the provided byte array this calculates the images format. diff --git a/src/ImageSharp/Image.FromFile.cs b/src/ImageSharp/Image.FromFile.cs index 80267146d..0b4966886 100644 --- a/src/ImageSharp/Image.FromFile.cs +++ b/src/ImageSharp/Image.FromFile.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp /// /// Adds static methods allowing the creation of new image from a given file. /// - public static partial class Image + public abstract partial class Image { /// /// By reading the header on the provided file this calculates the images mime type. diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index 8848225f5..b16501b0f 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp /// /// Adds static methods allowing the creation of new image from a given stream. /// - public static partial class Image + public abstract partial class Image { /// /// By reading the header on the provided stream this calculates the images mime type. diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs index 282f98086..eb7ce261f 100644 --- a/src/ImageSharp/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image.LoadPixelData.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp /// /// Adds static methods allowing the creation of new image from raw pixel data. /// - public static partial class Image + public abstract partial class Image { /// /// Create a new instance of the class from the raw data. diff --git a/src/ImageSharp/Image.WrapMemory.cs b/src/ImageSharp/Image.WrapMemory.cs index 3d788bb73..49bc99e9e 100644 --- a/src/ImageSharp/Image.WrapMemory.cs +++ b/src/ImageSharp/Image.WrapMemory.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp /// /// Adds static methods allowing wrapping an existing memory area as an image. /// - public static partial class Image + public abstract partial class Image { /// /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index a124ddcac..f780ca666 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -10,7 +10,10 @@ $(packageversion) 0.0.1 - netcoreapp2.1;netstandard1.3;netstandard2.0;net472 + + + netcoreapp2.1 + true true SixLabors.ImageSharp diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index e37f3e4c1..ea6d0beb2 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -128,10 +128,10 @@ namespace SixLabors.ImageSharp public PixelTypeInfo PixelType { get; } /// - public int Width => this.Frames.RootFrame.Width; + public override int Width => this.Frames.RootFrame.Width; /// - public int Height => this.Frames.RootFrame.Height; + public override int Height => this.Frames.RootFrame.Height; /// public ImageMetadata Metadata { get; } @@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp } /// - public void Dispose() => this.Frames.Dispose(); + public override void Dispose() => this.Frames.Dispose(); internal override void AcceptVisitor(IImageVisitor visitor) { From 22fa63122f505f3297d3506b7f28fda63eb669f5 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 00:55:09 +0200 Subject: [PATCH 106/223] refactor the rest of the FilterProcessor code --- .../Processing/BrightnessExtensions.cs | 12 ++-- .../Processing/ColorBlindnessExtensions.cs | 31 ++++------ .../Processing/ContrastExtensions.cs | 14 ++--- .../Processing/GrayscaleExtensions.cs | 62 +++++++------------ src/ImageSharp/Processing/HueExtensions.cs | 14 ++--- src/ImageSharp/Processing/InvertExtensions.cs | 14 ++--- .../Processing/KodachromeExtensions.cs | 14 ++--- .../Processing/LomographExtensions.cs | 14 ++--- .../Processing/PolaroidExtensions.cs | 13 ++-- .../Convolution/EdgeDetector2DProcessor.cs | 2 +- .../EdgeDetectorCompassProcessor.cs | 2 +- .../Convolution/EdgeDetectorProcessor.cs | 2 +- .../Filters/AchromatomalyProcessor.cs | 6 +- .../Filters/AchromatopsiaProcessor.cs | 6 +- .../Processors/Filters/BrightnessProcessor.cs | 6 +- .../Processors/Filters/ContrastProcessor.cs | 6 +- .../Filters/DeuteranomalyProcessor.cs | 6 +- .../Filters/DeuteranopiaProcessor.cs | 6 +- .../Processors/Filters/FilterProcessor.cs | 2 +- .../Filters/FilterProcessorImplementation.cs | 8 +-- .../Filters/GrayscaleBt601Processor.cs | 6 +- .../Filters/GrayscaleBt709Processor.cs | 17 +++-- .../Processors/Filters/HueProcessor.cs | 5 +- .../Processors/Filters/InvertProcessor.cs | 6 +- .../Processors/Filters/KodachromeProcessor.cs | 6 +- .../Processors/Filters/LomographProcessor.cs | 19 ++---- .../LomographProcessorImplementation.cs | 26 ++++++++ .../Processors/Filters/PolaroidProcessor.cs | 22 +++++-- .../Filters/ProtanomalyProcessor.cs | 6 +- .../Processors/Filters/ProtanopiaProcessor.cs | 5 +- .../Processors/Filters/SaturateProcessor.cs | 6 +- .../Processors/Filters/SepiaProcessor.cs | 6 +- .../Filters/TritanomalyProcessor.cs | 6 +- .../Processors/Filters/TritanopiaProcessor.cs | 6 +- .../Processing/Processors/IImageProcessor.cs | 31 +++++++++- .../Processing/SaturateExtensions.cs | 14 ++--- src/ImageSharp/Processing/SepiaExtensions.cs | 22 +++---- 37 files changed, 210 insertions(+), 239 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs diff --git a/src/ImageSharp/Processing/BrightnessExtensions.cs b/src/ImageSharp/Processing/BrightnessExtensions.cs index 2f252ad30..4de4dc897 100644 --- a/src/ImageSharp/Processing/BrightnessExtensions.cs +++ b/src/ImageSharp/Processing/BrightnessExtensions.cs @@ -19,13 +19,11 @@ namespace SixLabors.ImageSharp.Processing /// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing brighter results. /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be greater than or equal to 0. /// The . - public static IImageProcessingContext Brightness(this IImageProcessingContext source, float amount) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BrightnessProcessor(amount)); + public static IImageProcessingContext Brightness(this IImageProcessingContext source, float amount) + => source.ApplyProcessor(new BrightnessProcessor(amount)); /// /// Alters the brightness component of the image. @@ -34,15 +32,13 @@ namespace SixLabors.ImageSharp.Processing /// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing brighter results. /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be greater than or equal to 0. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Brightness(this IImageProcessingContext source, float amount, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BrightnessProcessor(amount), rectangle); + public static IImageProcessingContext Brightness(this IImageProcessingContext source, float amount, Rectangle rectangle) + => source.ApplyProcessor(new BrightnessProcessor(amount), rectangle); } } diff --git a/src/ImageSharp/Processing/ColorBlindnessExtensions.cs b/src/ImageSharp/Processing/ColorBlindnessExtensions.cs index 331635895..000d47bd3 100644 --- a/src/ImageSharp/Processing/ColorBlindnessExtensions.cs +++ b/src/ImageSharp/Processing/ColorBlindnessExtensions.cs @@ -16,49 +16,44 @@ namespace SixLabors.ImageSharp.Processing /// /// Applies the given colorblindness simulator to the image. /// - /// The pixel format. /// The image this method extends. /// The type of color blindness simulator to apply. /// The . - public static IImageProcessingContext ColorBlindness(this IImageProcessingContext source, ColorBlindnessMode colorBlindness) - where TPixel : struct, IPixel - => source.ApplyProcessor(GetProcessor(colorBlindness)); + public static IImageProcessingContext ColorBlindness(this IImageProcessingContext source, ColorBlindnessMode colorBlindness) + => source.ApplyProcessor(GetProcessor(colorBlindness)); /// /// Applies the given colorblindness simulator to the image. /// - /// The pixel format. /// The image this method extends. /// The type of color blindness simulator to apply. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext ColorBlindness(this IImageProcessingContext source, ColorBlindnessMode colorBlindnessMode, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(GetProcessor(colorBlindnessMode), rectangle); + public static IImageProcessingContext ColorBlindness(this IImageProcessingContext source, ColorBlindnessMode colorBlindnessMode, Rectangle rectangle) + => source.ApplyProcessor(GetProcessor(colorBlindnessMode), rectangle); - private static IImageProcessor GetProcessor(ColorBlindnessMode colorBlindness) - where TPixel : struct, IPixel + private static IImageProcessor GetProcessor(ColorBlindnessMode colorBlindness) { switch (colorBlindness) { case ColorBlindnessMode.Achromatomaly: - return new AchromatomalyProcessor(); + return new AchromatomalyProcessor(); case ColorBlindnessMode.Achromatopsia: - return new AchromatopsiaProcessor(); + return new AchromatopsiaProcessor(); case ColorBlindnessMode.Deuteranomaly: - return new DeuteranomalyProcessor(); + return new DeuteranomalyProcessor(); case ColorBlindnessMode.Deuteranopia: - return new DeuteranopiaProcessor(); + return new DeuteranopiaProcessor(); case ColorBlindnessMode.Protanomaly: - return new ProtanomalyProcessor(); + return new ProtanomalyProcessor(); case ColorBlindnessMode.Protanopia: - return new ProtanopiaProcessor(); + return new ProtanopiaProcessor(); case ColorBlindnessMode.Tritanomaly: - return new TritanomalyProcessor(); + return new TritanomalyProcessor(); default: - return new TritanopiaProcessor(); + return new TritanopiaProcessor(); } } } diff --git a/src/ImageSharp/Processing/ContrastExtensions.cs b/src/ImageSharp/Processing/ContrastExtensions.cs index 776aa6751..b03844d93 100644 --- a/src/ImageSharp/Processing/ContrastExtensions.cs +++ b/src/ImageSharp/Processing/ContrastExtensions.cs @@ -8,7 +8,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the alteration of the contrast component to the type. + /// Adds extensions that allow the alteration of the contrast component to the type. /// public static class ContrastExtensions { @@ -19,13 +19,11 @@ namespace SixLabors.ImageSharp.Processing /// A value of 0 will create an image that is completely gray. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing results with more contrast. /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be greater than or equal to 0. /// The . - public static IImageProcessingContext Contrast(this IImageProcessingContext source, float amount) - where TPixel : struct, IPixel - => source.ApplyProcessor(new ContrastProcessor(amount)); + public static IImageProcessingContext Contrast(this IImageProcessingContext source, float amount) + => source.ApplyProcessor(new ContrastProcessor(amount)); /// /// Alters the contrast component of the image. @@ -34,15 +32,13 @@ namespace SixLabors.ImageSharp.Processing /// A value of 0 will create an image that is completely gray. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing results with more contrast. /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be greater than or equal to 0. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Contrast(this IImageProcessingContext source, float amount, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new ContrastProcessor(amount), rectangle); + public static IImageProcessingContext Contrast(this IImageProcessingContext source, float amount, Rectangle rectangle) + => source.ApplyProcessor(new ContrastProcessor(amount), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/GrayscaleExtensions.cs b/src/ImageSharp/Processing/GrayscaleExtensions.cs index 9ab664056..d68a385e4 100644 --- a/src/ImageSharp/Processing/GrayscaleExtensions.cs +++ b/src/ImageSharp/Processing/GrayscaleExtensions.cs @@ -9,56 +9,48 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of grayscale toning to the type. + /// Adds extensions that allow the application of grayscale toning to the type. /// public static class GrayscaleExtensions { /// /// Applies grayscale toning to the image. /// - /// The pixel format. /// The image this method extends. - /// The . - public static IImageProcessingContext Grayscale(this IImageProcessingContext source) - where TPixel : struct, IPixel + /// The . + public static IImageProcessingContext Grayscale(this IImageProcessingContext source) => Grayscale(source, GrayscaleMode.Bt709); /// /// Applies grayscale toning to the image using the given amount. /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be between 0 and 1. - /// The . - public static IImageProcessingContext Grayscale(this IImageProcessingContext source, float amount) - where TPixel : struct, IPixel + /// The . + public static IImageProcessingContext Grayscale(this IImageProcessingContext source, float amount) => Grayscale(source, GrayscaleMode.Bt709, amount); /// /// Applies grayscale toning to the image with the given . /// - /// The pixel format. /// The image this method extends. /// The formula to apply to perform the operation. - /// The . - public static IImageProcessingContext Grayscale(this IImageProcessingContext source, GrayscaleMode mode) - where TPixel : struct, IPixel + /// The . + public static IImageProcessingContext Grayscale(this IImageProcessingContext source, GrayscaleMode mode) => Grayscale(source, mode, 1F); /// /// Applies grayscale toning to the image with the given using the given amount. /// - /// The pixel format. /// The image this method extends. /// The formula to apply to perform the operation. /// The proportion of the conversion. Must be between 0 and 1. - /// The . - public static IImageProcessingContext Grayscale(this IImageProcessingContext source, GrayscaleMode mode, float amount) - where TPixel : struct, IPixel + /// The . + public static IImageProcessingContext Grayscale(this IImageProcessingContext source, GrayscaleMode mode, float amount) { - IImageProcessor processor = mode == GrayscaleMode.Bt709 - ? (IImageProcessor)new GrayscaleBt709Processor(amount) - : new GrayscaleBt601Processor(1F); + IImageProcessor processor = mode == GrayscaleMode.Bt709 + ? (IImageProcessor)new GrayscaleBt709Processor(amount) + : new GrayscaleBt601Processor(1F); source.ApplyProcessor(processor); return source; @@ -67,61 +59,53 @@ namespace SixLabors.ImageSharp.Processing /// /// Applies grayscale toning to the image. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// - /// The . - public static IImageProcessingContext Grayscale(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel + /// The . + public static IImageProcessingContext Grayscale(this IImageProcessingContext source, Rectangle rectangle) => Grayscale(source, 1F, rectangle); /// /// Applies grayscale toning to the image using the given amount. /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be between 0 and 1. /// /// The structure that specifies the portion of the image object to alter. /// - /// The . - public static IImageProcessingContext Grayscale(this IImageProcessingContext source, float amount, Rectangle rectangle) - where TPixel : struct, IPixel + /// The . + public static IImageProcessingContext Grayscale(this IImageProcessingContext source, float amount, Rectangle rectangle) => Grayscale(source, GrayscaleMode.Bt709, amount, rectangle); /// /// Applies grayscale toning to the image. /// - /// The pixel format. /// The image this method extends. /// The formula to apply to perform the operation. /// /// The structure that specifies the portion of the image object to alter. /// - /// The . - public static IImageProcessingContext Grayscale(this IImageProcessingContext source, GrayscaleMode mode, Rectangle rectangle) - where TPixel : struct, IPixel + /// The . + public static IImageProcessingContext Grayscale(this IImageProcessingContext source, GrayscaleMode mode, Rectangle rectangle) => Grayscale(source, mode, 1F, rectangle); /// /// Applies grayscale toning to the image using the given amount. /// - /// The pixel format. /// The image this method extends. /// The formula to apply to perform the operation. /// The proportion of the conversion. Must be between 0 and 1. /// /// The structure that specifies the portion of the image object to alter. /// - /// The . - public static IImageProcessingContext Grayscale(this IImageProcessingContext source, GrayscaleMode mode, float amount, Rectangle rectangle) - where TPixel : struct, IPixel + /// The . + public static IImageProcessingContext Grayscale(this IImageProcessingContext source, GrayscaleMode mode, float amount, Rectangle rectangle) { - IImageProcessor processor = mode == GrayscaleMode.Bt709 - ? (IImageProcessor)new GrayscaleBt709Processor(amount) - : new GrayscaleBt601Processor(amount); + IImageProcessor processor = mode == GrayscaleMode.Bt709 + ? (IImageProcessor)new GrayscaleBt709Processor(amount) + : new GrayscaleBt601Processor(amount); source.ApplyProcessor(processor, rectangle); return source; diff --git a/src/ImageSharp/Processing/HueExtensions.cs b/src/ImageSharp/Processing/HueExtensions.cs index 246d4bf2b..17296e1db 100644 --- a/src/ImageSharp/Processing/HueExtensions.cs +++ b/src/ImageSharp/Processing/HueExtensions.cs @@ -8,33 +8,29 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the alteration of the hue component to the type. + /// Adds extensions that allow the alteration of the hue component to the type. /// public static class HueExtensions { /// /// Alters the hue component of the image. /// - /// The pixel format. /// The image this method extends. /// The rotation angle in degrees to adjust the hue. /// The . - public static IImageProcessingContext Hue(this IImageProcessingContext source, float degrees) - where TPixel : struct, IPixel - => source.ApplyProcessor(new HueProcessor(degrees)); + public static IImageProcessingContext Hue(this IImageProcessingContext source, float degrees) + => source.ApplyProcessor(new HueProcessor(degrees)); /// /// Alters the hue component of the image. /// - /// The pixel format. /// The image this method extends. /// The rotation angle in degrees to adjust the hue. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Hue(this IImageProcessingContext source, float degrees, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new HueProcessor(degrees), rectangle); + public static IImageProcessingContext Hue(this IImageProcessingContext source, float degrees, Rectangle rectangle) + => source.ApplyProcessor(new HueProcessor(degrees), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/InvertExtensions.cs b/src/ImageSharp/Processing/InvertExtensions.cs index 9e031bc95..828aaa1bb 100644 --- a/src/ImageSharp/Processing/InvertExtensions.cs +++ b/src/ImageSharp/Processing/InvertExtensions.cs @@ -8,31 +8,27 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the inversion of colors to the type. + /// Adds extensions that allow the inversion of colors to the type. /// public static class InvertExtensions { /// /// Inverts the colors of the image. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext Invert(this IImageProcessingContext source) - where TPixel : struct, IPixel - => source.ApplyProcessor(new InvertProcessor(1F)); + public static IImageProcessingContext Invert(this IImageProcessingContext source) + => source.ApplyProcessor(new InvertProcessor(1F)); /// /// Inverts the colors of the image. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Invert(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new InvertProcessor(1F), rectangle); + public static IImageProcessingContext Invert(this IImageProcessingContext source, Rectangle rectangle) + => source.ApplyProcessor(new InvertProcessor(1F), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/KodachromeExtensions.cs b/src/ImageSharp/Processing/KodachromeExtensions.cs index e438b131e..24bd51e01 100644 --- a/src/ImageSharp/Processing/KodachromeExtensions.cs +++ b/src/ImageSharp/Processing/KodachromeExtensions.cs @@ -8,31 +8,27 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the recreation of an old Kodachrome camera effect to the type. + /// Adds extensions that allow the recreation of an old Kodachrome camera effect to the type. /// public static class KodachromeExtensions { /// /// Alters the colors of the image recreating an old Kodachrome camera effect. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext Kodachrome(this IImageProcessingContext source) - where TPixel : struct, IPixel - => source.ApplyProcessor(new KodachromeProcessor()); + public static IImageProcessingContext Kodachrome(this IImageProcessingContext source) + => source.ApplyProcessor(new KodachromeProcessor()); /// /// Alters the colors of the image recreating an old Kodachrome camera effect. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Kodachrome(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new KodachromeProcessor(), rectangle); + public static IImageProcessingContext Kodachrome(this IImageProcessingContext source, Rectangle rectangle) + => source.ApplyProcessor(new KodachromeProcessor(), rectangle); } } diff --git a/src/ImageSharp/Processing/LomographExtensions.cs b/src/ImageSharp/Processing/LomographExtensions.cs index 7dff16402..a3fd3d3b5 100644 --- a/src/ImageSharp/Processing/LomographExtensions.cs +++ b/src/ImageSharp/Processing/LomographExtensions.cs @@ -8,31 +8,27 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the recreation of an old Lomograph camera effect to the type. + /// Adds extensions that allow the recreation of an old Lomograph camera effect to the type. /// public static class LomographExtensions { /// /// Alters the colors of the image recreating an old Lomograph camera effect. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext Lomograph(this IImageProcessingContext source) - where TPixel : struct, IPixel - => source.ApplyProcessor(new LomographProcessor()); + public static IImageProcessingContext Lomograph(this IImageProcessingContext source) + => source.ApplyProcessor(new LomographProcessor()); /// /// Alters the colors of the image recreating an old Lomograph camera effect. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Lomograph(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new LomographProcessor(), rectangle); + public static IImageProcessingContext Lomograph(this IImageProcessingContext source, Rectangle rectangle) + => source.ApplyProcessor(new LomographProcessor(), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/PolaroidExtensions.cs b/src/ImageSharp/Processing/PolaroidExtensions.cs index 5d4beee22..4172c1d61 100644 --- a/src/ImageSharp/Processing/PolaroidExtensions.cs +++ b/src/ImageSharp/Processing/PolaroidExtensions.cs @@ -8,19 +8,17 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the recreation of an old Polaroid camera effect to the type. + /// Adds extensions that allow the recreation of an old Polaroid camera effect to the type. /// public static class PolaroidExtensions { /// /// Alters the colors of the image recreating an old Polaroid camera effect. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext Polaroid(this IImageProcessingContext source) - where TPixel : struct, IPixel - => source.ApplyProcessor(new PolaroidProcessor()); + public static IImageProcessingContext Polaroid(this IImageProcessingContext source) + => source.ApplyProcessor(new PolaroidProcessor()); /// /// Alters the colors of the image recreating an old Polaroid camera effect. @@ -31,8 +29,7 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Polaroid(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new PolaroidProcessor(), rectangle); + public static IImageProcessingContext Polaroid(this IImageProcessingContext source, Rectangle rectangle) + => source.ApplyProcessor(new PolaroidProcessor(), rectangle); } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs index d2e9630dc..c08a17661 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs @@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { if (this.Grayscale) { - new GrayscaleBt709Processor(1F).Apply(source, sourceRectangle, configuration); + new GrayscaleBt709Processor(1F).ApplyToFrame(source, sourceRectangle, configuration); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs index 73f92fae3..aa33699f5 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { if (this.Grayscale) { - new GrayscaleBt709Processor(1F).Apply(source, sourceRectangle, configuration); + new GrayscaleBt709Processor(1F).ApplyToFrame(source, sourceRectangle, configuration); } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs index edc7ec4cc..9ec79da9e 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { if (this.Grayscale) { - new GrayscaleBt709Processor(1F).Apply(source, sourceRectangle, configuration); + new GrayscaleBt709Processor(1F).ApplyToFrame(source, sourceRectangle, configuration); } } diff --git a/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs index 57c1bad39..2dac6b827 100644 --- a/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness. /// - /// The pixel format. - internal class AchromatomalyProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class AchromatomalyProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public AchromatomalyProcessor() : base(KnownFilterMatrices.AchromatomalyFilter) diff --git a/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs index 696a854ab..4df94a760 100644 --- a/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness. /// - /// The pixel format. - internal class AchromatopsiaProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class AchromatopsiaProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public AchromatopsiaProcessor() : base(KnownFilterMatrices.AchromatopsiaFilter) diff --git a/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs index b1b8ad747..6a1f3869a 100644 --- a/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a brightness filter matrix using the given amount. /// - /// The pixel format. - internal class BrightnessProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class BrightnessProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged. diff --git a/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs index ebec464d5..3bea695b9 100644 --- a/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a contrast filter matrix using the given amount. /// - /// The pixel format. - internal class ContrastProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class ContrastProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// A value of 0 will create an image that is completely gray. A value of 1 leaves the input unchanged. diff --git a/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs index 0d1b1da90..395489d56 100644 --- a/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Deuteranomaly (Green-Weak) color blindness. /// - /// The pixel format. - internal class DeuteranomalyProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class DeuteranomalyProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public DeuteranomalyProcessor() : base(KnownFilterMatrices.DeuteranomalyFilter) diff --git a/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs index ae0727048..51f8361e6 100644 --- a/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Deuteranopia (Green-Blind) color blindness. /// - /// The pixel format. - internal class DeuteranopiaProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class DeuteranopiaProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public DeuteranopiaProcessor() : base(KnownFilterMatrices.DeuteranopiaFilter) diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs index 3f9f58687..5637e9770 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// public ColorMatrix Matrix { get; } - public IImageProcessor CreatePixelSpecificProcessor() + public virtual IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel { return new FilterProcessorImplementation(this); diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs index 1eaaf1ea5..8fea81564 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs @@ -18,11 +18,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters internal class FilterProcessorImplementation : ImageProcessor where TPixel : struct, IPixel { - private readonly FilterProcessor paramterSource; + private readonly FilterProcessor definition; - public FilterProcessorImplementation(FilterProcessor paramterSource) + public FilterProcessorImplementation(FilterProcessor definition) { - this.paramterSource = paramterSource; + this.definition = definition; } /// @@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); int startX = interest.X; - ColorMatrix matrix = this.paramterSource.Matrix; + ColorMatrix matrix = this.definition.Matrix; ParallelHelper.IterateRowsWithTempBuffer( interest, diff --git a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs index c933d4858..b39e01b9a 100644 --- a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a grayscale filter matrix using the given amount and the formula as specified by ITU-R Recommendation BT.601 /// - /// The pixel format. - internal class GrayscaleBt601Processor : FilterProcessor - where TPixel : struct, IPixel + internal class GrayscaleBt601Processor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The proportion of the conversion. Must be between 0 and 1. public GrayscaleBt601Processor(float amount) diff --git a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs index 1716773b4..038a2885b 100644 --- a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs @@ -2,18 +2,17 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Applies a grayscale filter matrix using the given amount and the formula as specified by ITU-R Recommendation BT.709 /// - /// The pixel format. - internal class GrayscaleBt709Processor : FilterProcessor - where TPixel : struct, IPixel + internal class GrayscaleBt709Processor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The proportion of the conversion. Must be between 0 and 1. public GrayscaleBt709Processor(float amount) @@ -23,8 +22,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters } /// - /// Gets the proportion of the conversion + /// Gets the proportion of the conversion. /// public float Amount { get; } + + // TODO: Move this to an appropriate extension method if possible. + internal void ApplyToFrame(ImageFrame frame, Rectangle sourceRectangle, Configuration configuration) + where TPixel : struct, IPixel + { + var processorImpl = new FilterProcessorImplementation(new GrayscaleBt709Processor(1F)); + processorImpl.Apply(frame, sourceRectangle, configuration); + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs index 4c3a0c73e..a69fd5075 100644 --- a/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs @@ -8,11 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a hue filter matrix using the given angle of rotation in degrees /// - internal class HueProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class HueProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The angle of rotation in degrees public HueProcessor(float degrees) diff --git a/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs index 462c42070..d7631970d 100644 --- a/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a filter matrix that inverts the colors of an image /// - /// The pixel format. - internal class InvertProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class InvertProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The proportion of the conversion. Must be between 0 and 1. public InvertProcessor(float amount) diff --git a/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs index 003766e8a..5570f23d7 100644 --- a/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a filter matrix recreating an old Kodachrome camera effect matrix to the image /// - /// The pixel format. - internal class KodachromeProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class KodachromeProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public KodachromeProcessor() : base(KnownFilterMatrices.KodachromeFilter) diff --git a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs index 737ebf618..345d829ac 100644 --- a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs @@ -1,33 +1,22 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors.Overlays; -using SixLabors.Primitives; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Converts the colors of the image recreating an old Lomograph effect. /// - /// The pixel format. - internal class LomographProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class LomographProcessor : FilterProcessor { - private static readonly TPixel VeryDarkGreen = ColorBuilder.FromRGBA(0, 10, 0, 255); - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public LomographProcessor() : base(KnownFilterMatrices.LomographFilter) { } - /// - protected override void AfterFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - new VignetteProcessor(VeryDarkGreen).Apply(source, sourceRectangle, configuration); - } + public override IImageProcessor CreatePixelSpecificProcessor() => + new LomographProcessorImplementation(this); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs new file mode 100644 index 000000000..d851b98e0 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs @@ -0,0 +1,26 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Overlays; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Filters +{ + internal class LomographProcessorImplementation : FilterProcessorImplementation + where TPixel : struct, IPixel + { + private static readonly TPixel VeryDarkGreen = ColorBuilder.FromRGBA(0, 10, 0, 255); + + /// + protected override void AfterFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + new VignetteProcessor(VeryDarkGreen).Apply(source, sourceRectangle, configuration); + } + + public LomographProcessorImplementation(FilterProcessor definition) + : base(definition) + { + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs index fb065ac17..af16d9eab 100644 --- a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs @@ -10,13 +10,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating an old Polaroid effect. /// - /// The pixel format. - internal class PolaroidProcessor : FilterProcessor - where TPixel : struct, IPixel + public class PolaroidProcessor : FilterProcessor { - private static readonly TPixel VeryDarkOrange = ColorBuilder.FromRGB(102, 34, 0); - private static readonly TPixel LightOrange = ColorBuilder.FromRGBA(255, 153, 102, 128); - /// /// Initializes a new instance of the class. /// @@ -25,11 +20,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters { } + public override IImageProcessor CreatePixelSpecificProcessor() => + new PolaroidProcessorImplementation(this); + } + + internal class PolaroidProcessorImplementation : FilterProcessorImplementation + where TPixel : struct, IPixel + { + private static readonly TPixel VeryDarkOrange = ColorBuilder.FromRGB(102, 34, 0); + private static readonly TPixel LightOrange = ColorBuilder.FromRGBA(255, 153, 102, 128); + /// protected override void AfterFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { new VignetteProcessor(VeryDarkOrange).Apply(source, sourceRectangle, configuration); new GlowProcessor(LightOrange, source.Width / 4F).Apply(source, sourceRectangle, configuration); } + + public PolaroidProcessorImplementation(FilterProcessor definition) + : base(definition) + { + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs index 79eb70851..95e369b37 100644 --- a/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Protanomaly (Red-Weak) color blindness. /// - /// The pixel format. - internal class ProtanomalyProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class ProtanomalyProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public ProtanomalyProcessor() : base(KnownFilterMatrices.ProtanomalyFilter) diff --git a/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs index c6a01439a..94eeaae47 100644 --- a/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs @@ -9,11 +9,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// Converts the colors of the image recreating Protanopia (Red-Blind) color blindness. /// /// The pixel format. - internal class ProtanopiaProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class ProtanopiaProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public ProtanopiaProcessor() : base(KnownFilterMatrices.ProtanopiaFilter) diff --git a/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs index 75e956071..424eeb461 100644 --- a/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a saturation filter matrix using the given amount. /// - /// The pixel format. - internal class SaturateProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class SaturateProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// A value of 0 is completely un-saturated. A value of 1 leaves the input unchanged. diff --git a/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs index 2009dccd5..538db4b52 100644 --- a/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a sepia filter matrix using the given amount. /// - /// The pixel format. - internal class SepiaProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class SepiaProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The proportion of the conversion. Must be between 0 and 1. public SepiaProcessor(float amount) diff --git a/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs index 593f7f5b0..3eda05a11 100644 --- a/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Tritanomaly (Blue-Weak) color blindness. /// - /// The pixel format. - internal class TritanomalyProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class TritanomalyProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public TritanomalyProcessor() : base(KnownFilterMatrices.TritanomalyFilter) diff --git a/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs index 153ad5559..f5ed26c83 100644 --- a/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs @@ -8,12 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Tritanopia (Blue-Blind) color blindness. /// - /// The pixel format. - internal class TritanopiaProcessor : FilterProcessor - where TPixel : struct, IPixel + internal class TritanopiaProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public TritanopiaProcessor() : base(KnownFilterMatrices.TritanopiaFilter) diff --git a/src/ImageSharp/Processing/Processors/IImageProcessor.cs b/src/ImageSharp/Processing/Processors/IImageProcessor.cs index 78800affb..68db45380 100644 --- a/src/ImageSharp/Processing/Processors/IImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/IImageProcessor.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Processing.Processors IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel; } - + /// /// Encapsulates methods to alter the pixels of an image. /// @@ -34,4 +34,33 @@ namespace SixLabors.ImageSharp.Processing.Processors /// void Apply(Image source, Rectangle sourceRectangle); } + + internal static class ImageProcessorExtensions + { + public static void Apply(this IImageProcessor processor, Image source, Rectangle sourceRectangle) + { + var visitor = new ApplyVisitor(processor, sourceRectangle); + source.AcceptVisitor(visitor); + } + + private class ApplyVisitor : IImageVisitor + { + private readonly IImageProcessor processor; + + private readonly Rectangle sourceRectangle; + + public ApplyVisitor(IImageProcessor processor, Rectangle sourceRectangle) + { + this.processor = processor; + this.sourceRectangle = sourceRectangle; + } + + public void Visit(Image image) + where TPixel : struct, IPixel + { + var processorImpl = processor.CreatePixelSpecificProcessor(); + processorImpl.Apply(image, this.sourceRectangle); + } + } + } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/SaturateExtensions.cs b/src/ImageSharp/Processing/SaturateExtensions.cs index ba45ae12c..fe2cf5f34 100644 --- a/src/ImageSharp/Processing/SaturateExtensions.cs +++ b/src/ImageSharp/Processing/SaturateExtensions.cs @@ -8,7 +8,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the alteration of the saturation component to the type. + /// Adds extensions that allow the alteration of the saturation component to the type. /// public static class SaturateExtensions { @@ -19,13 +19,11 @@ namespace SixLabors.ImageSharp.Processing /// A value of 0 is completely un-saturated. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of amount over 1 are allowed, providing super-saturated results /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be greater than or equal to 0. /// The . - public static IImageProcessingContext Saturate(this IImageProcessingContext source, float amount) - where TPixel : struct, IPixel - => source.ApplyProcessor(new SaturateProcessor(amount)); + public static IImageProcessingContext Saturate(this IImageProcessingContext source, float amount) + => source.ApplyProcessor(new SaturateProcessor(amount)); /// /// Alters the saturation component of the image. @@ -34,15 +32,13 @@ namespace SixLabors.ImageSharp.Processing /// A value of 0 is completely un-saturated. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of amount over 1 are allowed, providing super-saturated results /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be greater than or equal to 0. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Saturate(this IImageProcessingContext source, float amount, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new SaturateProcessor(amount), rectangle); + public static IImageProcessingContext Saturate(this IImageProcessingContext source, float amount, Rectangle rectangle) + => source.ApplyProcessor(new SaturateProcessor(amount), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/SepiaExtensions.cs b/src/ImageSharp/Processing/SepiaExtensions.cs index 08676ee62..5b23ec11a 100644 --- a/src/ImageSharp/Processing/SepiaExtensions.cs +++ b/src/ImageSharp/Processing/SepiaExtensions.cs @@ -8,56 +8,48 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of sepia toning to the type. + /// Adds extensions that allow the application of sepia toning to the type. /// public static class SepiaExtensions { /// /// Applies sepia toning to the image. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext Sepia(this IImageProcessingContext source) - where TPixel : struct, IPixel + public static IImageProcessingContext Sepia(this IImageProcessingContext source) => Sepia(source, 1F); /// /// Applies sepia toning to the image using the given amount. /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be between 0 and 1. /// The . - public static IImageProcessingContext Sepia(this IImageProcessingContext source, float amount) - where TPixel : struct, IPixel - => source.ApplyProcessor(new SepiaProcessor(amount)); + public static IImageProcessingContext Sepia(this IImageProcessingContext source, float amount) + => source.ApplyProcessor(new SepiaProcessor(amount)); /// /// Applies sepia toning to the image. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Sepia(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel + public static IImageProcessingContext Sepia(this IImageProcessingContext source, Rectangle rectangle) => Sepia(source, 1F, rectangle); /// /// Applies sepia toning to the image. /// - /// The pixel format. /// The image this method extends. /// The proportion of the conversion. Must be between 0 and 1. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Sepia(this IImageProcessingContext source, float amount, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new SepiaProcessor(amount), rectangle); + public static IImageProcessingContext Sepia(this IImageProcessingContext source, float amount, Rectangle rectangle) + => source.ApplyProcessor(new SepiaProcessor(amount), rectangle); } } \ No newline at end of file From 5091ac5e79f179c2e5260d257c37340e6d0b5d8b Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 01:08:48 +0200 Subject: [PATCH 107/223] reached a fully compiling state --- .../ImageSharp.Drawing.csproj | 4 +- .../Formats/Gif/GifEncoderTests.cs | 6 +-- .../Formats/Jpg/JpegDecoderTests.cs | 4 +- .../ImageSharp.Tests/ImageSharp.Tests.csproj | 3 +- .../Processing/Filters/BlackWhiteTest.cs | 27 ----------- .../Processing/Filters/BrightnessTest.cs | 31 ------------ .../Processing/Filters/ColorBlindnessTest.cs | 46 ------------------ .../Processing/Filters/ContrastTest.cs | 33 ------------- .../Processing/Filters/FilterTest.cs | 4 +- .../Processing/Filters/GrayscaleTest.cs | 47 ------------------- .../Processing/Filters/HueTest.cs | 32 ------------- .../Processing/Filters/InvertTest.cs | 27 ----------- .../Processing/Filters/KodachromeTest.cs | 27 ----------- .../Processing/Filters/LomographTest.cs | 31 ------------ .../Processing/Filters/OpacityTest.cs | 31 ------------ .../Processing/Filters/PolaroidTest.cs | 28 ----------- .../Processing/Filters/SaturateTest.cs | 31 ------------ .../Processing/Filters/SepiaTest.cs | 27 ----------- .../Processing/Transforms/PadTest.cs | 2 +- .../Processing/Transforms/ResizeTests.cs | 8 ++-- 20 files changed, 17 insertions(+), 432 deletions(-) delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/BlackWhiteTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/ColorBlindnessTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/ContrastTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/GrayscaleTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/HueTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/InvertTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/KodachromeTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/LomographTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/OpacityTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/PolaroidTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/SaturateTest.cs delete mode 100644 tests/ImageSharp.Tests/Processing/Filters/SepiaTest.cs diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 6f5cabb09..1734c48de 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -10,7 +10,9 @@ $(packageversion) 0.0.1 - netcoreapp2.1;netstandard1.3;netstandard2.0 + + netcoreapp2.1 + 7.3 true true diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index cac4030d5..5da1c3bb7 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif // Compare encoded result string path = provider.Utility.GetTestOutputFileName("gif", null, true); - using (var encoded = Image.Load(path)) + using (var encoded = Image.Load(path)) { encoded.CompareToReferenceOutput(ValidatorComparer, provider, null, "gif"); } @@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif { inStream.Position = 0; - var image = Image.Load(inStream); + var image = Image.Load(inStream); GifMetadata metaData = image.Metadata.GetFormatMetadata(GifFormat.Instance); GifFrameMetadata frameMetaData = image.Frames.RootFrame.Metadata.GetFormatMetadata(GifFormat.Instance); GifColorTableMode colorMode = metaData.ColorTableMode; @@ -194,7 +194,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif outStream.Position = 0; outStream.Position = 0; - var clone = Image.Load(outStream); + var clone = Image.Load(outStream); GifMetadata cloneMetaData = clone.Metadata.GetFormatMetadata(GifFormat.Instance); Assert.Equal(metaData.ColorTableMode, cloneMetaData.ColorTableMode); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index 15f7f92a8..e316fe67e 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -147,8 +147,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var comparer = ImageComparer.Tolerant(0, 0); using (Image expectedImage = provider.GetReferenceOutputImage(appendPixelTypeToFileName: false)) - using (var pdfJsOriginalResult = Image.Load(pdfJsOriginalResultPath)) - using (var pdfJsPortResult = Image.Load(sourceBytes, JpegDecoder)) + using (var pdfJsOriginalResult = Image.Load(pdfJsOriginalResultPath)) + using (var pdfJsPortResult = Image.Load(sourceBytes, JpegDecoder)) { ImageSimilarityReport originalReport = comparer.CompareImagesOrFrames(expectedImage, pdfJsOriginalResult); ImageSimilarityReport portReport = comparer.CompareImagesOrFrames(expectedImage, pdfJsPortResult); diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 0b727f30c..efdf89964 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,6 +1,7 @@  - netcoreapp2.1;net462;net472 + + netcoreapp2.1 True latest full diff --git a/tests/ImageSharp.Tests/Processing/Filters/BlackWhiteTest.cs b/tests/ImageSharp.Tests/Processing/Filters/BlackWhiteTest.cs deleted file mode 100644 index d651f2f04..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/BlackWhiteTest.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Filters -{ - public class BlackWhiteTest : BaseImageOperationsExtensionTest - { - [Fact] - public void BlackWhite_CorrectProcessor() - { - this.operations.BlackWhite(); - BlackWhiteProcessor p = this.Verify>(); - } - - [Fact] - public void BlackWhite_rect_CorrectProcessor() - { - this.operations.BlackWhite(this.rect); - BlackWhiteProcessor p = this.Verify>(this.rect); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs b/tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs deleted file mode 100644 index e210450a8..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Effects -{ - public class BrightnessTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Brightness_amount_BrightnessProcessorDefaultsSet() - { - this.operations.Brightness(1.5F); - BrightnessProcessor processor = this.Verify>(); - - Assert.Equal(1.5F, processor.Amount); - } - - [Fact] - public void Brightness_amount_rect_BrightnessProcessorDefaultsSet() - { - this.operations.Brightness(1.5F, this.rect); - BrightnessProcessor processor = this.Verify>(this.rect); - - Assert.Equal(1.5F, processor.Amount); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processing/Filters/ColorBlindnessTest.cs deleted file mode 100644 index aeafe5fe1..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/ColorBlindnessTest.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Collections.Generic; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; -using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.ImageSharp.Tests.TestUtilities; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Filters -{ - public class ColorBlindnessTest : BaseImageOperationsExtensionTest - { - public static IEnumerable TheoryData = new[] { - new object[]{ new TestType>(), ColorBlindnessMode.Achromatomaly }, - new object[]{ new TestType>(), ColorBlindnessMode.Achromatopsia }, - new object[]{ new TestType>(), ColorBlindnessMode.Deuteranomaly }, - new object[]{ new TestType>(), ColorBlindnessMode.Deuteranopia }, - new object[]{ new TestType>(), ColorBlindnessMode.Protanomaly }, - new object[]{ new TestType>(), ColorBlindnessMode.Protanopia }, - new object[]{ new TestType>(), ColorBlindnessMode.Tritanomaly }, - new object[]{ new TestType>(), ColorBlindnessMode.Tritanopia } - }; - - [Theory] - [MemberData(nameof(TheoryData))] - public void ColorBlindness_CorrectProcessor(TestType testType, ColorBlindnessMode colorBlindness) - where T : IImageProcessor - { - this.operations.ColorBlindness(colorBlindness); - T p = this.Verify(); - } - [Theory] - [MemberData(nameof(TheoryData))] - public void ColorBlindness_rect_CorrectProcessor(TestType testType, ColorBlindnessMode colorBlindness) - where T : IImageProcessor - { - this.operations.ColorBlindness(colorBlindness, this.rect); - T p = this.Verify(this.rect); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/ContrastTest.cs b/tests/ImageSharp.Tests/Processing/Filters/ContrastTest.cs deleted file mode 100644 index 21a552e6a..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/ContrastTest.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Effects -{ - using SixLabors.ImageSharp.Processing; - using SixLabors.ImageSharp.Processing.Processors.Filters; - - public class ContrastTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Contrast_amount_ContrastProcessorDefaultsSet() - { - this.operations.Contrast(1.5F); - ContrastProcessor processor = this.Verify>(); - - Assert.Equal(1.5F, processor.Amount); - } - - [Fact] - public void Contrast_amount_rect_ContrastProcessorDefaultsSet() - { - this.operations.Contrast(1.5F, this.rect); - ContrastProcessor processor = this.Verify>(this.rect); - - Assert.Equal(1.5F, processor.Amount); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/FilterTest.cs b/tests/ImageSharp.Tests/Processing/Filters/FilterTest.cs index 414a0d74e..f4efb1274 100644 --- a/tests/ImageSharp.Tests/Processing/Filters/FilterTest.cs +++ b/tests/ImageSharp.Tests/Processing/Filters/FilterTest.cs @@ -17,14 +17,14 @@ namespace SixLabors.ImageSharp.Tests.Processing.Filters public void Filter_CorrectProcessor() { this.operations.Filter(KnownFilterMatrices.AchromatomalyFilter * KnownFilterMatrices.CreateHueFilter(90F)); - FilterProcessor p = this.Verify>(); + FilterProcessorImplementation p = this.Verify>(); } [Fact] public void Filter_rect_CorrectProcessor() { this.operations.Filter(KnownFilterMatrices.AchromatomalyFilter * KnownFilterMatrices.CreateHueFilter(90F), this.rect); - FilterProcessor p = this.Verify>(this.rect); + FilterProcessorImplementation p = this.Verify>(this.rect); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/GrayscaleTest.cs b/tests/ImageSharp.Tests/Processing/Filters/GrayscaleTest.cs deleted file mode 100644 index d63d97820..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/GrayscaleTest.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Collections.Generic; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; -using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.ImageSharp.Tests.TestUtilities; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Filters -{ - public class GrayscaleTest : BaseImageOperationsExtensionTest - { - public static IEnumerable ModeTheoryData = new[] { - new object[]{ new TestType>(), GrayscaleMode.Bt709 } - }; - - [Theory] - [MemberData(nameof(ModeTheoryData))] - public void Grayscale_mode_CorrectProcessor(TestType testType, GrayscaleMode mode) - where T : IImageProcessor - { - this.operations.Grayscale(mode); - var p = this.Verify(); - } - - [Theory] - [MemberData(nameof(ModeTheoryData))] - public void Grayscale_mode_rect_CorrectProcessor(TestType testType, GrayscaleMode mode) - where T : IImageProcessor - { - this.operations.Grayscale(mode, this.rect); - this.Verify(this.rect); - } - - [Fact] - public void Grayscale_rect_CorrectProcessor() - { - this.operations.Grayscale(this.rect); - this.Verify>(this.rect); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/HueTest.cs b/tests/ImageSharp.Tests/Processing/Filters/HueTest.cs deleted file mode 100644 index f56578dd6..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/HueTest.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Filters -{ - public class HueTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Hue_amount_HueProcessorDefaultsSet() - { - this.operations.Hue(34f); - var processor = this.Verify>(); - - Assert.Equal(34f, processor.Degrees); - } - - [Fact] - public void Hue_amount_rect_HueProcessorDefaultsSet() - { - this.operations.Hue(5f, this.rect); - var processor = this.Verify>(this.rect); - - Assert.Equal(5f, processor.Degrees); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/InvertTest.cs b/tests/ImageSharp.Tests/Processing/Filters/InvertTest.cs deleted file mode 100644 index c93afc942..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/InvertTest.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Effects -{ - public class InvertTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Invert_InvertProcessorDefaultsSet() - { - this.operations.Invert(); - var processor = this.Verify>(); - } - - [Fact] - public void Pixelate_rect_PixelateProcessorDefaultsSet() - { - this.operations.Invert(this.rect); - var processor = this.Verify>(this.rect); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/KodachromeTest.cs b/tests/ImageSharp.Tests/Processing/Filters/KodachromeTest.cs deleted file mode 100644 index a98252140..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/KodachromeTest.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Filters -{ - public class KodachromeTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Kodachrome_amount_KodachromeProcessorDefaultsSet() - { - this.operations.Kodachrome(); - var processor = this.Verify>(); - } - - [Fact] - public void Kodachrome_amount_rect_KodachromeProcessorDefaultsSet() - { - this.operations.Kodachrome(this.rect); - var processor = this.Verify>(this.rect); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/LomographTest.cs b/tests/ImageSharp.Tests/Processing/Filters/LomographTest.cs deleted file mode 100644 index c104f8c25..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/LomographTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.IO; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.Primitives; -using Xunit; - -namespace SixLabors.ImageSharp.Tests -{ - using SixLabors.ImageSharp.Processing; - using SixLabors.ImageSharp.Processing.Processors.Filters; - - public class LomographTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Lomograph_amount_LomographProcessorDefaultsSet() - { - this.operations.Lomograph(); - var processor = this.Verify>(); - } - - [Fact] - public void Lomograph_amount_rect_LomographProcessorDefaultsSet() - { - this.operations.Lomograph(this.rect); - var processor = this.Verify>(this.rect); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/OpacityTest.cs b/tests/ImageSharp.Tests/Processing/Filters/OpacityTest.cs deleted file mode 100644 index adbb8cf29..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/OpacityTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Effects -{ - public class OpacityTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Alpha_amount_AlphaProcessorDefaultsSet() - { - this.operations.Opacity(0.2f); - OpacityProcessor processor = this.Verify>(); - - Assert.Equal(.2f, processor.Amount); - } - - [Fact] - public void Alpha_amount_rect_AlphaProcessorDefaultsSet() - { - this.operations.Opacity(0.6f, this.rect); - OpacityProcessor processor = this.Verify>(this.rect); - - Assert.Equal(.6f, processor.Amount); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/PolaroidTest.cs b/tests/ImageSharp.Tests/Processing/Filters/PolaroidTest.cs deleted file mode 100644 index f28827b71..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/PolaroidTest.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Filters -{ - public class PolaroidTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Polaroid_amount_PolaroidProcessorDefaultsSet() - { - this.operations.Polaroid(); - var processor = this.Verify>(); - } - - [Fact] - public void Polaroid_amount_rect_PolaroidProcessorDefaultsSet() - { - this.operations.Polaroid(this.rect); - var processor = this.Verify>(this.rect); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/SaturateTest.cs b/tests/ImageSharp.Tests/Processing/Filters/SaturateTest.cs deleted file mode 100644 index 4b8e80881..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/SaturateTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Filters -{ - public class SaturateTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Saturation_amount_SaturationProcessorDefaultsSet() - { - this.operations.Saturate(34); - SaturateProcessor processor = this.Verify>(); - - Assert.Equal(34, processor.Amount); - } - - [Fact] - public void Saturation_amount_rect_SaturationProcessorDefaultsSet() - { - this.operations.Saturate(5, this.rect); - SaturateProcessor processor = this.Verify>(this.rect); - - Assert.Equal(5, processor.Amount); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/SepiaTest.cs b/tests/ImageSharp.Tests/Processing/Filters/SepiaTest.cs deleted file mode 100644 index 9351c8443..000000000 --- a/tests/ImageSharp.Tests/Processing/Filters/SepiaTest.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Filters; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Filters -{ - public class SepiaTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Sepia_amount_SepiaProcessorDefaultsSet() - { - this.operations.Sepia(); - var processor = this.Verify>(); - } - - [Fact] - public void Sepia_amount_rect_SepiaProcessorDefaultsSet() - { - this.operations.Sepia(this.rect); - var processor = this.Verify>(this.rect); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs index 82d768255..eca1a458b 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms IResampler sampler = KnownResamplers.NearestNeighbor; this.operations.Pad(width, height); - ResizeProcessor resizeProcessor = this.Verify>(); + ResizeProcessorImplementation resizeProcessor = this.Verify>(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs index 948c79d8d..01c43a0a4 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms int width = 50; int height = 100; this.operations.Resize(width, height); - ResizeProcessor resizeProcessor = this.Verify>(); + ResizeProcessorImplementation resizeProcessor = this.Verify>(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms int height = 100; IResampler sampler = KnownResamplers.Lanczos3; this.operations.Resize(width, height, sampler); - ResizeProcessor resizeProcessor = this.Verify>(); + ResizeProcessorImplementation resizeProcessor = this.Verify>(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms // ReSharper disable once ConditionIsAlwaysTrueOrFalse this.operations.Resize(width, height, sampler, compand); - ResizeProcessor resizeProcessor = this.Verify>(); + ResizeProcessorImplementation resizeProcessor = this.Verify>(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms }; this.operations.Resize(resizeOptions); - ResizeProcessor resizeProcessor = this.Verify>(); + ResizeProcessorImplementation resizeProcessor = this.Verify>(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); From 77a1bba8c5ac639e1f1177b0b64ff991ee2c398f Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 01:21:06 +0200 Subject: [PATCH 108/223] fix processor invocation tests --- .../BaseImageOperationsExtensionTest.cs | 16 ++++++++++++-- .../FakeImageOperationsProvider.cs | 21 ++++++++++++++----- tests/ImageSharp.Tests/ImageOperationTests.cs | 14 ++++++------- .../Processing/Filters/FilterTest.cs | 4 ++-- .../Processing/Transforms/ResizeTests.cs | 8 +++---- 5 files changed, 43 insertions(+), 20 deletions(-) diff --git a/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs b/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs index 7adbefb34..857c19d87 100644 --- a/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs +++ b/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs @@ -3,6 +3,7 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors; using SixLabors.Primitives; using Xunit; @@ -33,7 +34,12 @@ namespace SixLabors.ImageSharp.Tests FakeImageOperationsProvider.FakeImageOperations.AppliedOperation operation = this.internalOperations.Applied[index]; - return Assert.IsType(operation.Processor); + if (operation.NonGenericProcessor != null) + { + return Assert.IsType(operation.NonGenericProcessor); + } + + return Assert.IsType(operation.GenericProcessor); } public T Verify(Rectangle rect, int index = 0) @@ -43,7 +49,13 @@ namespace SixLabors.ImageSharp.Tests FakeImageOperationsProvider.FakeImageOperations.AppliedOperation operation = this.internalOperations.Applied[index]; Assert.Equal(rect, operation.Rectangle); - return Assert.IsType(operation.Processor); + + if (operation.NonGenericProcessor != null) + { + return Assert.IsType(operation.NonGenericProcessor); + } + + return Assert.IsType(operation.GenericProcessor); } } } diff --git a/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs b/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs index 276cc5da8..c91cb16d4 100644 --- a/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs +++ b/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs @@ -69,19 +69,28 @@ namespace SixLabors.ImageSharp.Tests public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle) { - throw new System.NotImplementedException(); + this.Applied.Add(new AppliedOperation() + { + Rectangle = rectangle, + NonGenericProcessor = processor + }); + return this; } public IImageProcessingContext ApplyProcessor(IImageProcessor processor) { - throw new System.NotImplementedException(); + this.Applied.Add(new AppliedOperation() + { + NonGenericProcessor = processor + }); + return this; } public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle) { this.Applied.Add(new AppliedOperation { - Processor = processor, + GenericProcessor = processor, Rectangle = rectangle }); return this; @@ -91,7 +100,7 @@ namespace SixLabors.ImageSharp.Tests { this.Applied.Add(new AppliedOperation { - Processor = processor + GenericProcessor = processor }); return this; } @@ -99,7 +108,9 @@ namespace SixLabors.ImageSharp.Tests public struct AppliedOperation { public Rectangle? Rectangle { get; set; } - public IImageProcessor Processor { get; set; } + public IImageProcessor GenericProcessor { get; set; } + + public IImageProcessor NonGenericProcessor { get; set; } } } } diff --git a/tests/ImageSharp.Tests/ImageOperationTests.cs b/tests/ImageSharp.Tests/ImageOperationTests.cs index 869882f67..e694f0b64 100644 --- a/tests/ImageSharp.Tests/ImageOperationTests.cs +++ b/tests/ImageSharp.Tests/ImageOperationTests.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Tests this.image.Mutate(x => x.ApplyProcessor(this.processor)); Assert.True(this.provider.HasCreated(this.image)); - Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.Processor)); + Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests this.image.Mutate(this.processor); Assert.True(this.provider.HasCreated(this.image)); - Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.Processor)); + Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Tests Image returned = this.image.Clone(x => x.ApplyProcessor(this.processor)); Assert.True(this.provider.HasCreated(returned)); - Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.Processor)); + Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); } [Fact] @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests Image returned = this.image.Clone(this.processor); Assert.True(this.provider.HasCreated(returned)); - Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.Processor)); + Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); } [Fact] @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Tests { Image returned = this.image.Clone(x => x.ApplyProcessor(this.processor)); Assert.False(this.provider.HasCreated(this.image)); - Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.Processor)); + Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] @@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Tests { Image returned = this.image.Clone(this.processor); Assert.False(this.provider.HasCreated(this.image)); - Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.Processor)); + Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] @@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp.Tests { var operations = new FakeImageOperationsProvider.FakeImageOperations(null, false); operations.ApplyProcessors(this.processor); - Assert.Contains(this.processor, operations.Applied.Select(x => x.Processor)); + Assert.Contains(this.processor, operations.Applied.Select(x => x.GenericProcessor)); } public void Dispose() => this.image.Dispose(); diff --git a/tests/ImageSharp.Tests/Processing/Filters/FilterTest.cs b/tests/ImageSharp.Tests/Processing/Filters/FilterTest.cs index f4efb1274..d598f0ac8 100644 --- a/tests/ImageSharp.Tests/Processing/Filters/FilterTest.cs +++ b/tests/ImageSharp.Tests/Processing/Filters/FilterTest.cs @@ -17,14 +17,14 @@ namespace SixLabors.ImageSharp.Tests.Processing.Filters public void Filter_CorrectProcessor() { this.operations.Filter(KnownFilterMatrices.AchromatomalyFilter * KnownFilterMatrices.CreateHueFilter(90F)); - FilterProcessorImplementation p = this.Verify>(); + FilterProcessor p = this.Verify(); } [Fact] public void Filter_rect_CorrectProcessor() { this.operations.Filter(KnownFilterMatrices.AchromatomalyFilter * KnownFilterMatrices.CreateHueFilter(90F), this.rect); - FilterProcessorImplementation p = this.Verify>(this.rect); + FilterProcessor p = this.Verify(this.rect); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs index 01c43a0a4..570ac4e2c 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms int width = 50; int height = 100; this.operations.Resize(width, height); - ResizeProcessorImplementation resizeProcessor = this.Verify>(); + ResizeProcessor resizeProcessor = this.Verify(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms int height = 100; IResampler sampler = KnownResamplers.Lanczos3; this.operations.Resize(width, height, sampler); - ResizeProcessorImplementation resizeProcessor = this.Verify>(); + ResizeProcessor resizeProcessor = this.Verify(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms // ReSharper disable once ConditionIsAlwaysTrueOrFalse this.operations.Resize(width, height, sampler, compand); - ResizeProcessorImplementation resizeProcessor = this.Verify>(); + ResizeProcessor resizeProcessor = this.Verify(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms }; this.operations.Resize(resizeOptions); - ResizeProcessorImplementation resizeProcessor = this.Verify>(); + ResizeProcessor resizeProcessor = this.Verify(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); From 137a08a21c4e827c16cbdcb68f7681122b18e9b7 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 01:26:10 +0200 Subject: [PATCH 109/223] re-add and fix filter invocation tests --- .../Processing/Filters/BlackWhiteTest.cs | 27 +++++++++++ .../Processing/Filters/BrightnessTest.cs | 31 ++++++++++++ .../Processing/Filters/ColorBlindnessTest.cs | 46 ++++++++++++++++++ .../Processing/Filters/ContrastTest.cs | 33 +++++++++++++ .../Processing/Filters/GrayscaleTest.cs | 47 +++++++++++++++++++ .../Processing/Filters/HueTest.cs | 32 +++++++++++++ .../Processing/Filters/InvertTest.cs | 27 +++++++++++ .../Processing/Filters/KodachromeTest.cs | 27 +++++++++++ .../Processing/Filters/LomographTest.cs | 31 ++++++++++++ .../Processing/Filters/OpacityTest.cs | 31 ++++++++++++ .../Processing/Filters/PolaroidTest.cs | 28 +++++++++++ .../Processing/Filters/SaturateTest.cs | 31 ++++++++++++ .../Processing/Filters/SepiaTest.cs | 27 +++++++++++ 13 files changed, 418 insertions(+) create mode 100644 tests/ImageSharp.Tests/Processing/Filters/BlackWhiteTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/ColorBlindnessTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/ContrastTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/GrayscaleTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/HueTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/InvertTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/KodachromeTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/LomographTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/OpacityTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/PolaroidTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/SaturateTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Filters/SepiaTest.cs diff --git a/tests/ImageSharp.Tests/Processing/Filters/BlackWhiteTest.cs b/tests/ImageSharp.Tests/Processing/Filters/BlackWhiteTest.cs new file mode 100644 index 000000000..f913068e3 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/BlackWhiteTest.cs @@ -0,0 +1,27 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Filters +{ + public class BlackWhiteTest : BaseImageOperationsExtensionTest + { + [Fact] + public void BlackWhite_CorrectProcessor() + { + this.operations.BlackWhite(); + BlackWhiteProcessor p = this.Verify(); + } + + [Fact] + public void BlackWhite_rect_CorrectProcessor() + { + this.operations.BlackWhite(this.rect); + BlackWhiteProcessor p = this.Verify(this.rect); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs b/tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs new file mode 100644 index 000000000..c26524880 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs @@ -0,0 +1,31 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Effects +{ + public class BrightnessTest : BaseImageOperationsExtensionTest + { + [Fact] + public void Brightness_amount_BrightnessProcessorDefaultsSet() + { + this.operations.Brightness(1.5F); + BrightnessProcessor processor = this.Verify(); + + Assert.Equal(1.5F, processor.Amount); + } + + [Fact] + public void Brightness_amount_rect_BrightnessProcessorDefaultsSet() + { + this.operations.Brightness(1.5F, this.rect); + BrightnessProcessor processor = this.Verify(this.rect); + + Assert.Equal(1.5F, processor.Amount); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processing/Filters/ColorBlindnessTest.cs new file mode 100644 index 000000000..7dd894403 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/ColorBlindnessTest.cs @@ -0,0 +1,46 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Collections.Generic; + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using SixLabors.ImageSharp.Processing.Processors; +using SixLabors.ImageSharp.Tests.TestUtilities; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Filters +{ + public class ColorBlindnessTest : BaseImageOperationsExtensionTest + { + public static IEnumerable TheoryData = new[] { + new object[]{ new TestType(), ColorBlindnessMode.Achromatomaly }, + new object[]{ new TestType(), ColorBlindnessMode.Achromatopsia }, + new object[]{ new TestType(), ColorBlindnessMode.Deuteranomaly }, + new object[]{ new TestType(), ColorBlindnessMode.Deuteranopia }, + new object[]{ new TestType(), ColorBlindnessMode.Protanomaly }, + new object[]{ new TestType(), ColorBlindnessMode.Protanopia }, + new object[]{ new TestType(), ColorBlindnessMode.Tritanomaly }, + new object[]{ new TestType(), ColorBlindnessMode.Tritanopia } + }; + + [Theory] + [MemberData(nameof(TheoryData))] + public void ColorBlindness_CorrectProcessor(TestType testType, ColorBlindnessMode colorBlindness) + where T : IImageProcessor + { + this.operations.ColorBlindness(colorBlindness); + T p = this.Verify(); + } + [Theory] + [MemberData(nameof(TheoryData))] + public void ColorBlindness_rect_CorrectProcessor(TestType testType, ColorBlindnessMode colorBlindness) + where T : IImageProcessor + { + this.operations.ColorBlindness(colorBlindness, this.rect); + T p = this.Verify(this.rect); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/ContrastTest.cs b/tests/ImageSharp.Tests/Processing/Filters/ContrastTest.cs new file mode 100644 index 000000000..ff2b1c702 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/ContrastTest.cs @@ -0,0 +1,33 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Effects +{ + using SixLabors.ImageSharp.Processing; + using SixLabors.ImageSharp.Processing.Processors.Filters; + + public class ContrastTest : BaseImageOperationsExtensionTest + { + [Fact] + public void Contrast_amount_ContrastProcessorDefaultsSet() + { + this.operations.Contrast(1.5F); + ContrastProcessor processor = this.Verify(); + + Assert.Equal(1.5F, processor.Amount); + } + + [Fact] + public void Contrast_amount_rect_ContrastProcessorDefaultsSet() + { + this.operations.Contrast(1.5F, this.rect); + ContrastProcessor processor = this.Verify(this.rect); + + Assert.Equal(1.5F, processor.Amount); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/GrayscaleTest.cs b/tests/ImageSharp.Tests/Processing/Filters/GrayscaleTest.cs new file mode 100644 index 000000000..94e1b00a7 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/GrayscaleTest.cs @@ -0,0 +1,47 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Collections.Generic; + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using SixLabors.ImageSharp.Processing.Processors; +using SixLabors.ImageSharp.Tests.TestUtilities; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Filters +{ + public class GrayscaleTest : BaseImageOperationsExtensionTest + { + public static IEnumerable ModeTheoryData = new[] { + new object[]{ new TestType(), GrayscaleMode.Bt709 } + }; + + [Theory] + [MemberData(nameof(ModeTheoryData))] + public void Grayscale_mode_CorrectProcessor(TestType testType, GrayscaleMode mode) + where T : IImageProcessor + { + this.operations.Grayscale(mode); + var p = this.Verify(); + } + + [Theory] + [MemberData(nameof(ModeTheoryData))] + public void Grayscale_mode_rect_CorrectProcessor(TestType testType, GrayscaleMode mode) + where T : IImageProcessor + { + this.operations.Grayscale(mode, this.rect); + this.Verify(this.rect); + } + + [Fact] + public void Grayscale_rect_CorrectProcessor() + { + this.operations.Grayscale(this.rect); + this.Verify(this.rect); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/HueTest.cs b/tests/ImageSharp.Tests/Processing/Filters/HueTest.cs new file mode 100644 index 000000000..0eb25043c --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/HueTest.cs @@ -0,0 +1,32 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Filters +{ + public class HueTest : BaseImageOperationsExtensionTest + { + [Fact] + public void Hue_amount_HueProcessorDefaultsSet() + { + this.operations.Hue(34f); + var processor = this.Verify(); + + Assert.Equal(34f, processor.Degrees); + } + + [Fact] + public void Hue_amount_rect_HueProcessorDefaultsSet() + { + this.operations.Hue(5f, this.rect); + var processor = this.Verify(this.rect); + + Assert.Equal(5f, processor.Degrees); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/InvertTest.cs b/tests/ImageSharp.Tests/Processing/Filters/InvertTest.cs new file mode 100644 index 000000000..ff59eab05 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/InvertTest.cs @@ -0,0 +1,27 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Effects +{ + public class InvertTest : BaseImageOperationsExtensionTest + { + [Fact] + public void Invert_InvertProcessorDefaultsSet() + { + this.operations.Invert(); + var processor = this.Verify(); + } + + [Fact] + public void Pixelate_rect_PixelateProcessorDefaultsSet() + { + this.operations.Invert(this.rect); + var processor = this.Verify(this.rect); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/KodachromeTest.cs b/tests/ImageSharp.Tests/Processing/Filters/KodachromeTest.cs new file mode 100644 index 000000000..a06a9d65c --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/KodachromeTest.cs @@ -0,0 +1,27 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Filters +{ + public class KodachromeTest : BaseImageOperationsExtensionTest + { + [Fact] + public void Kodachrome_amount_KodachromeProcessorDefaultsSet() + { + this.operations.Kodachrome(); + var processor = this.Verify(); + } + + [Fact] + public void Kodachrome_amount_rect_KodachromeProcessorDefaultsSet() + { + this.operations.Kodachrome(this.rect); + var processor = this.Verify(this.rect); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/LomographTest.cs b/tests/ImageSharp.Tests/Processing/Filters/LomographTest.cs new file mode 100644 index 000000000..446cfa1c3 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/LomographTest.cs @@ -0,0 +1,31 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.IO; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors; +using SixLabors.Primitives; +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + using SixLabors.ImageSharp.Processing; + using SixLabors.ImageSharp.Processing.Processors.Filters; + + public class LomographTest : BaseImageOperationsExtensionTest + { + [Fact] + public void Lomograph_amount_LomographProcessorDefaultsSet() + { + this.operations.Lomograph(); + var processor = this.Verify(); + } + + [Fact] + public void Lomograph_amount_rect_LomographProcessorDefaultsSet() + { + this.operations.Lomograph(this.rect); + var processor = this.Verify(this.rect); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/OpacityTest.cs b/tests/ImageSharp.Tests/Processing/Filters/OpacityTest.cs new file mode 100644 index 000000000..95ea2c23e --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/OpacityTest.cs @@ -0,0 +1,31 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Effects +{ + public class OpacityTest : BaseImageOperationsExtensionTest + { + [Fact] + public void Alpha_amount_AlphaProcessorDefaultsSet() + { + this.operations.Opacity(0.2f); + OpacityProcessor processor = this.Verify(); + + Assert.Equal(.2f, processor.Amount); + } + + [Fact] + public void Alpha_amount_rect_AlphaProcessorDefaultsSet() + { + this.operations.Opacity(0.6f, this.rect); + OpacityProcessor processor = this.Verify(this.rect); + + Assert.Equal(.6f, processor.Amount); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/PolaroidTest.cs b/tests/ImageSharp.Tests/Processing/Filters/PolaroidTest.cs new file mode 100644 index 000000000..f63b892bc --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/PolaroidTest.cs @@ -0,0 +1,28 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Filters +{ + public class PolaroidTest : BaseImageOperationsExtensionTest + { + [Fact] + public void Polaroid_amount_PolaroidProcessorDefaultsSet() + { + this.operations.Polaroid(); + var processor = this.Verify(); + } + + [Fact] + public void Polaroid_amount_rect_PolaroidProcessorDefaultsSet() + { + this.operations.Polaroid(this.rect); + var processor = this.Verify(this.rect); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/SaturateTest.cs b/tests/ImageSharp.Tests/Processing/Filters/SaturateTest.cs new file mode 100644 index 000000000..b1583b4ac --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/SaturateTest.cs @@ -0,0 +1,31 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Filters +{ + public class SaturateTest : BaseImageOperationsExtensionTest + { + [Fact] + public void Saturation_amount_SaturationProcessorDefaultsSet() + { + this.operations.Saturate(34); + SaturateProcessor processor = this.Verify(); + + Assert.Equal(34, processor.Amount); + } + + [Fact] + public void Saturation_amount_rect_SaturationProcessorDefaultsSet() + { + this.operations.Saturate(5, this.rect); + SaturateProcessor processor = this.Verify(this.rect); + + Assert.Equal(5, processor.Amount); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Filters/SepiaTest.cs b/tests/ImageSharp.Tests/Processing/Filters/SepiaTest.cs new file mode 100644 index 000000000..441c9739d --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Filters/SepiaTest.cs @@ -0,0 +1,27 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Filters +{ + public class SepiaTest : BaseImageOperationsExtensionTest + { + [Fact] + public void Sepia_amount_SepiaProcessorDefaultsSet() + { + this.operations.Sepia(); + var processor = this.Verify(); + } + + [Fact] + public void Sepia_amount_rect_SepiaProcessorDefaultsSet() + { + this.operations.Sepia(this.rect); + var processor = this.Verify(this.rect); + } + } +} \ No newline at end of file From 6554db9732f8ad3582bf723d90fd3e8a630fa888 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 02:17:33 +0200 Subject: [PATCH 110/223] fix warnings and improve xmldocs --- .../Advanced/AdvancedImageExtensions.cs | 1 - src/ImageSharp/Formats/Bmp/BmpDecoder.cs | 1 + src/ImageSharp/Formats/Gif/GifDecoder.cs | 3 +- src/ImageSharp/Formats/IImageDecoder.cs | 11 ++- src/ImageSharp/Formats/Jpeg/JpegDecoder.cs | 3 +- src/ImageSharp/Formats/Png/PngDecoder.cs | 3 +- src/ImageSharp/IImageVisitor.cs | 22 +++++ src/ImageSharp/Image.Decode.cs | 4 +- src/ImageSharp/Image.FromFile.cs | 13 ++- src/ImageSharp/Image.FromStream.cs | 1 + src/ImageSharp/Image.WrapMemory.cs | 8 +- src/ImageSharp/Image.cs | 43 ++++++---- src/ImageSharp/ImageExtensions.cs | 3 - src/ImageSharp/Image{TPixel}.cs | 25 ++---- .../Processing/IImageProcessingContext.cs | 42 +++++++++ .../IImageProcessingContext{TPixel}.cs | 26 +----- src/ImageSharp/Processing/PadExtensions.cs | 3 +- .../Processing/PolaroidExtensions.cs | 1 - .../Processing/ProcessingExtensions.cs | 85 +++++++++++-------- .../Processors/Filters/BlackWhiteProcessor.cs | 3 +- .../Processors/Filters/FilterProcessor.cs | 4 + .../LomographProcessorImplementation.cs | 13 +-- .../Processors/Filters/OpacityProcessor.cs | 3 +- .../Processors/Filters/PolaroidProcessor.cs | 26 +----- .../PolaroidProcessorImplementation.cs | 31 +++++++ .../Processors/Filters/ProtanopiaProcessor.cs | 1 - .../Processing/Processors/IImageProcessor.cs | 13 ++- .../Transforms/Resize/ResizeProcessor.cs | 72 +++++++++------- .../Resize/ResizeProcessorImplementation.cs | 6 +- src/ImageSharp/Processing/ResizeExtensions.cs | 10 --- .../ImageSharp.Benchmarks.csproj | 3 +- 31 files changed, 287 insertions(+), 196 deletions(-) create mode 100644 src/ImageSharp/IImageVisitor.cs create mode 100644 src/ImageSharp/Processing/IImageProcessingContext.cs create mode 100644 src/ImageSharp/Processing/Processors/Filters/PolaroidProcessorImplementation.cs diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs index 378b6e8b9..e0d7a4b18 100644 --- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs +++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs @@ -18,7 +18,6 @@ namespace SixLabors.ImageSharp.Advanced /// /// Gets the configuration for the image. /// - /// The Pixel format. /// The source image. /// Returns the configuration. public static Configuration GetConfiguration(this Image source) diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs index 4922a9200..ebb7ffdf3 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs @@ -30,6 +30,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp return new BmpDecoderCore(configuration, this).Decode(stream); } + /// public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); /// diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs index 6498f4aa2..1addcd0ab 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoder.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs @@ -44,7 +44,8 @@ namespace SixLabors.ImageSharp.Formats.Gif var decoder = new GifDecoderCore(configuration, this); return decoder.Identify(stream); } - + + /// public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } } diff --git a/src/ImageSharp/Formats/IImageDecoder.cs b/src/ImageSharp/Formats/IImageDecoder.cs index 625c4efb6..8dafdac79 100644 --- a/src/ImageSharp/Formats/IImageDecoder.cs +++ b/src/ImageSharp/Formats/IImageDecoder.cs @@ -12,15 +12,22 @@ namespace SixLabors.ImageSharp.Formats public interface IImageDecoder { /// - /// Decodes the image from the specified stream to the . + /// Decodes the image from the specified stream to an of a specific pixel type. /// /// The pixel format. /// The configuration for the image. /// The containing image data. - /// The decoded image + /// The decoded image of a given pixel type. Image Decode(Configuration configuration, Stream stream) where TPixel : struct, IPixel; + /// + /// Decodes the image from the specified stream to an . + /// The decoder is free to choose the pixel type. + /// + /// The configuration for the image. + /// The containing image data. + /// The decoded image of a pixel type chosen by the decoder. Image Decode(Configuration configuration, Stream stream); } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs index 7459abec5..a1bf04852 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs @@ -38,7 +38,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg return decoder.Identify(stream); } } - + + /// public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/PngDecoder.cs b/src/ImageSharp/Formats/Png/PngDecoder.cs index e8c5ac8e8..040da9473 100644 --- a/src/ImageSharp/Formats/Png/PngDecoder.cs +++ b/src/ImageSharp/Formats/Png/PngDecoder.cs @@ -59,7 +59,8 @@ namespace SixLabors.ImageSharp.Formats.Png var decoder = new PngDecoderCore(configuration, this); return decoder.Identify(stream); } - + + /// public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } } \ No newline at end of file diff --git a/src/ImageSharp/IImageVisitor.cs b/src/ImageSharp/IImageVisitor.cs new file mode 100644 index 000000000..971c4d37c --- /dev/null +++ b/src/ImageSharp/IImageVisitor.cs @@ -0,0 +1,22 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + /// + /// A visitor to implement double-dispatch pattern in order to apply pixel-specific operations + /// on non-generic instances. The operation is dispatched by . + /// + internal interface IImageVisitor + { + /// + /// Provides a pixel-specific implementation for a given operation. + /// + /// The image. + /// The pixel type. + void Visit(Image image) + where TPixel : struct, IPixel; + } +} \ No newline at end of file diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index 17a15a916..8d0df599e 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp /// The image might be filled with memory garbage. /// /// The pixel type - /// The + /// The /// The width of the image /// The height of the image /// The @@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp Image img = decoder.Decode(config, stream); return (img, format); } - + private static (Image img, IImageFormat format) Decode(Stream stream, Configuration config) { IImageDecoder decoder = DiscoverDecoder(stream, config, out IImageFormat format); diff --git a/src/ImageSharp/Image.FromFile.cs b/src/ImageSharp/Image.FromFile.cs index 0b4966886..61500e20d 100644 --- a/src/ImageSharp/Image.FromFile.cs +++ b/src/ImageSharp/Image.FromFile.cs @@ -162,7 +162,18 @@ namespace SixLabors.ImageSharp return Load(config, stream, out format); } } - + + /// + /// Create a new instance of the class from the given file. + /// The pixel type is selected by the decoder. + /// + /// The configuration options. + /// The file path to the image. + /// The mime type of the decoded image. + /// + /// Thrown if the stream is not readable nor seekable. + /// + /// A new . public static Image Load(Configuration config, string path, out IImageFormat format) { using (Stream stream = config.FileSystem.OpenRead(path)) diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index b16501b0f..a4a9eeec7 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -182,6 +182,7 @@ namespace SixLabors.ImageSharp throw new NotSupportedException(sb.ToString()); } + private static Image Load(Configuration config, Stream stream, out IImageFormat format) { config = config ?? Configuration.Default; diff --git a/src/ImageSharp/Image.WrapMemory.cs b/src/ImageSharp/Image.WrapMemory.cs index 49bc99e9e..095991b07 100644 --- a/src/ImageSharp/Image.WrapMemory.cs +++ b/src/ImageSharp/Image.WrapMemory.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp /// allowing to view/manipulate it as an ImageSharp instance. /// /// The pixel type - /// The + /// The /// The pixel memory. /// The width of the memory image. /// The height of the memory image. @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp /// allowing to view/manipulate it as an ImageSharp instance. /// /// The pixel type - /// The + /// The /// The pixel memory. /// The width of the memory image. /// The height of the memory image. @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp /// It will be disposed together with the result image. /// /// The pixel type - /// The + /// The /// The that is being transferred to the image /// The width of the memory image. /// The height of the memory image. @@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp /// It will be disposed together with the result image. /// /// The pixel type. - /// The + /// The /// The that is being transferred to the image. /// The width of the memory image. /// The height of the memory image. diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index a27f16ab3..d0a1c4319 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -10,15 +10,30 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { - internal interface IImageVisitor - { - void Visit(Image image) - where TPixel : struct, IPixel; - } - + /// + /// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes. + /// For the non-generic type, the pixel type is only known at runtime. + /// is always implemented by a pixel-specific instance. + /// public abstract partial class Image : IImage, IConfigurable { - protected readonly Configuration configuration; + /// + /// Initializes a new instance of the class. + /// + /// The . + /// The . + /// The . + protected Image(Configuration configuration, PixelTypeInfo pixelType, ImageMetadata metadata) + { + this.Configuration = configuration ?? Configuration.Default; + this.PixelType = pixelType; + this.Metadata = metadata ?? new ImageMetadata(); + } + + /// + /// Gets the . + /// + protected Configuration Configuration { get; } /// public PixelTypeInfo PixelType { get; } @@ -28,22 +43,16 @@ namespace SixLabors.ImageSharp /// public abstract int Height { get; } - + /// public ImageMetadata Metadata { get; } /// /// Gets the pixel buffer. /// - Configuration IConfigurable.Configuration => this.configuration; - - protected Image(Configuration configuration, PixelTypeInfo pixelType, ImageMetadata metadata) - { - this.configuration = configuration ?? Configuration.Default; - this.PixelType = pixelType; - this.Metadata = metadata ?? new ImageMetadata(); - } + Configuration IConfigurable.Configuration => this.Configuration; + /// public abstract void Dispose(); internal abstract void AcceptVisitor(IImageVisitor visitor); @@ -63,7 +72,7 @@ namespace SixLabors.ImageSharp this.AcceptVisitor(visitor); } - class EncodeVisitor : IImageVisitor + private class EncodeVisitor : IImageVisitor { private readonly IImageEncoder encoder; diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs index 3bd60694d..ec4c364d8 100644 --- a/src/ImageSharp/ImageExtensions.cs +++ b/src/ImageSharp/ImageExtensions.cs @@ -19,7 +19,6 @@ namespace SixLabors.ImageSharp /// /// Writes the image to the given stream using the currently loaded image format. /// - /// The pixel format. /// The source image. /// The file path to save the image to. /// Thrown if the stream is null. @@ -61,7 +60,6 @@ namespace SixLabors.ImageSharp /// /// Writes the image to the given stream using the currently loaded image format. /// - /// The pixel format. /// The source image. /// The file path to save the image to. /// The encoder to save the image with. @@ -78,7 +76,6 @@ namespace SixLabors.ImageSharp /// /// Writes the image to the given stream using the currently loaded image format. /// - /// The Pixel format. /// The source image. /// The stream to save the image to. /// The format to save the image in. diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index ea6d0beb2..243e2912b 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -16,6 +16,7 @@ namespace SixLabors.ImageSharp { /// /// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes. + /// For generic -s the pixel type is known at compile time. /// /// The pixel format. public sealed class Image : Image @@ -68,8 +69,6 @@ namespace SixLabors.ImageSharp internal Image(Configuration configuration, int width, int height, ImageMetadata metadata) : base(configuration, PixelTypeInfo.Create(), metadata) { - this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); - this.Metadata = metadata ?? new ImageMetadata(); this.Frames = new ImageFrameCollection(this, width, height, default(TPixel)); } @@ -85,8 +84,6 @@ namespace SixLabors.ImageSharp internal Image(Configuration configuration, MemorySource memorySource, int width, int height, ImageMetadata metadata) : base(configuration, PixelTypeInfo.Create(), metadata) { - this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); - this.Metadata = metadata; this.Frames = new ImageFrameCollection(this, width, height, memorySource); } @@ -102,8 +99,6 @@ namespace SixLabors.ImageSharp internal Image(Configuration configuration, int width, int height, TPixel backgroundColor, ImageMetadata metadata) : base(configuration, PixelTypeInfo.Create(), metadata) { - this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); - this.Metadata = metadata ?? new ImageMetadata(); this.Frames = new ImageFrameCollection(this, width, height, backgroundColor); } @@ -115,27 +110,18 @@ namespace SixLabors.ImageSharp /// The images metadata. /// The frames that will be owned by this image instance. internal Image(Configuration configuration, ImageMetadata metadata, IEnumerable> frames) - : base(configuration,PixelTypeInfo.Create(), metadata) + : base(configuration, PixelTypeInfo.Create(), metadata) { - this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8); - this.Metadata = metadata ?? new ImageMetadata(); - this.Frames = new ImageFrameCollection(this, frames); } - - /// - public PixelTypeInfo PixelType { get; } - /// public override int Width => this.Frames.RootFrame.Width; /// public override int Height => this.Frames.RootFrame.Height; - /// - public ImageMetadata Metadata { get; } - + /// /// Gets the frames. /// public ImageFrameCollection Frames { get; } @@ -154,7 +140,6 @@ namespace SixLabors.ImageSharp public TPixel this[int x, int y] { get => this.PixelSource.PixelBuffer[x, y]; - set => this.PixelSource.PixelBuffer[x, y] = value; } @@ -162,7 +147,7 @@ namespace SixLabors.ImageSharp /// Clones the current image /// /// Returns a new image with all the same metadata as the original. - public Image Clone() => this.Clone(this.configuration); + public Image Clone() => this.Clone(this.Configuration); /// /// Clones the current image with the given configuration. @@ -181,7 +166,7 @@ namespace SixLabors.ImageSharp /// The pixel format. /// The public Image CloneAs() - where TPixel2 : struct, IPixel => this.CloneAs(this.configuration); + where TPixel2 : struct, IPixel => this.CloneAs(this.Configuration); /// /// Returns a copy of the image in the given pixel format. diff --git a/src/ImageSharp/Processing/IImageProcessingContext.cs b/src/ImageSharp/Processing/IImageProcessingContext.cs new file mode 100644 index 000000000..509b1313d --- /dev/null +++ b/src/ImageSharp/Processing/IImageProcessingContext.cs @@ -0,0 +1,42 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.Processing.Processors; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing +{ + /// + /// A pixel-agnostic interface to queue up image operations to apply to an image. + /// + public interface IImageProcessingContext + { + /// + /// Gets a reference to the used to allocate buffers + /// for this context. + /// + MemoryAllocator MemoryAllocator { get; } + + /// + /// Gets the image dimensions at the current point in the processing pipeline. + /// + /// The . + Size GetCurrentSize(); + + /// + /// Adds the processor to the current set of image operations to be applied. + /// + /// The processor to apply. + /// The area to apply it to. + /// The current operations class to allow chaining of operations. + IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle); + + /// + /// Adds the processor to the current set of image operations to be applied. + /// + /// The processor to apply. + /// The current operations class to allow chaining of operations. + IImageProcessingContext ApplyProcessor(IImageProcessor processor); + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs b/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs index fefa973f7..b49cfe215 100644 --- a/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs +++ b/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs @@ -3,32 +3,12 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.Memory; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { - public interface IImageProcessingContext - { - /// - /// Gets a reference to the used to allocate buffers - /// for this context. - /// - MemoryAllocator MemoryAllocator { get; } - - /// - /// Gets the image dimensions at the current point in the processing pipeline. - /// - /// The - Size GetCurrentSize(); - - IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle); - - IImageProcessingContext ApplyProcessor(IImageProcessor processor); - } - /// - /// An interface to queue up image operations to apply to an image. + /// A pixel-specific interface to queue up image operations to apply to an image. /// /// The pixel format public interface IImageProcessingContext : IImageProcessingContext @@ -37,8 +17,8 @@ namespace SixLabors.ImageSharp.Processing /// /// Adds the processor to the current set of image operations to be applied. /// - /// The processor to apply - /// The area to apply it to + /// The processor to apply. + /// The area to apply it to. /// The current operations class to allow chaining of operations. IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle); diff --git a/src/ImageSharp/Processing/PadExtensions.cs b/src/ImageSharp/Processing/PadExtensions.cs index 2db219795..0422f7c59 100644 --- a/src/ImageSharp/Processing/PadExtensions.cs +++ b/src/ImageSharp/Processing/PadExtensions.cs @@ -14,7 +14,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Evenly pads an image to fit the new dimensions. /// - /// The pixel format. /// The source image to pad. /// The new width. /// The new height. @@ -25,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing { Size = new Size(width, height), Mode = ResizeMode.BoxPad, - Sampler = KnownResamplers.NearestNeighbor + Sampler = KnownResamplers.NearestNeighbor, }; return source.Resize(options); diff --git a/src/ImageSharp/Processing/PolaroidExtensions.cs b/src/ImageSharp/Processing/PolaroidExtensions.cs index 4172c1d61..4e7841168 100644 --- a/src/ImageSharp/Processing/PolaroidExtensions.cs +++ b/src/ImageSharp/Processing/PolaroidExtensions.cs @@ -23,7 +23,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Alters the colors of the image recreating an old Polaroid camera effect. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. diff --git a/src/ImageSharp/Processing/ProcessingExtensions.cs b/src/ImageSharp/Processing/ProcessingExtensions.cs index a1acf3aa0..c72e8cfb7 100644 --- a/src/ImageSharp/Processing/ProcessingExtensions.cs +++ b/src/ImageSharp/Processing/ProcessingExtensions.cs @@ -13,43 +13,6 @@ namespace SixLabors.ImageSharp.Processing /// public static class ProcessingExtensions { - class ProcessingVisitor : IImageVisitor - { - private readonly Action operation; - - private readonly bool mutate; - - public Image ResultImage { get; private set; } - - public ProcessingVisitor(Action operation, bool mutate) - { - this.operation = operation; - this.mutate = mutate; - } - - public void Visit(Image image) - where TPixel : struct, IPixel - { - IInternalImageProcessingContext operationsRunner = image.GetConfiguration() - .ImageOperationsProvider.CreateImageProcessingContext(image, this.mutate); - this.operation(operationsRunner); - this.ResultImage = operationsRunner.Apply(); - } - } - - public static void Mutate(this Image source, Action operation) - { - ProcessingVisitor visitor = new ProcessingVisitor(operation, true); - source.AcceptVisitor(visitor); - } - - public static Image Clone(this Image source, Action operation) - { - ProcessingVisitor visitor = new ProcessingVisitor(operation, false); - source.AcceptVisitor(visitor); - return visitor.ResultImage; - } - /// /// Applies the given operation to the mutable image. /// Useful when we need to extract information like Width/Height to parametrize the next operation working on the chain. @@ -62,6 +25,17 @@ namespace SixLabors.ImageSharp.Processing public static IImageProcessingContext Apply(this IImageProcessingContext source, Action> operation) where TPixel : struct, IPixel => source.ApplyProcessor(new DelegateProcessor(operation)); + /// + /// Mutates the source image by applying the image operation to it. + /// + /// The image to mutate. + /// The operation to perform on the source. + public static void Mutate(this Image source, Action operation) + { + ProcessingVisitor visitor = new ProcessingVisitor(operation, true); + source.AcceptVisitor(visitor); + } + /// /// Mutates the source image by applying the image operation to it. /// @@ -96,6 +70,19 @@ namespace SixLabors.ImageSharp.Processing operationsRunner.Apply(); } + /// + /// Creates a deep clone of the current image. The clone is then mutated by the given operation. + /// + /// The image to clone. + /// The operation to perform on the clone. + /// The new . + public static Image Clone(this Image source, Action operation) + { + ProcessingVisitor visitor = new ProcessingVisitor(operation, false); + source.AcceptVisitor(visitor); + return visitor.ResultImage; + } + /// /// Creates a deep clone of the current image. The clone is then mutated by the given operation. /// @@ -149,5 +136,29 @@ namespace SixLabors.ImageSharp.Processing return source; } + + private class ProcessingVisitor : IImageVisitor + { + private readonly Action operation; + + private readonly bool mutate; + + public ProcessingVisitor(Action operation, bool mutate) + { + this.operation = operation; + this.mutate = mutate; + } + + public Image ResultImage { get; private set; } + + public void Visit(Image image) + where TPixel : struct, IPixel + { + IInternalImageProcessingContext operationsRunner = image.GetConfiguration() + .ImageOperationsProvider.CreateImageProcessingContext(image, this.mutate); + this.operation(operationsRunner); + this.ResultImage = operationsRunner.Apply(); + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs index 8bf925cf0..698f11cbf 100644 --- a/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs @@ -8,11 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a black and white filter matrix to the image /// - /// The pixel format. internal class BlackWhiteProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public BlackWhiteProcessor() : base(KnownFilterMatrices.BlackWhiteFilter) diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs index 5637e9770..886b4e096 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs @@ -6,6 +6,9 @@ using SixLabors.ImageSharp.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Filters { + /// + /// Provides methods that accept a matrix to apply free-form filters to images. + /// public class FilterProcessor : IImageProcessor { /// @@ -19,6 +22,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// public ColorMatrix Matrix { get; } + /// public virtual IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel { diff --git a/src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs index d851b98e0..a922e7125 100644 --- a/src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs +++ b/src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs @@ -7,20 +7,23 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Filters { + /// + /// Converts the colors of the image recreating an old Lomograph effect. + /// internal class LomographProcessorImplementation : FilterProcessorImplementation where TPixel : struct, IPixel { private static readonly TPixel VeryDarkGreen = ColorBuilder.FromRGBA(0, 10, 0, 255); - /// - protected override void AfterFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + public LomographProcessorImplementation(LomographProcessor definition) + : base(definition) { - new VignetteProcessor(VeryDarkGreen).Apply(source, sourceRectangle, configuration); } - public LomographProcessorImplementation(FilterProcessor definition) - : base(definition) + /// + protected override void AfterFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { + new VignetteProcessor(VeryDarkGreen).Apply(source, sourceRectangle, configuration); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs index 2d6bf6e83..e790753f3 100644 --- a/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs @@ -8,11 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies an opacity filter matrix using the given amount. /// - /// The pixel format. internal class OpacityProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The proportion of the conversion. Must be between 0 and 1. public OpacityProcessor(float amount) diff --git a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs index af16d9eab..0b272c339 100644 --- a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs @@ -1,10 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors.Overlays; -using SixLabors.Primitives; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// @@ -13,33 +9,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters public class PolaroidProcessor : FilterProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public PolaroidProcessor() : base(KnownFilterMatrices.PolaroidFilter) { } + /// public override IImageProcessor CreatePixelSpecificProcessor() => new PolaroidProcessorImplementation(this); } - - internal class PolaroidProcessorImplementation : FilterProcessorImplementation - where TPixel : struct, IPixel - { - private static readonly TPixel VeryDarkOrange = ColorBuilder.FromRGB(102, 34, 0); - private static readonly TPixel LightOrange = ColorBuilder.FromRGBA(255, 153, 102, 128); - - /// - protected override void AfterFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - new VignetteProcessor(VeryDarkOrange).Apply(source, sourceRectangle, configuration); - new GlowProcessor(LightOrange, source.Width / 4F).Apply(source, sourceRectangle, configuration); - } - - public PolaroidProcessorImplementation(FilterProcessor definition) - : base(definition) - { - } - } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessorImplementation.cs new file mode 100644 index 000000000..ec3c5ed26 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessorImplementation.cs @@ -0,0 +1,31 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Overlays; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Filters +{ + /// + /// Converts the colors of the image recreating an old Polaroid effect. + /// + internal class PolaroidProcessorImplementation : FilterProcessorImplementation + where TPixel : struct, IPixel + { + private static readonly TPixel VeryDarkOrange = ColorBuilder.FromRGB(102, 34, 0); + private static readonly TPixel LightOrange = ColorBuilder.FromRGBA(255, 153, 102, 128); + + public PolaroidProcessorImplementation(FilterProcessor definition) + : base(definition) + { + } + + /// + protected override void AfterFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + new VignetteProcessor(VeryDarkOrange).Apply(source, sourceRectangle, configuration); + new GlowProcessor(LightOrange, source.Width / 4F).Apply(source, sourceRectangle, configuration); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs index 94eeaae47..bd9257913 100644 --- a/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs @@ -8,7 +8,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Protanopia (Red-Blind) color blindness. /// - /// The pixel format. internal class ProtanopiaProcessor : FilterProcessor { /// diff --git a/src/ImageSharp/Processing/Processors/IImageProcessor.cs b/src/ImageSharp/Processing/Processors/IImageProcessor.cs index 68db45380..e9b2c9c0e 100644 --- a/src/ImageSharp/Processing/Processors/IImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/IImageProcessor.cs @@ -6,14 +6,23 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors { + /// + /// Defines an algorithm to alter the pixels of an image. + /// public interface IImageProcessor { + /// + /// Creates a pixel specific that is capable for executing + /// the processing algorithm on an . + /// + /// The pixel type. + /// The IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel; } /// - /// Encapsulates methods to alter the pixels of an image. + /// Implements an algorithm to alter the pixels of an image. /// /// The pixel format. public interface IImageProcessor @@ -58,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors public void Visit(Image image) where TPixel : struct, IPixel { - var processorImpl = processor.CreatePixelSpecificProcessor(); + var processorImpl = this.processor.CreatePixelSpecificProcessor(); processorImpl.Apply(image, this.sourceRectangle); } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index d3077b7e6..021451b5c 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -8,36 +8,20 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { - // The non-generic processor is responsible for: - // - Encapsulating the parameters of the processor - // - Implementing a factory method to create the pixel-specific processor that contains the implementation + /// + /// Implements resizing of images using various resamplers. + /// public class ResizeProcessor : IImageProcessor { /// - /// Gets the sampler to perform the resize operation. + /// Initializes a new instance of the class. /// - public IResampler Sampler { get; } - - /// - /// Gets the target width. - /// - public int Width { get; } - - /// - /// Gets the target height. - /// - public int Height { get; } - - /// - /// Gets the resize rectangle. - /// - public Rectangle TargetRectangle { get; } - - /// - /// Gets a value indicating whether to compress or expand individual pixel color values on processing. - /// - public bool Compand { get; } - + /// The . + /// The width. + /// The height. + /// The size of the source image. + /// The target rectangle to resize into. + /// A value indicating whether to apply RGBA companding. public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize, Rectangle targetRectangle, bool compand) { Guard.NotNull(sampler, nameof(sampler)); @@ -67,12 +51,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.TargetRectangle = targetRectangle; this.Compand = compand; } - + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The resize options - /// The source image size + /// The resize options. + /// The source image size. public ResizeProcessor(ResizeOptions options, Size sourceSize) { Guard.NotNull(options, nameof(options)); @@ -109,7 +93,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The sampler to perform the resize operation. /// The target width. @@ -120,6 +104,32 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { } + /// + /// Gets the sampler to perform the resize operation. + /// + public IResampler Sampler { get; } + + /// + /// Gets the target width. + /// + public int Width { get; } + + /// + /// Gets the target height. + /// + public int Height { get; } + + /// + /// Gets the resize rectangle. + /// + public Rectangle TargetRectangle { get; } + + /// + /// Gets a value indicating whether to compress or expand individual pixel color values on processing. + /// + public bool Compand { get; } + + /// public IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel { diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs index 1a8bb931e..36a054c54 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs @@ -19,9 +19,11 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Provides methods that allow the resizing of images using various algorithms. - /// Adapted from + /// Implements resizing of images using various resamplers. /// + /// + /// The original code has been adapted from . + /// /// The pixel format. internal class ResizeProcessorImplementation : TransformProcessorBase where TPixel : struct, IPixel diff --git a/src/ImageSharp/Processing/ResizeExtensions.cs b/src/ImageSharp/Processing/ResizeExtensions.cs index cf029eb15..57dbcb1d1 100644 --- a/src/ImageSharp/Processing/ResizeExtensions.cs +++ b/src/ImageSharp/Processing/ResizeExtensions.cs @@ -15,7 +15,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Resizes an image in accordance with the given . /// - /// The pixel format. /// The image to resize. /// The resize options. /// The @@ -26,7 +25,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Resizes an image to the given . /// - /// The pixel format. /// The image to resize. /// The target image size. /// The @@ -37,7 +35,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Resizes an image to the given . /// - /// The pixel format. /// The image to resize. /// The target image size. /// Whether to compress and expand the image color-space to gamma correct the image during processing. @@ -49,7 +46,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Resizes an image to the given width and height. /// - /// The pixel format. /// The image to resize. /// The target image width. /// The target image height. @@ -61,7 +57,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Resizes an image to the given width and height. /// - /// The pixel format. /// The image to resize. /// The target image width. /// The target image height. @@ -74,7 +69,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Resizes an image to the given width and height with the given sampler. /// - /// The pixel format. /// The image to resize. /// The target image width. /// The target image height. @@ -87,7 +81,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Resizes an image to the given width and height with the given sampler. /// - /// The pixel format. /// The image to resize. /// The target image size. /// The to perform the resampling. @@ -100,7 +93,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Resizes an image to the given width and height with the given sampler. /// - /// The pixel format. /// The image to resize. /// The target image width. /// The target image height. @@ -115,7 +107,6 @@ namespace SixLabors.ImageSharp.Processing /// Resizes an image to the given width and height with the given sampler and /// source rectangle. /// - /// The pixel format. /// The image to resize. /// The target image width. /// The target image height. @@ -142,7 +133,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Resizes an image to the given width and height with the given sampler and source rectangle. /// - /// The pixel format. /// The image to resize. /// The target image width. /// The target image height. diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index 9af4d57cf..2a5408da1 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -1,6 +1,7 @@  - netcoreapp2.1;net472 + + netcoreapp2.1 Exe True SixLabors.ImageSharp.Benchmarks From b758eaf16bdeb4e1e5d8ad9d4a817f4652efc432 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 14:34:11 +0200 Subject: [PATCH 111/223] *ProcessorImplementation ===> *Processor, add suppression of SA1413 to AssemblyInfo.cs --- .../Processing/Processors/Filters/FilterProcessor.cs | 2 +- ...sorImplementation.cs => FilterProcessor{TPixel}.cs} | 4 ++-- .../Processors/Filters/GrayscaleBt709Processor.cs | 2 +- .../Processors/Filters/LomographProcessor.cs | 2 +- ...Implementation.cs => LomographProcessor{TPixel}.cs} | 4 ++-- .../Processing/Processors/Filters/PolaroidProcessor.cs | 2 +- ...rImplementation.cs => PolaroidProcessor{TPixel}.cs} | 4 ++-- .../Processors/Transforms/Resize/ResizeProcessor.cs | 2 +- ...sorImplementation.cs => ResizeProcessor{TPixel}.cs} | 4 ++-- src/ImageSharp/Properties/AssemblyInfo.cs | 10 +++++++++- .../ImageSharp.Tests/Processing/Transforms/PadTest.cs | 2 +- 11 files changed, 23 insertions(+), 15 deletions(-) rename src/ImageSharp/Processing/Processors/Filters/{FilterProcessorImplementation.cs => FilterProcessor{TPixel}.cs} (92%) rename src/ImageSharp/Processing/Processors/Filters/{LomographProcessorImplementation.cs => LomographProcessor{TPixel}.cs} (83%) rename src/ImageSharp/Processing/Processors/Filters/{PolaroidProcessorImplementation.cs => PolaroidProcessor{TPixel}.cs} (86%) rename src/ImageSharp/Processing/Processors/Transforms/Resize/{ResizeProcessorImplementation.cs => ResizeProcessor{TPixel}.cs} (97%) diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs index 886b4e096..b615b7bc6 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters public virtual IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel { - return new FilterProcessorImplementation(this); + return new FilterProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs similarity index 92% rename from src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs rename to src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs index 8fea81564..ab60a4279 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessorImplementation.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs @@ -15,12 +15,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// Provides methods that accept a matrix to apply free-form filters to images. /// /// The pixel format. - internal class FilterProcessorImplementation : ImageProcessor + internal class FilterProcessor : ImageProcessor where TPixel : struct, IPixel { private readonly FilterProcessor definition; - public FilterProcessorImplementation(FilterProcessor definition) + public FilterProcessor(FilterProcessor definition) { this.definition = definition; } diff --git a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs index 038a2885b..7bbd91556 100644 --- a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters internal void ApplyToFrame(ImageFrame frame, Rectangle sourceRectangle, Configuration configuration) where TPixel : struct, IPixel { - var processorImpl = new FilterProcessorImplementation(new GrayscaleBt709Processor(1F)); + var processorImpl = new FilterProcessor(new GrayscaleBt709Processor(1F)); processorImpl.Apply(frame, sourceRectangle, configuration); } } diff --git a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs index 345d829ac..b102f4daf 100644 --- a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs @@ -17,6 +17,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters } public override IImageProcessor CreatePixelSpecificProcessor() => - new LomographProcessorImplementation(this); + new LomographProcessor(this); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs similarity index 83% rename from src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs rename to src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs index a922e7125..8ec4ec258 100644 --- a/src/ImageSharp/Processing/Processors/Filters/LomographProcessorImplementation.cs +++ b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs @@ -10,12 +10,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating an old Lomograph effect. /// - internal class LomographProcessorImplementation : FilterProcessorImplementation + internal class LomographProcessor : FilterProcessor where TPixel : struct, IPixel { private static readonly TPixel VeryDarkGreen = ColorBuilder.FromRGBA(0, 10, 0, 255); - public LomographProcessorImplementation(LomographProcessor definition) + public LomographProcessor(LomographProcessor definition) : base(definition) { } diff --git a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs index 0b272c339..341c02acf 100644 --- a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs @@ -18,6 +18,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// public override IImageProcessor CreatePixelSpecificProcessor() => - new PolaroidProcessorImplementation(this); + new PolaroidProcessor(this); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs similarity index 86% rename from src/ImageSharp/Processing/Processors/Filters/PolaroidProcessorImplementation.cs rename to src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs index ec3c5ed26..a73aa28de 100644 --- a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessorImplementation.cs +++ b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs @@ -10,13 +10,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating an old Polaroid effect. /// - internal class PolaroidProcessorImplementation : FilterProcessorImplementation + internal class PolaroidProcessor : FilterProcessor where TPixel : struct, IPixel { private static readonly TPixel VeryDarkOrange = ColorBuilder.FromRGB(102, 34, 0); private static readonly TPixel LightOrange = ColorBuilder.FromRGBA(255, 153, 102, 128); - public PolaroidProcessorImplementation(FilterProcessor definition) + public PolaroidProcessor(FilterProcessor definition) : base(definition) { } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 021451b5c..5710c4bd8 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel { - return new ResizeProcessorImplementation(this); + return new ResizeProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs similarity index 97% rename from src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs rename to src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index 36a054c54..cf99f28dd 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessorImplementation.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The original code has been adapted from . /// /// The pixel format. - internal class ResizeProcessorImplementation : TransformProcessorBase + internal class ResizeProcessor : TransformProcessorBase where TPixel : struct, IPixel { // The following fields are not immutable but are optionally created on demand. @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly ResizeProcessor parameterSource; - public ResizeProcessorImplementation(ResizeProcessor parameterSource) + public ResizeProcessor(ResizeProcessor parameterSource) { this.parameterSource = parameterSource; } diff --git a/src/ImageSharp/Properties/AssemblyInfo.cs b/src/ImageSharp/Properties/AssemblyInfo.cs index 7b8f933b0..f4459887f 100644 --- a/src/ImageSharp/Properties/AssemblyInfo.cs +++ b/src/ImageSharp/Properties/AssemblyInfo.cs @@ -1,6 +1,14 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. + using System.Runtime.CompilerServices; // Ensure the other projects can see the internal helpers -[assembly: InternalsVisibleTo("SixLabors.ImageSharp.Drawing")] \ No newline at end of file +[assembly: InternalsVisibleTo("SixLabors.ImageSharp.Drawing")] + +// Redundant suppressing of SA1413 for Rider. +[assembly: + System.Diagnostics.CodeAnalysis.SuppressMessage( + "StyleCop.CSharp.MaintainabilityRules", + "SA1413:UseTrailingCommasInMultiLineInitializers", + Justification = "Follows SixLabors.ruleset")] \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs index eca1a458b..82d768255 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms IResampler sampler = KnownResamplers.NearestNeighbor; this.operations.Pad(width, height); - ResizeProcessorImplementation resizeProcessor = this.Verify>(); + ResizeProcessor resizeProcessor = this.Verify>(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); From 513825b5276ab30b091c310247daaeb641afb3ce Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 17:02:46 +0200 Subject: [PATCH 112/223] validating tests for Convolution processors --- src/ImageSharp/Common/Helpers/Vector4Utils.cs | 2 +- .../Convolution/EdgeDetector2DProcessor.cs | 2 +- .../Basic1ParameterConvolutionTests.cs | 56 +++++++++++++++++++ .../Processors/Convolution/BoxBlurTest.cs | 44 ++------------- .../Processors/Convolution/DetectEdgesTest.cs | 19 ++++--- .../Convolution/GaussianBlurTest.cs | 35 ++---------- .../Convolution/GaussianSharpenTest.cs | 40 ++----------- tests/Images/External | 2 +- 8 files changed, 85 insertions(+), 115 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs diff --git a/src/ImageSharp/Common/Helpers/Vector4Utils.cs b/src/ImageSharp/Common/Helpers/Vector4Utils.cs index 5c122217d..a4e0921d0 100644 --- a/src/ImageSharp/Common/Helpers/Vector4Utils.cs +++ b/src/ImageSharp/Common/Helpers/Vector4Utils.cs @@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp } /// - /// Bulk variant of + /// Bulk variant of . /// /// The span of vectors /// The transformation matrix. diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs index c08a17661..b4ac89139 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution public DenseMatrix KernelY { get; } /// - public bool Grayscale { get; set; } + public bool Grayscale { get; } /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs new file mode 100644 index 000000000..1f939a281 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs @@ -0,0 +1,56 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.Primitives; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution +{ + [GroupOutput("Convolution")] + public abstract class Basic1ParameterConvolutionTests + { + private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.05F); + + public static readonly TheoryData Values = new TheoryData { 3, 5 }; + + public static readonly string[] InputImages = + { + TestImages.Bmp.Car, + TestImages.Png.CalliphoraPartial + }; + + [Theory] + [WithFileCollection(nameof(InputImages), nameof(Values), PixelTypes.Rgba32)] + public void OnFullImage(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + provider.Utility.TestGroupName = this.GetType().Name; + provider.RunValidatingProcessorTest( + x => this.Apply(x, value), + value, + ValidatorComparer); + } + + [Theory] + [WithFileCollection(nameof(InputImages), nameof(Values), PixelTypes.Rgba32)] + public void InBox(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + provider.Utility.TestGroupName = this.GetType().Name; + provider.RunRectangleConstrainedValidatingProcessorTest( + (x, rect) => this.Apply(x, value, rect), + value, + ValidatorComparer); + } + + protected abstract void Apply(IImageProcessingContext ctx, int value) + where TPixel : struct, IPixel; + + protected abstract void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) + where TPixel : struct, IPixel; + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs index 1f0d12cf7..923f9d616 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs @@ -1,51 +1,17 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - using SixLabors.Primitives; -using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { - public class BoxBlurTest : FileTestBase + [GroupOutput("Convolution")] + public class BoxBlurTest : Basic1ParameterConvolutionTests { - public static readonly TheoryData BoxBlurValues - = new TheoryData - { - 3, - 5 - }; - - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), DefaultPixelType)] - public void ImageShouldApplyBoxBlurFilter(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.BoxBlur(value)); - image.DebugSave(provider, value); - } - } - - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), DefaultPixelType)] - public void ImageShouldApplyBoxBlurFilterInBox(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image source = provider.GetImage()) - using (Image image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.BoxBlur(value, bounds)); - image.DebugSave(provider, value); + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.BoxBlur(value); - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } - } + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + ctx.BoxBlur(value, bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs index b6a7741b3..05524b20b 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs @@ -10,13 +10,16 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { - public class DetectEdgesTest : FileTestBase + [GroupOutput("Convolution")] + public class DetectEdgesTest { // I think our comparison is not accurate enough (nor can be) for RgbaVector. // The image pixels are identical according to BeyondCompare. private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.0456F); - public static readonly string[] CommonTestImages = { TestImages.Png.Bike }; + public static readonly string[] TestImages = { Tests.TestImages.Png.Bike }; + + public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; public static readonly TheoryData DetectEdgesFilters = new TheoryData { @@ -33,7 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution }; [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(TestImages), PixelTypes.Rgba32)] public void DetectEdges_WorksOnWrappedMemoryImage(TestImageProvider provider) where TPixel : struct, IPixel { @@ -49,8 +52,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution } [Theory] - [WithTestPatternImages(nameof(DetectEdgesFilters), 100, 100, DefaultPixelType)] - [WithFileCollection(nameof(CommonTestImages), nameof(DetectEdgesFilters), DefaultPixelType)] + [WithTestPatternImages(nameof(DetectEdgesFilters), 100, 100, PixelTypes.Rgba32)] + [WithFileCollection(nameof(TestImages), nameof(DetectEdgesFilters), PixelTypes.Rgba32)] public void DetectEdges_WorksWithAllFilters(TestImageProvider provider, EdgeDetectionOperators detector) where TPixel : struct, IPixel { @@ -63,7 +66,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution } [Theory] - [WithFileCollection(nameof(CommonTestImages), CommonNonDefaultPixelTypes)] + [WithFileCollection(nameof(TestImages), CommonNonDefaultPixelTypes)] public void DetectEdges_IsNotBoundToSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { @@ -76,7 +79,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution } [Theory] - [WithFile(TestImages.Gif.Giphy, DefaultPixelType)] + [WithFile(Tests.TestImages.Gif.Giphy, PixelTypes.Rgba32)] public void DetectEdges_IsAppliedToAllFrames(TestImageProvider provider) where TPixel : struct, IPixel { @@ -88,7 +91,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(TestImages), PixelTypes.Rgba32)] public void DetectEdges_InBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs index 6bd3b34bb..6307a1c51 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs @@ -10,37 +10,12 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { - public class GaussianBlurTest : FileTestBase + [GroupOutput("Convolution")] + public class GaussianBlurTest : Basic1ParameterConvolutionTests { - public static readonly TheoryData GaussianBlurValues = new TheoryData { 3, 5 }; + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianBlur(value); - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), DefaultPixelType)] - public void ImageShouldApplyGaussianBlurFilter(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.GaussianBlur(value)); - image.DebugSave(provider, value); - } - } - - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), DefaultPixelType)] - public void ImageShouldApplyGaussianBlurFilterInBox(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image source = provider.GetImage()) - using (Image image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.GaussianBlur(value, bounds)); - image.DebugSave(provider, value); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } - } + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + ctx.GaussianBlur(value, bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs index 8eb1f85eb..29a1643b0 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs @@ -9,42 +9,12 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { - public class GaussianSharpenTest : FileTestBase + [GroupOutput("Convolution")] + public class GaussianSharpenTest : Basic1ParameterConvolutionTests { - public static readonly TheoryData GaussianSharpenValues - = new TheoryData - { - 3, - 5 - }; + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianSharpen(value); - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), DefaultPixelType)] - public void ImageShouldApplyGaussianSharpenFilter(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.GaussianSharpen(value)); - image.DebugSave(provider, value); - } - } - - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), DefaultPixelType)] - public void ImageShouldApplyGaussianSharpenFilterInBox(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image source = provider.GetImage()) - using (var image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.GaussianSharpen(value, bounds)); - image.DebugSave(provider, value); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } - } + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + ctx.GaussianSharpen(value, bounds); } } \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index 1ca515499..2a3247c6d 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 1ca515499663e8b0b7c924a49b8d212f7447bdb0 +Subproject commit 2a3247c6da18b8a96cc71e1f2862ac03f2a42315 From fe2bad29de7d543bcb85ac03952a2b4b50acd783 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 17:05:48 +0200 Subject: [PATCH 113/223] validating tests for Convolution processors --- src/ImageSharp/Common/Helpers/Vector4Utils.cs | 2 +- .../Convolution/EdgeDetector2DProcessor.cs | 2 +- .../Basic1ParameterConvolutionTests.cs | 56 +++++++++++++++++++ .../Processors/Convolution/BoxBlurTest.cs | 44 ++------------- .../Processors/Convolution/DetectEdgesTest.cs | 19 ++++--- .../Convolution/GaussianBlurTest.cs | 35 ++---------- .../Convolution/GaussianSharpenTest.cs | 40 ++----------- tests/Images/External | 2 +- 8 files changed, 85 insertions(+), 115 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs diff --git a/src/ImageSharp/Common/Helpers/Vector4Utils.cs b/src/ImageSharp/Common/Helpers/Vector4Utils.cs index 5c122217d..a4e0921d0 100644 --- a/src/ImageSharp/Common/Helpers/Vector4Utils.cs +++ b/src/ImageSharp/Common/Helpers/Vector4Utils.cs @@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp } /// - /// Bulk variant of + /// Bulk variant of . /// /// The span of vectors /// The transformation matrix. diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs index d2e9630dc..83746952c 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution public DenseMatrix KernelY { get; } /// - public bool Grayscale { get; set; } + public bool Grayscale { get; } /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs new file mode 100644 index 000000000..1f939a281 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs @@ -0,0 +1,56 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.Primitives; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution +{ + [GroupOutput("Convolution")] + public abstract class Basic1ParameterConvolutionTests + { + private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.05F); + + public static readonly TheoryData Values = new TheoryData { 3, 5 }; + + public static readonly string[] InputImages = + { + TestImages.Bmp.Car, + TestImages.Png.CalliphoraPartial + }; + + [Theory] + [WithFileCollection(nameof(InputImages), nameof(Values), PixelTypes.Rgba32)] + public void OnFullImage(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + provider.Utility.TestGroupName = this.GetType().Name; + provider.RunValidatingProcessorTest( + x => this.Apply(x, value), + value, + ValidatorComparer); + } + + [Theory] + [WithFileCollection(nameof(InputImages), nameof(Values), PixelTypes.Rgba32)] + public void InBox(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + provider.Utility.TestGroupName = this.GetType().Name; + provider.RunRectangleConstrainedValidatingProcessorTest( + (x, rect) => this.Apply(x, value, rect), + value, + ValidatorComparer); + } + + protected abstract void Apply(IImageProcessingContext ctx, int value) + where TPixel : struct, IPixel; + + protected abstract void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) + where TPixel : struct, IPixel; + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs index 1f0d12cf7..923f9d616 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs @@ -1,51 +1,17 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - using SixLabors.Primitives; -using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { - public class BoxBlurTest : FileTestBase + [GroupOutput("Convolution")] + public class BoxBlurTest : Basic1ParameterConvolutionTests { - public static readonly TheoryData BoxBlurValues - = new TheoryData - { - 3, - 5 - }; - - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), DefaultPixelType)] - public void ImageShouldApplyBoxBlurFilter(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.BoxBlur(value)); - image.DebugSave(provider, value); - } - } - - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), DefaultPixelType)] - public void ImageShouldApplyBoxBlurFilterInBox(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image source = provider.GetImage()) - using (Image image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.BoxBlur(value, bounds)); - image.DebugSave(provider, value); + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.BoxBlur(value); - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } - } + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + ctx.BoxBlur(value, bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs index b6a7741b3..05524b20b 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs @@ -10,13 +10,16 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { - public class DetectEdgesTest : FileTestBase + [GroupOutput("Convolution")] + public class DetectEdgesTest { // I think our comparison is not accurate enough (nor can be) for RgbaVector. // The image pixels are identical according to BeyondCompare. private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.0456F); - public static readonly string[] CommonTestImages = { TestImages.Png.Bike }; + public static readonly string[] TestImages = { Tests.TestImages.Png.Bike }; + + public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; public static readonly TheoryData DetectEdgesFilters = new TheoryData { @@ -33,7 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution }; [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(TestImages), PixelTypes.Rgba32)] public void DetectEdges_WorksOnWrappedMemoryImage(TestImageProvider provider) where TPixel : struct, IPixel { @@ -49,8 +52,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution } [Theory] - [WithTestPatternImages(nameof(DetectEdgesFilters), 100, 100, DefaultPixelType)] - [WithFileCollection(nameof(CommonTestImages), nameof(DetectEdgesFilters), DefaultPixelType)] + [WithTestPatternImages(nameof(DetectEdgesFilters), 100, 100, PixelTypes.Rgba32)] + [WithFileCollection(nameof(TestImages), nameof(DetectEdgesFilters), PixelTypes.Rgba32)] public void DetectEdges_WorksWithAllFilters(TestImageProvider provider, EdgeDetectionOperators detector) where TPixel : struct, IPixel { @@ -63,7 +66,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution } [Theory] - [WithFileCollection(nameof(CommonTestImages), CommonNonDefaultPixelTypes)] + [WithFileCollection(nameof(TestImages), CommonNonDefaultPixelTypes)] public void DetectEdges_IsNotBoundToSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { @@ -76,7 +79,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution } [Theory] - [WithFile(TestImages.Gif.Giphy, DefaultPixelType)] + [WithFile(Tests.TestImages.Gif.Giphy, PixelTypes.Rgba32)] public void DetectEdges_IsAppliedToAllFrames(TestImageProvider provider) where TPixel : struct, IPixel { @@ -88,7 +91,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(TestImages), PixelTypes.Rgba32)] public void DetectEdges_InBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs index 6bd3b34bb..6307a1c51 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs @@ -10,37 +10,12 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { - public class GaussianBlurTest : FileTestBase + [GroupOutput("Convolution")] + public class GaussianBlurTest : Basic1ParameterConvolutionTests { - public static readonly TheoryData GaussianBlurValues = new TheoryData { 3, 5 }; + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianBlur(value); - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), DefaultPixelType)] - public void ImageShouldApplyGaussianBlurFilter(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.GaussianBlur(value)); - image.DebugSave(provider, value); - } - } - - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), DefaultPixelType)] - public void ImageShouldApplyGaussianBlurFilterInBox(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image source = provider.GetImage()) - using (Image image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.GaussianBlur(value, bounds)); - image.DebugSave(provider, value); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } - } + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + ctx.GaussianBlur(value, bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs index 8eb1f85eb..29a1643b0 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs @@ -9,42 +9,12 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution { - public class GaussianSharpenTest : FileTestBase + [GroupOutput("Convolution")] + public class GaussianSharpenTest : Basic1ParameterConvolutionTests { - public static readonly TheoryData GaussianSharpenValues - = new TheoryData - { - 3, - 5 - }; + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianSharpen(value); - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), DefaultPixelType)] - public void ImageShouldApplyGaussianSharpenFilter(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.GaussianSharpen(value)); - image.DebugSave(provider, value); - } - } - - [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), DefaultPixelType)] - public void ImageShouldApplyGaussianSharpenFilterInBox(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image source = provider.GetImage()) - using (var image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.GaussianSharpen(value, bounds)); - image.DebugSave(provider, value); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } - } + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + ctx.GaussianSharpen(value, bounds); } } \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index 1ca515499..2a3247c6d 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 1ca515499663e8b0b7c924a49b8d212f7447bdb0 +Subproject commit 2a3247c6da18b8a96cc71e1f2862ac03f2a42315 From c1d595e0060fbd5e1905827043c7b235460447d5 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 17:09:25 +0200 Subject: [PATCH 114/223] mark FileTestBase obsolete --- tests/ImageSharp.Tests/FileTestBase.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ImageSharp.Tests/FileTestBase.cs b/tests/ImageSharp.Tests/FileTestBase.cs index efd6c3b40..a056bc474 100644 --- a/tests/ImageSharp.Tests/FileTestBase.cs +++ b/tests/ImageSharp.Tests/FileTestBase.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Collections.Generic; namespace SixLabors.ImageSharp.Tests @@ -8,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests /// /// The test base class for reading and writing to files. /// + [Obsolete("See: https://github.com/SixLabors/ImageSharp/issues/868")] public abstract class FileTestBase { /// From 226b5f53dd3f7a873423b0d6e78359b4c316e6be Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 17:30:35 +0200 Subject: [PATCH 115/223] improve DitherTests CQ --- .../Processors/Dithering/DitherTests.cs | 133 +++++++++--------- 1 file changed, 68 insertions(+), 65 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs index 9774cb50c..fbe7bb182 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs @@ -2,128 +2,131 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Dithering; using SixLabors.ImageSharp.Processing.Processors.Dithering; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.Primitives; + using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { - public class DitherTests : FileTestBase + public class DitherTests { - public static readonly string[] CommonTestImages = - { - TestImages.Png.CalliphoraPartial, TestImages.Png.Bike - }; - - public static readonly TheoryData OrderedDitherers = new TheoryData - { - { "Bayer8x8", KnownDitherers.BayerDither8x8 }, - { "Bayer4x4", KnownDitherers.BayerDither4x4 }, - { "Ordered3x3", KnownDitherers.OrderedDither3x3 }, - { "Bayer2x2", KnownDitherers.BayerDither2x2 } - }; - - public static readonly TheoryData ErrorDiffusers = new TheoryData - { - { "Atkinson", KnownDiffusers.Atkinson }, - { "Burks", KnownDiffusers.Burks }, - { "FloydSteinberg", KnownDiffusers.FloydSteinberg }, - { "JarvisJudiceNinke", KnownDiffusers.JarvisJudiceNinke }, - { "Sierra2", KnownDiffusers.Sierra2 }, - { "Sierra3", KnownDiffusers.Sierra3 }, - { "SierraLite", KnownDiffusers.SierraLite }, - { "StevensonArce", KnownDiffusers.StevensonArce }, - { "Stucki", KnownDiffusers.Stucki }, - }; - + public const PixelTypes CommonNonDefaultPixelTypes = + PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24 | PixelTypes.RgbaVector; + + public static readonly string[] CommonTestImages = { TestImages.Png.CalliphoraPartial, TestImages.Png.Bike }; + + public static readonly TheoryData ErrorDiffusers = new TheoryData + { + KnownDiffusers.Atkinson, + KnownDiffusers.Burks, + KnownDiffusers.FloydSteinberg, + KnownDiffusers.JarvisJudiceNinke, + KnownDiffusers.Sierra2, + KnownDiffusers.Sierra3, + KnownDiffusers.SierraLite, + KnownDiffusers.StevensonArce, + KnownDiffusers.Stucki, + }; + + public static readonly TheoryData OrderedDitherers = new TheoryData + { + KnownDitherers.BayerDither8x8, + KnownDitherers.BayerDither4x4, + KnownDitherers.OrderedDither3x3, + KnownDitherers.BayerDither2x2 + }; + private static IOrderedDither DefaultDitherer => KnownDitherers.BayerDither4x4; private static IErrorDiffuser DefaultErrorDiffuser => KnownDiffusers.Atkinson; [Theory] - [WithFileCollection(nameof(CommonTestImages), nameof(OrderedDitherers), DefaultPixelType)] - [WithTestPatternImages(nameof(OrderedDitherers), 100, 100, DefaultPixelType)] - public void DitherFilter_WorksWithAllDitherers(TestImageProvider provider, string name, IOrderedDither ditherer) + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] + public void ApplyDiffusionFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) + using (Image source = provider.GetImage()) + using (Image image = source.Clone()) { - image.Mutate(x => x.Dither(ditherer)); - image.DebugSave(provider, name); + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Mutate(x => x.Diffuse(DefaultErrorDiffuser, .5F, bounds)); + image.DebugSave(provider); + + ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); } } [Theory] - [WithFileCollection(nameof(CommonTestImages), nameof(ErrorDiffusers), DefaultPixelType)] - [WithTestPatternImages(nameof(ErrorDiffusers), 100, 100, DefaultPixelType)] - public void DiffusionFilter_WorksWithAllErrorDiffusers(TestImageProvider provider, string name, IErrorDiffuser diffuser) + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] + public void ApplyDitherFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) + using (Image source = provider.GetImage()) + using (Image image = source.Clone()) { - image.Mutate(x => x.Diffuse(diffuser, .5F)); - image.DebugSave(provider, name); + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Mutate(x => x.Dither(DefaultDitherer, bounds)); + image.DebugSave(provider); + + ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); } } [Theory] [WithFile(TestImages.Png.Filter0, CommonNonDefaultPixelTypes)] - public void DitherFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) + public void DiffusionFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { - image.Mutate(x => x.Dither(DefaultDitherer)); + image.Mutate(x => x.Diffuse(DefaultErrorDiffuser, 0.5f)); image.DebugSave(provider); } } [Theory] - [WithFile(TestImages.Png.Filter0, CommonNonDefaultPixelTypes)] - public void DiffusionFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) + [WithFileCollection(nameof(CommonTestImages), nameof(ErrorDiffusers), PixelTypes.Rgba32)] + public void DiffusionFilter_WorksWithAllErrorDiffusers( + TestImageProvider provider, + IErrorDiffuser diffuser) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { - image.Mutate(x => x.Diffuse(DefaultErrorDiffuser, 0.5f)); - image.DebugSave(provider); + image.Mutate(x => x.Diffuse(diffuser, .5F)); + image.DebugSave(provider, diffuser.GetType().Name); } } [Theory] - [WithFile(TestImages.Png.CalliphoraPartial, DefaultPixelType)] - public void ApplyDitherFilterInBox(TestImageProvider provider) + [WithFile(TestImages.Png.Filter0, CommonNonDefaultPixelTypes)] + public void DitherFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image source = provider.GetImage()) - using (Image image = source.Clone()) + using (Image image = provider.GetImage()) { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.Dither(DefaultDitherer, bounds)); + image.Mutate(x => x.Dither(DefaultDitherer)); image.DebugSave(provider); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); } } [Theory] - [WithFile(TestImages.Png.CalliphoraPartial, DefaultPixelType)] - public void ApplyDiffusionFilterInBox(TestImageProvider provider) + [WithFileCollection(nameof(CommonTestImages), nameof(OrderedDitherers), PixelTypes.Rgba32)] + public void DitherFilter_WorksWithAllDitherers( + TestImageProvider provider, + IOrderedDither ditherer) where TPixel : struct, IPixel { - using (Image source = provider.GetImage()) - using (Image image = source.Clone()) + using (Image image = provider.GetImage()) { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.Diffuse(DefaultErrorDiffuser, .5F, bounds)); - image.DebugSave(provider); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); + image.Mutate(x => x.Dither(ditherer)); + image.DebugSave(provider, ditherer.GetType().Name); } } } From 80a54484d63353ad80073863483fcb9cb85e1eff Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 17:49:28 +0200 Subject: [PATCH 116/223] extended diffusion + dither tests --- .../Processors/Dithering/DitherTests.cs | 66 +++++++------------ tests/Images/External | 2 +- 2 files changed, 26 insertions(+), 42 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs index fbe7bb182..368feefb9 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Dithering; using SixLabors.ImageSharp.Processing.Processors.Dithering; @@ -39,6 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization KnownDitherers.OrderedDither3x3, KnownDitherers.BayerDither2x2 }; + private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.05f); private static IOrderedDither DefaultDitherer => KnownDitherers.BayerDither4x4; @@ -49,16 +51,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization public void ApplyDiffusionFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image source = provider.GetImage()) - using (Image image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.Diffuse(DefaultErrorDiffuser, .5F, bounds)); - image.DebugSave(provider); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } + provider.RunRectangleConstrainedValidatingProcessorTest( + (x, rect) => x.Diffuse(DefaultErrorDiffuser, .5F, rect), + comparer: ValidatorComparer); } [Theory] @@ -66,28 +61,19 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization public void ApplyDitherFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image source = provider.GetImage()) - using (Image image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.Dither(DefaultDitherer, bounds)); - image.DebugSave(provider); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } + provider.RunRectangleConstrainedValidatingProcessorTest( + (x, rect) => x.Dither(DefaultDitherer, rect), + comparer: ValidatorComparer); } [Theory] [WithFile(TestImages.Png.Filter0, CommonNonDefaultPixelTypes)] - public void DiffusionFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) + public void DiffusionFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Diffuse(DefaultErrorDiffuser, 0.5f)); - image.DebugSave(provider); - } + // Increased tolerance because of compatibility issues on .NET 4.6.2: + var comparer = ImageComparer.TolerantPercentage(1f); + provider.RunValidatingProcessorTest(x => x.Diffuse(DefaultErrorDiffuser, 0.5f), comparer: comparer); } [Theory] @@ -97,11 +83,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization IErrorDiffuser diffuser) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Diffuse(diffuser, .5F)); - image.DebugSave(provider, diffuser.GetType().Name); - } + provider.RunValidatingProcessorTest( + x => x.Diffuse(diffuser, 0.5f), + testOutputDetails: diffuser.GetType().Name, + comparer: ValidatorComparer, + appendPixelTypeToFileName: false); } [Theory] @@ -109,11 +95,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization public void DitherFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Dither(DefaultDitherer)); - image.DebugSave(provider); - } + provider.RunValidatingProcessorTest( + x => x.Dither(DefaultDitherer), + comparer: ValidatorComparer); } [Theory] @@ -123,11 +107,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization IOrderedDither ditherer) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Dither(ditherer)); - image.DebugSave(provider, ditherer.GetType().Name); - } + provider.RunValidatingProcessorTest( + x => x.Dither(ditherer), + testOutputDetails: ditherer.GetType().Name, + comparer: ValidatorComparer, + appendPixelTypeToFileName: false); } } } \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index 2a3247c6d..0c524009f 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 2a3247c6da18b8a96cc71e1f2862ac03f2a42315 +Subproject commit 0c524009f4d4b0edefddd944defdc408c3971536 From f70b13798124c19585d93522359a4462583e71cc Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sat, 4 May 2019 18:42:07 +0200 Subject: [PATCH 117/223] Add additional pixel conversion tests --- .../PixelFormats/Bgr565Tests.cs | 165 ++++++++++++++++++ .../PixelFormats/Bgra4444Tests.cs | 160 +++++++++++++++++ .../PixelFormats/Bgra5551Tests.cs | 75 +++++++- .../PixelFormats/Byte4Tests.cs | 148 +++++++++++++++- .../PixelFormats/Rgba1010102Tests.cs | 128 ++++++++++++++ 5 files changed, 672 insertions(+), 4 deletions(-) diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs index 4419fe898..03e905466 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -9,6 +10,36 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class Bgr565Tests { + /// + /// Tests the equality operators for equality. + /// + [Fact] + public void AreEqual() + { + var color1 = new Bgr565(0.0f, 0.0f, 0.0f); + var color2 = new Bgr565(new Vector3(0.0f)); + var color3 = new Bgr565(new Vector3(1.0f, 0.0f, 1.0f)); + var color4 = new Bgr565(1.0f, 0.0f, 1.0f); + + Assert.Equal(color1, color2); + Assert.Equal(color3, color4); + } + + /// + /// Tests the equality operators for inequality. + /// + [Fact] + public void AreNotEqual() + { + var color1 = new Bgr565(0.0f, 0.0f, 0.0f); + var color2 = new Bgr565(new Vector3(1.0f)); + var color3 = new Bgr565(new Vector3(1.0f, 0.0f, 0.0f)); + var color4 = new Bgr565(1.0f, 1.0f, 0.0f); + + Assert.NotEqual(color1, color2); + Assert.NotEqual(color3, color4); + } + [Fact] public void Bgr565_PackedValue() { @@ -77,6 +108,140 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, bgr.PackedValue); } + [Fact] + public void Bgr565_FromArgb32() + { + // arrange + var bgr1 = default(Bgr565); + var bgr2 = default(Bgr565); + ushort expected1 = ushort.MaxValue; + ushort expected2 = ushort.MaxValue; + + // act + bgr1.FromArgb32(new Argb32(1.0f, 1.0f, 1.0f, 1.0f)); + bgr2.FromArgb32(new Argb32(1.0f, 1.0f, 1.0f, 0.0f)); + + // assert + Assert.Equal(expected1, bgr1.PackedValue); + Assert.Equal(expected2, bgr2.PackedValue); + } + + [Fact] + public void Bgr565_FromRgba32() + { + // arrange + var bgr1 = default(Bgr565); + var bgr2 = default(Bgr565); + ushort expected1 = ushort.MaxValue; + ushort expected2 = ushort.MaxValue; + + // act + bgr1.FromRgba32(new Rgba32(1.0f, 1.0f, 1.0f, 1.0f)); + bgr2.FromRgba32(new Rgba32(1.0f, 1.0f, 1.0f, 0.0f)); + + // assert + Assert.Equal(expected1, bgr1.PackedValue); + Assert.Equal(expected2, bgr2.PackedValue); + } + + [Fact] + public void Bgr565_ToRgba32() + { + // arrange + var bgra = new Bgr565(Vector3.One); + var expected = new Rgba32(Vector4.One); + var actual = default(Rgba32); + + // act + bgra.ToRgba32(ref actual); + + Assert.Equal(expected, actual); + } + + [Fact] + public void Bgra565_FromRgb48() + { + // arrange + var bgr = default(Bgr565); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgr.FromRgb48(new Rgb48(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgr.PackedValue); + } + + [Fact] + public void Bgra565_FromRgba64() + { + // arrange + var bgr = default(Bgr565); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgr.FromRgba64(new Rgba64(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgr.PackedValue); + } + + [Fact] + public void Bgr565_FromBgr24() + { + // arrange + var bgr = default(Bgr565); + ushort expected = ushort.MaxValue; + + // act + bgr.FromBgr24(new Bgr24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expected, bgr.PackedValue); + } + + [Fact] + public void Bgr565_FromRgb24() + { + // arrange + var bgr = default(Bgr565); + ushort expected = ushort.MaxValue; + + // act + bgr.FromRgb24(new Rgb24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expected, bgr.PackedValue); + } + + [Fact] + public void Bgr565_FromGrey8() + { + // arrange + var bgr = default(Bgr565); + ushort expected = ushort.MaxValue; + + // act + bgr.FromGray8(new Gray8(byte.MaxValue)); + + // assert + Assert.Equal(expected, bgr.PackedValue); + } + + [Fact] + public void Bgr565_FromGrey16() + { + // arrange + var bgr = default(Bgr565); + ushort expected = ushort.MaxValue; + + // act + bgr.FromGray16(new Gray16(ushort.MaxValue)); + + // assert + Assert.Equal(expected, bgr.PackedValue); + } + [Fact] public void Bgr565_Clamping() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs index b6019016c..d4c998625 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs @@ -9,6 +9,36 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class Bgra4444Tests { + /// + /// Tests the equality operators for equality. + /// + [Fact] + public void AreEqual() + { + var color1 = new Bgra4444(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new Bgra4444(new Vector4(0.0f)); + var color3 = new Bgra4444(new Vector4(1.0f, 0.0f, 1.0f, 1.0f)); + var color4 = new Bgra4444(1.0f, 0.0f, 1.0f, 1.0f); + + Assert.Equal(color1, color2); + Assert.Equal(color3, color4); + } + + /// + /// Tests the equality operators for inequality. + /// + [Fact] + public void AreNotEqual() + { + var color1 = new Bgra4444(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new Bgra4444(new Vector4(1.0f)); + var color3 = new Bgra4444(new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + var color4 = new Bgra4444(1.0f, 1.0f, 0.0f, 1.0f); + + Assert.NotEqual(color1, color2); + Assert.NotEqual(color3, color4); + } + [Fact] public void Bgra4444_PackedValue() { @@ -48,6 +78,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(1, actual.W); } + [Fact] + public void Bgra4444_ToRgba32() + { + // arrange + var bgra = new Bgra4444(Vector4.One); + var expected = new Rgba32(Vector4.One); + var actual = default(Rgba32); + + // act + bgra.ToRgba32(ref actual); + + Assert.Equal(expected, actual); + } + [Fact] public void Bgra4444_FromScaledVector4() { @@ -78,6 +122,122 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, bgra.PackedValue); } + [Fact] + public void Bgra4444_FromArgb32() + { + // arrange + var bgra = default(Bgra4444); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromArgb32(new Argb32(255, 255, 255, 255)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra4444_FromRgba32() + { + // arrange + var bgra1 = default(Bgra4444); + var bgra2 = default(Bgra4444); + ushort expectedPackedValue1 = ushort.MaxValue; + ushort expectedPackedValue2 = 0xFF0F; + + // act + bgra1.FromRgba32(new Rgba32(255, 255, 255, 255)); + bgra2.FromRgba32(new Rgba32(255, 0, 255, 255)); + + // assert + Assert.Equal(expectedPackedValue1, bgra1.PackedValue); + Assert.Equal(expectedPackedValue2, bgra2.PackedValue); + } + + [Fact] + public void Bgra4444_FromRgb48() + { + // arrange + var bgra = default(Bgra4444); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromRgb48(new Rgb48(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra4444_FromRgba64() + { + // arrange + var bgra = default(Bgra4444); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromRgba64(new Rgba64(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra4444_FromGrey16() + { + // arrange + var bgra = default(Bgra4444); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromGray16(new Gray16(ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra4444_FromGrey8() + { + // arrange + var bgra = default(Bgra4444); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromGray8(new Gray8(byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra4444_FromBgr24() + { + // arrange + var bgra = default(Bgra4444); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromBgr24(new Bgr24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + + [Fact] + public void Bgra4444_FromRgb24() + { + // arrange + var bgra = default(Bgra4444); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromRgb24(new Rgb24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + [Fact] public void Bgra4444_Clamping() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs index f5abca59a..7751d7ab9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Numerics; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -10,6 +9,36 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class Bgra5551Tests { + /// + /// Tests the equality operators for equality. + /// + [Fact] + public void AreEqual() + { + var color1 = new Bgra5551(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new Bgra5551(new Vector4(0.0f)); + var color3 = new Bgra5551(new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + var color4 = new Bgra5551(1.0f, 0.0f, 0.0f, 1.0f); + + Assert.Equal(color1, color2); + Assert.Equal(color3, color4); + } + + /// + /// Tests the equality operators for inequality. + /// + [Fact] + public void AreNotEqual() + { + var color1 = new Bgra5551(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new Bgra5551(new Vector4(1.0f)); + var color3 = new Bgra5551(new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + var color4 = new Bgra5551(1.0f, 1.0f, 0.0f, 1.0f); + + Assert.NotEqual(color1, color2); + Assert.NotEqual(color3, color4); + } + [Fact] public void Bgra5551_PackedValue() { @@ -54,6 +83,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(1, actual.W); } + [Fact] + public void Bgra5551_ToRgba32() + { + // arrange + var bgra = new Bgra5551(Vector4.One); + var expected = new Rgba32(Vector4.One); + var actual = default(Rgba32); + + // act + bgra.ToRgba32(ref actual); + + Assert.Equal(expected, actual); + } + [Fact] public void Bgra5551_FromScaledVector4() { @@ -70,6 +113,22 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual); } + [Fact] + public void Bgra5551_FromBgra5551() + { + // arrange + var bgra = default(Bgra5551); + var actual = default(Bgra5551); + var expected = new Bgra5551(1.0f, 0.0f, 1.0f, 1.0f); + + // act + bgra.FromBgra5551(expected); + actual.FromBgra5551(bgra); + + // assert + Assert.Equal(expected, actual); + } + [Fact] public void Bgra5551_FromRgba32() { @@ -120,6 +179,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expectedPackedValue, bgra.PackedValue); } + [Fact] + public void Bgra5551_FromRgb48() + { + // arrange + var bgra = default(Bgra5551); + ushort expectedPackedValue = ushort.MaxValue; + + // act + bgra.FromRgb48(new Rgb48(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, bgra.PackedValue); + } + [Fact] public void Bgra5551_FromRgba64() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs index 9174a6abd..ce9e56317 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs @@ -9,6 +9,36 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class Byte4Tests { + /// + /// Tests the equality operators for equality. + /// + [Fact] + public void AreEqual() + { + var color1 = new Byte4(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new Byte4(new Vector4(0.0f)); + var color3 = new Byte4(new Vector4(1.0f, 0.0f, 1.0f, 1.0f)); + var color4 = new Byte4(1.0f, 0.0f, 1.0f, 1.0f); + + Assert.Equal(color1, color2); + Assert.Equal(color3, color4); + } + + /// + /// Tests the equality operators for inequality. + /// + [Fact] + public void AreNotEqual() + { + var color1 = new Byte4(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new Byte4(new Vector4(1.0f)); + var color3 = new Byte4(new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + var color4 = new Byte4(1.0f, 1.0f, 0.0f, 1.0f); + + Assert.NotEqual(color1, color2); + Assert.NotEqual(color3, color4); + } + [Fact] public void Byte4_PackedValue() { @@ -61,18 +91,130 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual); } + [Fact] + public void Byte4_FromArgb32() + { + // arrange + var byte4 = default(Byte4); + uint expectedPackedValue = uint.MaxValue; + + // act + byte4.FromArgb32(new Argb32(255, 255, 255, 255)); + + // assert + Assert.Equal(expectedPackedValue, byte4.PackedValue); + } + + [Fact] + public void Byte4_FromBgr24() + { + // arrange + var byte4 = default(Byte4); + uint expectedPackedValue = uint.MaxValue; + + // act + byte4.FromBgr24(new Bgr24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, byte4.PackedValue); + } + + [Fact] + public void Byte4_FromGrey8() + { + // arrange + var byte4 = default(Byte4); + uint expectedPackedValue = uint.MaxValue; + + // act + byte4.FromGray8(new Gray8(byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, byte4.PackedValue); + } + + [Fact] + public void Byte4_FromGrey16() + { + // arrange + var byte4 = default(Byte4); + uint expectedPackedValue = uint.MaxValue; + + // act + byte4.FromGray16(new Gray16(ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, byte4.PackedValue); + } + + [Fact] + public void Byte4_FromRgb24() + { + // arrange + var byte4 = default(Byte4); + uint expectedPackedValue = uint.MaxValue; + + // act + byte4.FromRgb24(new Rgb24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, byte4.PackedValue); + } + [Fact] public void Byte4_FromBgra5551() { // arrange - var rgb = default(Byte4); + var byte4 = default(Byte4); uint expected = 0xFFFFFFFF; // act - rgb.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + byte4.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, byte4.PackedValue); + } + + [Fact] + public void Byte4_FromRgba32() + { + // arrange + var byte4 = default(Byte4); + uint expectedPackedValue1 = uint.MaxValue; + + // act + byte4.FromRgba32(new Rgba32(255, 255, 255, 255)); + + // assert + Assert.Equal(expectedPackedValue1, byte4.PackedValue); + } + + [Fact] + public void Byte4_FromRgb48() + { + // arrange + var byte4 = default(Byte4); + uint expectedPackedValue = uint.MaxValue; + + // act + byte4.FromRgb48(new Rgb48(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, byte4.PackedValue); + } + + [Fact] + public void Byte4_FromRgba64() + { + // arrange + var byte4 = default(Byte4); + uint expectedPackedValue = uint.MaxValue; + + // act + byte4.FromRgba64(new Rgba64(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); // assert - Assert.Equal(expected, rgb.PackedValue); + Assert.Equal(expectedPackedValue, byte4.PackedValue); } [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs index 0dbed2d2c..19a5d4b22 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs @@ -9,6 +9,36 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class Rgba1010102Tests { + /// + /// Tests the equality operators for equality. + /// + [Fact] + public void AreEqual() + { + var color1 = new Rgba1010102(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new Rgba1010102(new Vector4(0.0f)); + var color3 = new Rgba1010102(new Vector4(1.0f, 0.0f, 1.0f, 1.0f)); + var color4 = new Rgba1010102(1.0f, 0.0f, 1.0f, 1.0f); + + Assert.Equal(color1, color2); + Assert.Equal(color3, color4); + } + + /// + /// Tests the equality operators for inequality. + /// + [Fact] + public void AreNotEqual() + { + var color1 = new Rgba1010102(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new Rgba1010102(new Vector4(1.0f)); + var color3 = new Rgba1010102(new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + var color4 = new Rgba1010102(1.0f, 1.0f, 0.0f, 1.0f); + + Assert.NotEqual(color1, color2); + Assert.NotEqual(color3, color4); + } + [Fact] public void Rgba1010102_PackedValue() { @@ -78,6 +108,104 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, rgba.PackedValue); } + [Fact] + public void Rgba1010102_FromArgb32() + { + // arrange + var rgba = default(Rgba1010102); + uint expectedPackedValue = uint.MaxValue; + + // act + rgba.FromArgb32(new Argb32(255, 255, 255, 255)); + + // assert + Assert.Equal(expectedPackedValue, rgba.PackedValue); + } + + [Fact] + public void Rgba1010102_FromBgr24() + { + // arrange + var rgba = default(Rgba1010102); + uint expectedPackedValue = uint.MaxValue; + + // act + rgba.FromBgr24(new Bgr24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, rgba.PackedValue); + } + + [Fact] + public void Rgba1010102_FromGrey8() + { + // arrange + var rgba = default(Rgba1010102); + uint expectedPackedValue = uint.MaxValue; + + // act + rgba.FromGray8(new Gray8(byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, rgba.PackedValue); + } + + [Fact] + public void Rgba1010102_FromGrey16() + { + // arrange + var rgba = default(Rgba1010102); + uint expectedPackedValue = uint.MaxValue; + + // act + rgba.FromGray16(new Gray16(ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, rgba.PackedValue); + } + + [Fact] + public void Rgba1010102_FromRgb24() + { + // arrange + var rgba = default(Rgba1010102); + uint expectedPackedValue = uint.MaxValue; + + // act + rgba.FromRgb24(new Rgb24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, rgba.PackedValue); + } + + [Fact] + public void Rgba1010102_FromRgb48() + { + // arrange + var rgba = default(Rgba1010102); + uint expectedPackedValue = uint.MaxValue; + + // act + rgba.FromRgb48(new Rgb48(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, rgba.PackedValue); + } + + [Fact] + public void Rgba1010102_FromRgba64() + { + // arrange + var rgba = default(Rgba1010102); + uint expectedPackedValue = uint.MaxValue; + + // act + rgba.FromRgba64(new Rgba64(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expectedPackedValue, rgba.PackedValue); + } + [Fact] public void Rgba1010102_Clamping() { From 6b9703786c482550999ede0a334d680f55252e0d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 19:05:08 +0200 Subject: [PATCH 118/223] validating tests for Effects --- .../Processors/Effects/BackgroundColorTest.cs | 35 ++++------ .../Processors/Effects/OilPaintTest.cs | 42 +++++------ .../Processors/Effects/PixelateTest.cs | 70 +++---------------- tests/Images/External | 2 +- 4 files changed, 47 insertions(+), 102 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs index 792c7b080..d7f77c956 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs @@ -10,35 +10,30 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects { - public class BackgroundColorTest : FileTestBase + [GroupOutput("Effects")] + public class BackgroundColorTest { + public static readonly string[] InputImages = + { + TestImages.Png.Splash, + TestImages.Png.Ducky + }; + [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] - public void ImageShouldApplyBackgroundColorFilter(TestImageProvider provider) + [WithFileCollection(nameof(InputImages), PixelTypes.Rgba32)] + public void FullImage(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.BackgroundColor(NamedColors.HotPink)); - image.DebugSave(provider); - } + provider.RunValidatingProcessorTest(x => x.BackgroundColor(NamedColors.HotPink)); } [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] - public void ImageShouldApplyBackgroundColorFilterInBox(TestImageProvider provider) + [WithFileCollection(nameof(InputImages), PixelTypes.Rgba32)] + public void InBox(TestImageProvider provider) where TPixel : struct, IPixel { - using (Image source = provider.GetImage()) - using (var image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.BackgroundColor(NamedColors.HotPink, bounds)); - image.DebugSave(provider); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } + provider.RunRectangleConstrainedValidatingProcessorTest( + (x, rect) => x.BackgroundColor(NamedColors.HotPink, rect)); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Effects/OilPaintTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Effects/OilPaintTest.cs index d4429aaf3..ea2273cd5 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Effects/OilPaintTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Effects/OilPaintTest.cs @@ -10,40 +10,40 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects { - public class OilPaintTest : FileTestBase + [GroupOutput("Effects")] + public class OilPaintTest { public static readonly TheoryData OilPaintValues = new TheoryData { - { 15, 10 }, { 6, 5 } + { 15, 10 }, + { 6, 5 } }; + public static readonly string[] InputImages = + { + TestImages.Png.CalliphoraPartial, + TestImages.Bmp.Car + }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), DefaultPixelType)] - public void ApplyOilPaintFilter(TestImageProvider provider, int levels, int brushSize) + [WithFileCollection(nameof(InputImages), nameof(OilPaintValues), PixelTypes.Rgba32)] + public void FullImage(TestImageProvider provider, int levels, int brushSize) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.OilPaint(levels, brushSize)); - image.DebugSave(provider, string.Join("-", levels, brushSize)); - } + provider.RunValidatingProcessorTest( + x => x.OilPaint(levels, brushSize), + $"{levels}-{brushSize}", + appendPixelTypeToFileName: false); } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), DefaultPixelType)] - public void ApplyOilPaintFilterInBox(TestImageProvider provider, int levels, int brushSize) + [WithFileCollection(nameof(InputImages), nameof(OilPaintValues), PixelTypes.Rgba32)] + [WithTestPatternImages(nameof(OilPaintValues), 100, 100, PixelTypes.Rgba32)] + public void InBox(TestImageProvider provider, int levels, int brushSize) where TPixel : struct, IPixel { - using (Image source = provider.GetImage()) - using (Image image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.OilPaint(levels, brushSize, bounds)); - image.DebugSave(provider, string.Join("-", levels, brushSize)); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } + provider.RunRectangleConstrainedValidatingProcessorTest( + (x, rect) => x.OilPaint(levels, brushSize, rect), + $"{levels}-{brushSize}"); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Effects/PixelateTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Effects/PixelateTest.cs index cb9a0ba0c..726f4b707 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Effects/PixelateTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Effects/PixelateTest.cs @@ -4,82 +4,32 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - using SixLabors.Primitives; + using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects { - public class PixelateTest : FileTestBase + [GroupOutput("Effects")] + public class PixelateTest { - public static readonly TheoryData PixelateValues - = new TheoryData - { - 4 , - 8 - }; + public static readonly TheoryData PixelateValues = new TheoryData { 4, 8 }; [Theory] - [WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.Rgba32)] - public void ImageShouldApplyPixelateFilter(TestImageProvider provider, int value) + [WithFile(TestImages.Png.Ducky, nameof(PixelateValues), PixelTypes.Rgba32)] + public void FullImage(TestImageProvider provider, int value) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Pixelate(value)); - image.DebugSave(provider, value); - - // Test the neigbouring pixels - for (int y = 0; y < image.Height; y += value) - { - for (int x = 0; x < image.Width; x += value) - { - TPixel source = image[x, y]; - for (int pixY = y; pixY < y + value && pixY < image.Height; pixY++) - { - for (int pixX = x; pixX < x + value && pixX < image.Width; pixX++) - { - Assert.Equal(source, image[pixX, pixY]); - } - } - } - } - } + provider.RunValidatingProcessorTest(x => x.Pixelate(value), value, appendPixelTypeToFileName: false); } [Theory] [WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.Rgba32)] - public void ImageShouldApplyPixelateFilterInBox(TestImageProvider provider, int value) + [WithFile(TestImages.Png.CalliphoraPartial, nameof(PixelateValues), PixelTypes.Rgba32)] + public void InBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { - using (Image source = provider.GetImage()) - using (var image = source.Clone()) - { - var bounds = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.Pixelate(value, bounds)); - image.DebugSave(provider, value); - - for (int y = 0; y < image.Height; y++) - { - for (int x = 0; x < image.Width; x++) - { - int tx = x; - int ty = y; - TPixel sourceColor = source[tx, ty]; - if (bounds.Contains(tx, ty)) - { - int sourceX = tx - ((tx - bounds.Left) % value) + (value / 2); - int sourceY = ty - ((ty - bounds.Top) % value) + (value / 2); - - sourceColor = image[sourceX, sourceY]; - } - Assert.Equal(sourceColor, image[tx, ty]); - } - } - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } + provider.RunRectangleConstrainedValidatingProcessorTest((x, rect) => x.Pixelate(value, rect), value); } } } \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index 0c524009f..50de3b986 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 0c524009f4d4b0edefddd944defdc408c3971536 +Subproject commit 50de3b98694f20c9307d4d7cdac870f5820823c8 From f03c5def950b4a8d9d3a86c084057b4679bebf5a Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 19:42:44 +0200 Subject: [PATCH 119/223] validating tests for AutoOrient --- .../Processors/Transforms/AutoOrientTests.cs | 58 +++++++++++-------- tests/Images/External | 2 +- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs index 28b01061e..6dc9b3630 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs @@ -6,27 +6,16 @@ using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; + using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { - public class AutoOrientTests : FileTestBase + [GroupOutput("Transforms")] + public class AutoOrientTests { - public static readonly string[] FlipFiles = { TestImages.Bmp.F }; - - public static readonly TheoryData OrientationValues - = new TheoryData - { - { RotateMode.None, FlipMode.None, 0 }, - { RotateMode.None, FlipMode.None, 1 }, - { RotateMode.None, FlipMode.Horizontal, 2 }, - { RotateMode.Rotate180, FlipMode.None, 3 }, - { RotateMode.Rotate180, FlipMode.Horizontal, 4 }, - { RotateMode.Rotate90, FlipMode.Horizontal, 5 }, - { RotateMode.Rotate270, FlipMode.None, 6 }, - { RotateMode.Rotate90, FlipMode.Vertical, 7 }, - { RotateMode.Rotate90, FlipMode.None, 8 }, - }; + public const string FlipTestFile = TestImages.Bmp.F; public static readonly TheoryData InvalidOrientationValues = new TheoryData @@ -38,27 +27,38 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { ExifDataType.SignedLong, BitConverter.GetBytes((int) 5) } }; + public static readonly TheoryData ExifOrientationValues = new TheoryData() + { + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 + }; + [Theory] - [WithFileCollection(nameof(FlipFiles), nameof(OrientationValues), DefaultPixelType)] - public void ImageShouldAutoRotate(TestImageProvider provider, RotateMode rotateType, FlipMode flipType, ushort orientation) + [WithFile(FlipTestFile, nameof(ExifOrientationValues), PixelTypes.Rgba32)] + public void AutoOrient_WorksForAllExifOrientations(TestImageProvider provider, ushort orientation) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { image.Metadata.ExifProfile = new ExifProfile(); image.Metadata.ExifProfile.SetValue(ExifTag.Orientation, orientation); - - image.Mutate(x => x.RotateFlip(rotateType, flipType)); - image.DebugSave(provider, string.Join("_", rotateType, flipType, orientation, "1_before")); - + image.Mutate(x => x.AutoOrient()); - image.DebugSave(provider, string.Join("_", rotateType, flipType, orientation, "2_after")); + image.DebugSave(provider, orientation, appendPixelTypeToFileName: false); + image.CompareToReferenceOutput(provider, orientation, appendPixelTypeToFileName: false); } } [Theory] - [WithFileCollection(nameof(FlipFiles), nameof(InvalidOrientationValues), DefaultPixelType)] - public void ImageShouldAutoRotateInvalidValues(TestImageProvider provider, ExifDataType dataType, byte[] orientation) + [WithFile(FlipTestFile, nameof(InvalidOrientationValues), PixelTypes.Rgba32)] + public void AutoOrient_WorksWithCorruptExifData(TestImageProvider provider, ExifDataType dataType, byte[] orientation) where TPixel : struct, IPixel { var profile = new ExifProfile(); @@ -72,11 +72,19 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms bytes[18] = (byte)dataType; // Change the number of components bytes[20] = 1; + + byte[] orientationCodeData = new byte[8]; + Array.Copy(orientation, orientationCodeData, orientation.Length); + + ulong orientationCode = BitConverter.ToUInt64(orientationCodeData, 0); using (Image image = provider.GetImage()) + using (Image reference = image.Clone()) { image.Metadata.ExifProfile = new ExifProfile(bytes); image.Mutate(x => x.AutoOrient()); + image.DebugSave(provider, $"{dataType}-{orientationCode}", appendPixelTypeToFileName: false); + ImageComparer.Exact.VerifySimilarity(image, reference); } } } diff --git a/tests/Images/External b/tests/Images/External index 50de3b986..497dda871 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 50de3b98694f20c9307d4d7cdac870f5820823c8 +Subproject commit 497dda87179af1dc323064140765f72b892116a3 From 7caebe385aa02b3dfe3141df3a9d5913983e793b Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 20:22:06 +0200 Subject: [PATCH 120/223] validating tests for Skew and Entropy crop --- .../Processors/Transforms/CropTest.cs | 2 +- .../Processors/Transforms/EntropyCropTest.cs | 27 ++++--- .../Processors/Transforms/SkewTest.cs | 72 ------------------- .../Processors/Transforms/SkewTests.cs | 67 +++++++++++++++++ tests/Images/External | 2 +- 5 files changed, 82 insertions(+), 88 deletions(-) delete mode 100644 tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTests.cs diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/CropTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/CropTest.cs index c01c3b1bd..50217e892 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/CropTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/CropTest.cs @@ -13,7 +13,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { [GroupOutput("Transforms")] - public class CropTest : FileTestBase + public class CropTest { [Theory] [WithTestPatternImages(70, 30, PixelTypes.Rgba32, 0, 0, 70, 30)] diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/EntropyCropTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/EntropyCropTest.cs index 728527021..d20e6fa35 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/EntropyCropTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/EntropyCropTest.cs @@ -7,25 +7,24 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { - public class EntropyCropTest : FileTestBase + [GroupOutput("Transforms")] + public class EntropyCropTest { - public static readonly TheoryData EntropyCropValues - = new TheoryData - { - .25F, - .75F - }; + public static readonly TheoryData EntropyCropValues = new TheoryData { .25F, .75F }; + + public static readonly string[] InputImages = + { + TestImages.Png.Ducky, + TestImages.Jpeg.Baseline.Jpeg400, + TestImages.Jpeg.Baseline.MultiScanBaselineCMYK + }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(EntropyCropValues), DefaultPixelType)] - public void ImageShouldEntropyCrop(TestImageProvider provider, float value) + [WithFileCollection(nameof(InputImages), nameof(EntropyCropValues), PixelTypes.Rgba32)] + public void EntropyCrop(TestImageProvider provider, float value) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.EntropyCrop(value)); - image.DebugSave(provider, value); - } + provider.RunValidatingProcessorTest(x => x.EntropyCrop(value), value, appendPixelTypeToFileName: false); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTest.cs deleted file mode 100644 index 29c51543f..000000000 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTest.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Collections.Generic; -using System.Reflection; - -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Processing.Processors.Transforms; -using SixLabors.ImageSharp.PixelFormats; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms -{ - public class SkewTest : FileTestBase - { - public static readonly TheoryData SkewValues - = new TheoryData - { - { 20, 10 }, - { -20, -10 } - }; - - public static readonly List ResamplerNames - = new List - { - nameof(KnownResamplers.Bicubic), - nameof(KnownResamplers.Box), - nameof(KnownResamplers.CatmullRom), - nameof(KnownResamplers.Hermite), - nameof(KnownResamplers.Lanczos2), - nameof(KnownResamplers.Lanczos3), - nameof(KnownResamplers.Lanczos5), - nameof(KnownResamplers.Lanczos8), - nameof(KnownResamplers.MitchellNetravali), - nameof(KnownResamplers.NearestNeighbor), - nameof(KnownResamplers.Robidoux), - nameof(KnownResamplers.RobidouxSharp), - nameof(KnownResamplers.Spline), - nameof(KnownResamplers.Triangle), - nameof(KnownResamplers.Welch), - }; - - [Theory] - [WithTestPatternImages(nameof(SkewValues), 100, 50, DefaultPixelType)] - public void ImageShouldSkew(TestImageProvider provider, float x, float y) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(i => i.Skew(x, y)); - image.DebugSave(provider, string.Join("_", x, y)); - } - } - - [Theory] - [WithTestPatternImages(nameof(SkewValues), 100, 50, DefaultPixelType)] - public void ImageShouldSkewWithSampler(TestImageProvider provider, float x, float y) - where TPixel : struct, IPixel - { - foreach (string resamplerName in ResamplerNames) - { - IResampler sampler = TestUtils.GetResampler(resamplerName); - using (Image image = provider.GetImage()) - { - image.Mutate(i => i.Skew(x, y, sampler)); - image.DebugSave(provider, string.Join("_", x, y, resamplerName)); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTests.cs new file mode 100644 index 000000000..ad77027f0 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTests.cs @@ -0,0 +1,67 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Transforms; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms +{ + [GroupOutput("Transforms")] + public class SkewTests + { + private const PixelTypes CommonPixelTypes = PixelTypes.Bgra32 | PixelTypes.Rgb24; + + public static readonly string[] ResamplerNames = new[] + { + nameof(KnownResamplers.Bicubic), + nameof(KnownResamplers.Box), + nameof(KnownResamplers.CatmullRom), + nameof(KnownResamplers.Hermite), + nameof(KnownResamplers.Lanczos2), + nameof(KnownResamplers.Lanczos3), + nameof(KnownResamplers.Lanczos5), + nameof(KnownResamplers.Lanczos8), + nameof(KnownResamplers.MitchellNetravali), + nameof(KnownResamplers.NearestNeighbor), + nameof(KnownResamplers.Robidoux), + nameof(KnownResamplers.RobidouxSharp), + nameof(KnownResamplers.Spline), + nameof(KnownResamplers.Triangle), + nameof(KnownResamplers.Welch), + }; + + public static readonly TheoryData SkewValues = new TheoryData + { + { 20, 10 }, + { -20, -10 } + }; + + private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.01f); + + [Theory] + [WithTestPatternImages(nameof(SkewValues), 100, 50, CommonPixelTypes)] + public void Skew_IsNotBoundToSinglePixelType(TestImageProvider provider, float x, float y) + where TPixel : struct, IPixel + { + provider.RunValidatingProcessorTest(ctx => ctx.Skew(x, y), $"{x}_{y}", ValidatorComparer); + } + + [Theory] + [WithFile(TestImages.Png.Ducky, nameof(ResamplerNames), PixelTypes.Rgba32)] + public void Skew_WorksWithAllResamplers(TestImageProvider provider, string resamplerName) + where TPixel : struct, IPixel + { + IResampler sampler = TestUtils.GetResampler(resamplerName); + + provider.RunValidatingProcessorTest( + x => x.Skew(21, 32, sampler), + resamplerName, + comparer: ValidatorComparer, + appendPixelTypeToFileName: false); + } + } +} \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index 497dda871..56ee5df14 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 497dda87179af1dc323064140765f72b892116a3 +Subproject commit 56ee5df145d9696e401e2bc53e615c553cfb32d5 From 3468f0a4d138c038683e176c04a1abe3c6bccbe9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 20:57:30 +0200 Subject: [PATCH 121/223] validating tests for Overlay processors --- .../Processors/Overlays/GlowTest.cs | 57 ++------------- .../Processors/Overlays/OverlayTestBase.cs | 70 +++++++++++++++++++ .../Processors/Overlays/VignetteTest.cs | 61 ++-------------- tests/Images/External | 2 +- 4 files changed, 83 insertions(+), 107 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs diff --git a/tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs index 479ee346a..113c13b8a 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs @@ -10,59 +10,14 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays { - public class GlowTest : FileTestBase + [GroupOutput("Overlays")] + public class GlowTest : OverlayTestBase { - [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] - public void ImageShouldApplyGlowFilter(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Glow()); - image.DebugSave(provider); - } - } + protected override void Apply(IImageProcessingContext ctx, T color) => ctx.Glow(color); - [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] - public void ImageShouldApplyGlowFilterColor(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Glow(NamedColors.Orange)); - image.DebugSave(provider); - } - } + protected override void Apply(IImageProcessingContext ctx, float radiusX, float radiusY) => + ctx.Glow(radiusX); - [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] - public void ImageShouldApplyGlowFilterRadius(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Glow(image.Width / 4F)); - image.DebugSave(provider); - } - } - - [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] - public void ImageShouldApplyGlowFilterInBox(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image source = provider.GetImage()) - using (var image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); - - image.Mutate(x => x.Glow(bounds)); - image.DebugSave(provider); - - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } - } + protected override void Apply(IImageProcessingContext ctx, Rectangle rect) => ctx.Glow(rect); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs b/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs new file mode 100644 index 000000000..d2abcd731 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs @@ -0,0 +1,70 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Reflection; + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.Primitives; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays +{ + [GroupOutput("Overlays")] + public abstract class OverlayTestBase + { + public static string[] ColorNames = { "Blue", "White" }; + + public static string[] InputImages = { TestImages.Png.Ducky, TestImages.Png.Splash }; + + private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.05f); + + [Theory] + [WithFileCollection(nameof(InputImages), nameof(ColorNames), PixelTypes.Rgba32)] + public void FullImage_ApplyColor(TestImageProvider provider, string colorName) + where TPixel : struct, IPixel + { + provider.Utility.TestGroupName = this.GetType().Name; + var f = (FieldInfo)typeof(NamedColors).GetMember(colorName)[0]; + TPixel color = (TPixel)f.GetValue(null); + + provider.RunValidatingProcessorTest(x => this.Apply(x, color), colorName, ValidatorComparer, appendPixelTypeToFileName: false); + } + + [Theory] + [WithFileCollection(nameof(InputImages), PixelTypes.Rgba32)] + public void FullImage_ApplyRadius(TestImageProvider provider) + where TPixel : struct, IPixel + { + provider.Utility.TestGroupName = this.GetType().Name; + provider.RunValidatingProcessorTest( + x => + { + Size size = x.GetCurrentSize(); + this.Apply(x, size.Width / 4f, size.Height / 4f); + }, + comparer: ValidatorComparer, + appendPixelTypeToFileName: false); + } + + [Theory] + [WithFileCollection(nameof(InputImages), PixelTypes.Rgba32)] + public void InBox(TestImageProvider provider) + where TPixel : struct, IPixel + { + provider.Utility.TestGroupName = this.GetType().Name; + provider.RunRectangleConstrainedValidatingProcessorTest((x, rect) => this.Apply(x, rect)); + } + + protected abstract void Apply(IImageProcessingContext ctx, T color) + where T : struct, IPixel; + + protected abstract void Apply(IImageProcessingContext ctx, float radiusX, float radiusY) + where T : struct, IPixel; + + protected abstract void Apply(IImageProcessingContext ctx, Rectangle rect) + where T : struct, IPixel; + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs index 3a378a095..ad04a827d 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs @@ -1,68 +1,19 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - using SixLabors.Primitives; -using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays { - public class VignetteTest : FileTestBase + [GroupOutput("Overlays")] + public class VignetteTest : OverlayTestBase { - [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] - public void ImageShouldApplyVignetteFilter(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Vignette()); - image.DebugSave(provider); - } - } - - [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] - public void ImageShouldApplyVignetteFilterColor(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Vignette(NamedColors.Orange)); - image.DebugSave(provider); - } - } - - [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] - public void ImageShouldApplyVignetteFilterRadius(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Mutate(x => x.Vignette(image.Width / 4F, image.Height / 4F)); - image.DebugSave(provider); - } - } - - [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] - public void ImageShouldApplyVignetteFilterInBox(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image source = provider.GetImage()) - using (var image = source.Clone()) - { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + protected override void Apply(IImageProcessingContext ctx, T color) => ctx.Vignette(color); - image.Mutate(x => x.Vignette(bounds)); - image.DebugSave(provider); + protected override void Apply(IImageProcessingContext ctx, float radiusX, float radiusY) => + ctx.Vignette(radiusX, radiusY); - ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); - } - } + protected override void Apply(IImageProcessingContext ctx, Rectangle rect) => ctx.Vignette(rect); } } \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index 56ee5df14..854ba68b0 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 56ee5df145d9696e401e2bc53e615c553cfb32d5 +Subproject commit 854ba68b05162bdd87c0c9bbdcdb1c848aa6ddbe From 07670cb0d1c313d0311a3cc781f0452a23b76212 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sat, 4 May 2019 21:05:25 +0200 Subject: [PATCH 122/223] Add more pixel conversion tests --- .../PixelImplementations/Byte4.cs | 2 +- .../PixelFormats/Argb32Tests.cs | 62 +++++++ .../PixelFormats/Bgr24Tests.cs | 18 ++ .../PixelFormats/Bgr565Tests.cs | 1 - .../PixelFormats/Bgra32Tests.cs | 25 +++ .../PixelFormats/Byte4Tests.cs | 14 ++ .../PixelFormats/Gray16Tests.cs | 18 ++ .../PixelFormats/Gray8Tests.cs | 20 ++- .../PixelFormats/NormalizedByte4Tests.cs | 156 ++++++++++++++++++ .../PixelFormats/NormalizedShort4Tests.cs | 156 ++++++++++++++++++ .../PixelFormats/Rgba1010102Tests.cs | 18 ++ .../PixelFormats/RgbaVectorTests.cs | 42 +++++ 12 files changed, 528 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs index a07cd5213..ab8a13c16 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs @@ -149,7 +149,7 @@ namespace SixLabors.ImageSharp.PixelFormats public override string ToString() { var vector = this.ToVector4(); - return FormattableString.Invariant($"Bgra5551({vector.X:#0.##}, {vector.Y:#0.##}, {vector.Z:#0.##}, {vector.W:#0.##})"); + return FormattableString.Invariant($"Byte4({vector.X:#0.##}, {vector.Y:#0.##}, {vector.Z:#0.##}, {vector.W:#0.##})"); } /// diff --git a/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs index 4f3394e69..1ccf485fe 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -9,6 +10,67 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class Argb32Tests { + /// + /// Tests the equality operators for equality. + /// + [Fact] + public void AreEqual() + { + var color1 = new Argb32(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new Argb32(new Vector4(0.0f)); + var color3 = new Argb32(new Vector4(1.0f, 0.0f, 1.0f, 1.0f)); + var color4 = new Argb32(1.0f, 0.0f, 1.0f, 1.0f); + + Assert.Equal(color1, color2); + Assert.Equal(color3, color4); + } + + /// + /// Tests the equality operators for inequality. + /// + [Fact] + public void AreNotEqual() + { + var color1 = new Argb32(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new Argb32(new Vector4(1.0f)); + var color3 = new Argb32(new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + var color4 = new Argb32(1.0f, 1.0f, 0.0f, 1.0f); + + Assert.NotEqual(color1, color2); + Assert.NotEqual(color3, color4); + } + + /// + /// Tests whether the color constructor correctly assign properties. + /// + [Fact] + public void ConstructorAssignsProperties() + { + var color1 = new Argb32(1, .1f, .133f, .864f); + Assert.Equal(255, color1.R); + Assert.Equal((byte)Math.Round(.1f * 255), color1.G); + Assert.Equal((byte)Math.Round(.133f * 255), color1.B); + Assert.Equal((byte)Math.Round(.864f * 255), color1.A); + + var color2 = new Argb32(1, .1f, .133f); + Assert.Equal(255, color2.R); + Assert.Equal(Math.Round(.1f * 255), color2.G); + Assert.Equal(Math.Round(.133f * 255), color2.B); + Assert.Equal(255, color2.A); + + var color4 = new Argb32(new Vector3(1, .1f, .133f)); + Assert.Equal(255, color4.R); + Assert.Equal(Math.Round(.1f * 255), color4.G); + Assert.Equal(Math.Round(.133f * 255), color4.B); + Assert.Equal(255, color4.A); + + var color5 = new Argb32(new Vector4(1, .1f, .133f, .5f)); + Assert.Equal(255, color5.R); + Assert.Equal(Math.Round(.1f * 255), color5.G); + Assert.Equal(Math.Round(.133f * 255), color5.B); + Assert.Equal(Math.Round(.5f * 255), color5.A); + } + [Fact] public void Argb32_PackedValue() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs index f145e6928..026670485 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs @@ -9,6 +9,24 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class Bgr24Tests { + [Fact] + public void AreEqual() + { + var color1 = new Bgr24(byte.MaxValue, 0, byte.MaxValue); + var color2 = new Bgr24(byte.MaxValue, 0, byte.MaxValue); + + Assert.Equal(color1, color2); + } + + [Fact] + public void AreNotEqual() + { + var color1 = new Bgr24(byte.MaxValue, 0, 0); + var color2 = new Bgr24(byte.MaxValue, 0, byte.MaxValue); + + Assert.NotEqual(color1, color2); + } + public static readonly TheoryData ColorData = new TheoryData() { { 1, 2, 3 }, { 4, 5, 6 }, { 0, 255, 42 } }; diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs index 03e905466..ccefa85c1 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Numerics; using SixLabors.ImageSharp.PixelFormats; using Xunit; diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs index 171a3dfa0..4c5de7ee9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -9,6 +10,30 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class Bgra32Tests { + /// + /// Tests the equality operators for equality. + /// + [Fact] + public void AreEqual() + { + var color1 = new Bgra32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); + var color2 = new Bgra32(byte.MaxValue, byte.MaxValue, byte.MaxValue); + + Assert.Equal(color1, color2); + } + + /// + /// Tests the equality operators for inequality. + /// + [Fact] + public void AreNotEqual() + { + var color1 = new Bgra32(0, 0, byte.MaxValue, byte.MaxValue); + var color2 = new Bgra32(byte.MaxValue, byte.MaxValue, byte.MaxValue); + + Assert.NotEqual(color1, color2); + } + public static readonly TheoryData ColorData = new TheoryData() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs index ce9e56317..2dff656ac 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs @@ -75,6 +75,20 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(1, actual.W); } + [Fact] + public void Byte4_ToRgba32() + { + // arrange + var byte4 = new Byte4(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); + var expected = new Rgba32(Vector4.One); + var actual = default(Rgba32); + + // act + byte4.ToRgba32(ref actual); + + Assert.Equal(expected, actual); + } + [Fact] public void Byte4_FromScaledVector4() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs index 01b60832e..8a0bd62c1 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs @@ -9,6 +9,24 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class Gray16Tests { + [Fact] + public void AreEqual() + { + var color1 = new Gray16(3000); + var color2 = new Gray16(3000); + + Assert.Equal(color1, color2); + } + + [Fact] + public void AreNotEqual() + { + var color1 = new Gray16(12345); + var color2 = new Gray16(54321); + + Assert.NotEqual(color1, color2); + } + [Theory] [InlineData(0)] [InlineData(65535)] diff --git a/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs index 159f97cde..74fd903ca 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs @@ -1,10 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Diagnostics; using System.Numerics; -using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -45,6 +43,24 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats public void Gray8_PackedValue_EqualsInput(byte input) => Assert.Equal(input, new Gray8(input).PackedValue); + [Fact] + public void AreEqual() + { + var color1 = new Gray8(100); + var color2 = new Gray8(100); + + Assert.Equal(color1, color2); + } + + [Fact] + public void AreNotEqual() + { + var color1 = new Gray8(100); + var color2 = new Gray8(200); + + Assert.NotEqual(color1, color2); + } + [Fact] public void Gray8_FromScaledVector4() { diff --git a/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs index 1cb404a00..7687a7777 100644 --- a/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs @@ -9,6 +9,36 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class NormalizedByte4Tests { + /// + /// Tests the equality operators for equality. + /// + [Fact] + public void AreEqual() + { + var color1 = new NormalizedByte4(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new NormalizedByte4(new Vector4(0.0f)); + var color3 = new NormalizedByte4(new Vector4(1.0f, 0.0f, 1.0f, 1.0f)); + var color4 = new NormalizedByte4(1.0f, 0.0f, 1.0f, 1.0f); + + Assert.Equal(color1, color2); + Assert.Equal(color3, color4); + } + + /// + /// Tests the equality operators for inequality. + /// + [Fact] + public void AreNotEqual() + { + var color1 = new NormalizedByte4(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new NormalizedByte4(new Vector4(1.0f)); + var color3 = new NormalizedByte4(new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + var color4 = new NormalizedByte4(1.0f, 1.0f, 0.0f, 1.0f); + + Assert.NotEqual(color1, color2); + Assert.NotEqual(color3, color4); + } + [Fact] public void NormalizedByte4_PackedValues() { @@ -61,6 +91,90 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual); } + [Fact] + public void NormalizedByte4_FromArgb32() + { + // arrange + var byte4 = default(NormalizedByte4); + Vector4 expected = Vector4.One; + + // act + byte4.FromArgb32(new Argb32(255, 255, 255, 255)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedByte4_FromBgr24() + { + // arrange + var byte4 = default(NormalizedByte4); + Vector4 expected = Vector4.One; + + // act + byte4.FromBgr24(new Bgr24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedByte4_FromGrey8() + { + // arrange + var byte4 = default(NormalizedByte4); + Vector4 expected = Vector4.One; + + // act + byte4.FromGray8(new Gray8(byte.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedByte4_FromGrey16() + { + // arrange + var byte4 = default(NormalizedByte4); + Vector4 expected = Vector4.One; + + // act + byte4.FromGray16(new Gray16(ushort.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedByte4_FromRgb24() + { + // arrange + var byte4 = default(NormalizedByte4); + Vector4 expected = Vector4.One; + + // act + byte4.FromRgb24(new Rgb24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedByte4_FromRgba32() + { + // arrange + var byte4 = default(NormalizedByte4); + Vector4 expected = Vector4.One; + + // act + byte4.FromRgba32(new Rgba32(255, 255, 255, 255)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + [Fact] public void NormalizedByte4_FromBgra5551() { @@ -74,5 +188,47 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, normalizedByte4.ToVector4()); } + + [Fact] + public void NormalizedByte4_FromRgb48() + { + // arrange + var byte4 = default(NormalizedByte4); + Vector4 expected = Vector4.One; + + // act + byte4.FromRgb48(new Rgb48(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedByte4_FromRgba64() + { + // arrange + var byte4 = default(NormalizedByte4); + Vector4 expected = Vector4.One; + + // act + byte4.FromRgba64(new Rgba64(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedByte4_ToRgba32() + { + // arrange + var byte4 = new NormalizedByte4(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); + var expected = new Rgba32(Vector4.One); + var actual = default(Rgba32); + + // act + byte4.ToRgba32(ref actual); + + Assert.Equal(expected, actual); + } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs index cea7e3146..b872e58b6 100644 --- a/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs @@ -9,6 +9,36 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { public class NormalizedShort4Tests { + /// + /// Tests the equality operators for equality. + /// + [Fact] + public void AreEqual() + { + var color1 = new NormalizedShort4(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new NormalizedShort4(new Vector4(0.0f)); + var color3 = new NormalizedShort4(new Vector4(1.0f, 0.0f, 1.0f, 1.0f)); + var color4 = new NormalizedShort4(1.0f, 0.0f, 1.0f, 1.0f); + + Assert.Equal(color1, color2); + Assert.Equal(color3, color4); + } + + /// + /// Tests the equality operators for inequality. + /// + [Fact] + public void AreNotEqual() + { + var color1 = new NormalizedShort4(0.0f, 0.0f, 0.0f, 0.0f); + var color2 = new NormalizedShort4(new Vector4(1.0f)); + var color3 = new NormalizedShort4(new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); + var color4 = new NormalizedShort4(1.0f, 1.0f, 0.0f, 1.0f); + + Assert.NotEqual(color1, color2); + Assert.NotEqual(color3, color4); + } + [Fact] public void NormalizedShort4_PackedValues() { @@ -62,6 +92,132 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, actual); } + [Fact] + public void NormalizedShort4_FromArgb32() + { + // arrange + var byte4 = default(NormalizedShort4); + Vector4 expected = Vector4.One; + + // act + byte4.FromArgb32(new Argb32(255, 255, 255, 255)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedShort4_FromBgr24() + { + // arrange + var byte4 = default(NormalizedShort4); + Vector4 expected = Vector4.One; + + // act + byte4.FromBgr24(new Bgr24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedShort4_FromGrey8() + { + // arrange + var byte4 = default(NormalizedShort4); + Vector4 expected = Vector4.One; + + // act + byte4.FromGray8(new Gray8(byte.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedShort4_FromGrey16() + { + // arrange + var byte4 = default(NormalizedShort4); + Vector4 expected = Vector4.One; + + // act + byte4.FromGray16(new Gray16(ushort.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedShort4_FromRgb24() + { + // arrange + var byte4 = default(NormalizedShort4); + Vector4 expected = Vector4.One; + + // act + byte4.FromRgb24(new Rgb24(byte.MaxValue, byte.MaxValue, byte.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedShort4_FromRgba32() + { + // arrange + var byte4 = default(NormalizedShort4); + Vector4 expected = Vector4.One; + + // act + byte4.FromRgba32(new Rgba32(255, 255, 255, 255)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedShort4_FromRgb48() + { + // arrange + var byte4 = default(NormalizedShort4); + Vector4 expected = Vector4.One; + + // act + byte4.FromRgb48(new Rgb48(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedShort4_FromRgba64() + { + // arrange + var byte4 = default(NormalizedShort4); + Vector4 expected = Vector4.One; + + // act + byte4.FromRgba64(new Rgba64(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)); + + // assert + Assert.Equal(expected, byte4.ToScaledVector4()); + } + + [Fact] + public void NormalizedShort4_ToRgba32() + { + // arrange + var byte4 = new NormalizedShort4(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); + var expected = new Rgba32(Vector4.One); + var actual = default(Rgba32); + + // act + byte4.ToRgba32(ref actual); + + Assert.Equal(expected, actual); + } + [Fact] public void NormalizedShort4_FromBgra5551() { diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs index 19a5d4b22..3a28c82b7 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs @@ -122,6 +122,24 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expectedPackedValue, rgba.PackedValue); } + [Fact] + public void Rgba1010102_FromRgba32() + { + // arrange + var rgba1 = default(Rgba1010102); + var rgba2 = default(Rgba1010102); + uint expectedPackedValue1 = uint.MaxValue; + uint expectedPackedValue2 = 0xFFF003FF; + + // act + rgba1.FromRgba32(new Rgba32(255, 255, 255, 255)); + rgba2.FromRgba32(new Rgba32(255, 0, 255, 255)); + + // assert + Assert.Equal(expectedPackedValue1, rgba1.PackedValue); + Assert.Equal(expectedPackedValue2, rgba2.PackedValue); + } + [Fact] public void Rgba1010102_FromBgr24() { diff --git a/tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs b/tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs index e880e3851..570d72cf4 100644 --- a/tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs @@ -146,5 +146,47 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + + [Fact] + public void RgbaVector_FromBgra5551() + { + // arrange + var rgb = default(RgbaVector); + Vector4 expected = Vector4.One; + + // act + rgb.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); + + // assert + Assert.Equal(expected, rgb.ToScaledVector4()); + } + + [Fact] + public void RgbaVector_FromGrey16() + { + // arrange + var rgba = default(RgbaVector); + Vector4 expected = Vector4.One; + + // act + rgba.FromGray16(new Gray16(ushort.MaxValue)); + + // assert + Assert.Equal(expected, rgba.ToScaledVector4()); + } + + [Fact] + public void RgbaVector_FromGrey8() + { + // arrange + var rgba = default(RgbaVector); + Vector4 expected = Vector4.One; + + // act + rgba.FromGray8(new Gray8(byte.MaxValue)); + + // assert + Assert.Equal(expected, rgba.ToScaledVector4()); + } } } \ No newline at end of file From 4f4128864446268e6eff01cf03c3e7cd528bd9f1 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 22:18:22 +0200 Subject: [PATCH 123/223] skip DitherTests on old 32 bit runtimes --- .../Processors/Dithering/DitherTests.cs | 37 +++++++++++++++++++ tests/Images/External | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs index 368feefb9..cb901c2a8 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs @@ -46,11 +46,23 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization private static IErrorDiffuser DefaultErrorDiffuser => KnownDiffusers.Atkinson; + /// + /// The output is visually correct old 32bit runtime, + /// but it is very different because of floating point inaccuracies. + /// + private static readonly bool SkipAllDitherTests = + !TestEnvironment.Is64BitProcess && string.IsNullOrEmpty(TestEnvironment.NetCoreVersion); + [Theory] [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] public void ApplyDiffusionFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { + if (SkipAllDitherTests) + { + return; + } + provider.RunRectangleConstrainedValidatingProcessorTest( (x, rect) => x.Diffuse(DefaultErrorDiffuser, .5F, rect), comparer: ValidatorComparer); @@ -61,6 +73,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization public void ApplyDitherFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { + if (SkipAllDitherTests) + { + return; + } + provider.RunRectangleConstrainedValidatingProcessorTest( (x, rect) => x.Dither(DefaultDitherer, rect), comparer: ValidatorComparer); @@ -71,6 +88,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization public void DiffusionFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { + if (SkipAllDitherTests) + { + return; + } + // Increased tolerance because of compatibility issues on .NET 4.6.2: var comparer = ImageComparer.TolerantPercentage(1f); provider.RunValidatingProcessorTest(x => x.Diffuse(DefaultErrorDiffuser, 0.5f), comparer: comparer); @@ -83,6 +105,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization IErrorDiffuser diffuser) where TPixel : struct, IPixel { + if (SkipAllDitherTests) + { + return; + } + provider.RunValidatingProcessorTest( x => x.Diffuse(diffuser, 0.5f), testOutputDetails: diffuser.GetType().Name, @@ -95,6 +122,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization public void DitherFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { + if (SkipAllDitherTests) + { + return; + } + provider.RunValidatingProcessorTest( x => x.Dither(DefaultDitherer), comparer: ValidatorComparer); @@ -107,6 +139,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization IOrderedDither ditherer) where TPixel : struct, IPixel { + if (SkipAllDitherTests) + { + return; + } + provider.RunValidatingProcessorTest( x => x.Dither(ditherer), testOutputDetails: ditherer.GetType().Name, diff --git a/tests/Images/External b/tests/Images/External index 854ba68b0..c057090b4 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 854ba68b05162bdd87c0c9bbdcdb1c848aa6ddbe +Subproject commit c057090b4402120a83a8efe251aa5b691db9c0dc From ff48c62e7155e797a2982b37e61676da7db42319 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 23:16:11 +0200 Subject: [PATCH 124/223] refactor BoxBlur and GaussianBlur --- .../Processing/BoxBlurExtensions.cs | 20 ++--- .../Processing/GaussianBlurExtensions.cs | 20 ++--- .../Convolution/BoxBlurProcessor.cs | 53 ++++-------- .../Convolution/BoxBlurProcessor{TPixel}.cs | 64 +++++++++++++++ .../Convolution/GaussianBlurProcessor.cs | 82 +++++++------------ .../GaussianBlurProcessor{TPixel}.cs | 79 ++++++++++++++++++ .../Processing/Convolution/BoxBlurTest.cs | 6 +- .../Convolution/GaussianBlurTest.cs | 6 +- 8 files changed, 210 insertions(+), 120 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs diff --git a/src/ImageSharp/Processing/BoxBlurExtensions.cs b/src/ImageSharp/Processing/BoxBlurExtensions.cs index 624da239b..bc6e06dd6 100644 --- a/src/ImageSharp/Processing/BoxBlurExtensions.cs +++ b/src/ImageSharp/Processing/BoxBlurExtensions.cs @@ -8,43 +8,37 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds box blurring extensions to the type. + /// Adds box blurring extensions to the type. /// public static class BoxBlurExtensions { /// /// Applies a box blur to the image. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext BoxBlur(this IImageProcessingContext source) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BoxBlurProcessor()); + public static IImageProcessingContext BoxBlur(this IImageProcessingContext source) + => source.ApplyProcessor(new BoxBlurProcessor()); /// /// Applies a box blur to the image. /// - /// The pixel format. /// The image this method extends. /// The 'radius' value representing the size of the area to sample. /// The . - public static IImageProcessingContext BoxBlur(this IImageProcessingContext source, int radius) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BoxBlurProcessor(radius)); + public static IImageProcessingContext BoxBlur(this IImageProcessingContext source, int radius) + => source.ApplyProcessor(new BoxBlurProcessor(radius)); /// /// Applies a box blur to the image. /// - /// The pixel format. /// The image this method extends. /// The 'radius' value representing the size of the area to sample. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext BoxBlur(this IImageProcessingContext source, int radius, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BoxBlurProcessor(radius), rectangle); + public static IImageProcessingContext BoxBlur(this IImageProcessingContext source, int radius, Rectangle rectangle) + => source.ApplyProcessor(new BoxBlurProcessor(radius), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/GaussianBlurExtensions.cs b/src/ImageSharp/Processing/GaussianBlurExtensions.cs index 165c4ce1a..1dab05457 100644 --- a/src/ImageSharp/Processing/GaussianBlurExtensions.cs +++ b/src/ImageSharp/Processing/GaussianBlurExtensions.cs @@ -8,43 +8,37 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds Gaussian blurring extensions to the type. + /// Adds Gaussian blurring extensions to the type. /// public static class GaussianBlurExtensions { /// /// Applies a Gaussian blur to the image. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source) - where TPixel : struct, IPixel - => source.ApplyProcessor(new GaussianBlurProcessor()); + public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source) + => source.ApplyProcessor(new GaussianBlurProcessor()); /// /// Applies a Gaussian blur to the image. /// - /// The pixel format. /// The image this method extends. /// The 'sigma' value representing the weight of the blur. /// The . - public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source, float sigma) - where TPixel : struct, IPixel - => source.ApplyProcessor(new GaussianBlurProcessor(sigma)); + public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source, float sigma) + => source.ApplyProcessor(new GaussianBlurProcessor(sigma)); /// /// Applies a Gaussian blur to the image. /// - /// The pixel format. /// The image this method extends. /// The 'sigma' value representing the weight of the blur. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source, float sigma, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new GaussianBlurProcessor(sigma), rectangle); + public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source, float sigma, Rectangle rectangle) + => source.ApplyProcessor(new GaussianBlurProcessor(sigma), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs index 3d5bdc42a..bb37489e1 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs @@ -3,67 +3,48 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Applies box blur processing to the image. + /// Defines a box blur processor of a given Radius. /// - /// The pixel format. - internal class BoxBlurProcessor : ImageProcessor - where TPixel : struct, IPixel + public class BoxBlurProcessor : IImageProcessor { /// - /// The maximum size of the kernel in either direction. + /// The default radius used by the parameterless constructor. /// - private readonly int kernelSize; + public const int DefaultRadius = 7; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// The 'radius' value representing the size of the area to sample. /// - public BoxBlurProcessor(int radius = 7) + public BoxBlurProcessor(int radius) { this.Radius = radius; - this.kernelSize = (radius * 2) + 1; - this.KernelX = this.CreateBoxKernel(); - this.KernelY = this.KernelX.Transpose(); } /// - /// Gets the Radius + /// Initializes a new instance of the class. /// - public int Radius { get; } - - /// - /// Gets the horizontal gradient operator. - /// - public DenseMatrix KernelX { get; } + public BoxBlurProcessor() + : this(DefaultRadius) + { + } /// - /// Gets the vertical gradient operator. + /// Gets the Radius. /// - public DenseMatrix KernelY { get; } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - => new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply(source, sourceRectangle, configuration); + public int Radius { get; } - /// - /// Create a 1 dimensional Box kernel. - /// - /// The - private DenseMatrix CreateBoxKernel() + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - int size = this.kernelSize; - var kernel = new DenseMatrix(size, 1); - - kernel.Fill(1F / size); - - return kernel; + return new BoxBlurProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs new file mode 100644 index 000000000..ba092cb42 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs @@ -0,0 +1,64 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + /// + /// Applies box blur processing to the image. + /// + /// The pixel format. + internal class BoxBlurProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly BoxBlurProcessor definition; + + /// + /// Initializes a new instance of the class. + /// + /// The defining the processor parameters. + public BoxBlurProcessor(BoxBlurProcessor definition) + { + this.definition = definition; + int kernelSize = (definition.Radius * 2) + 1; + this.KernelX = CreateBoxKernel(kernelSize); + this.KernelY = this.KernelX.Transpose(); + } + + /// + /// Gets the horizontal gradient operator. + /// + public DenseMatrix KernelX { get; } + + /// + /// Gets the vertical gradient operator. + /// + public DenseMatrix KernelY { get; } + + + /// + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) => + new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply( + source, + sourceRectangle, + configuration); + + /// + /// Create a 1 dimensional Box kernel. + /// + /// The maximum size of the kernel in either direction. + /// The . + private static DenseMatrix CreateBoxKernel(int kernelSize) + { + var kernel = new DenseMatrix(kernelSize, 1); + kernel.Fill(1F / kernelSize); + return kernel; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs index 0fc822d57..33e2ef955 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs @@ -4,35 +4,38 @@ using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Applies Gaussian blur processing to the image. + /// Defines a gaussian blur processor with a (Sigma, Radius) pair. /// - /// The pixel format. - internal class GaussianBlurProcessor : ImageProcessor - where TPixel : struct, IPixel + public class GaussianBlurProcessor : IImageProcessor { /// - /// The maximum size of the kernel in either direction. + /// The default value for . /// - private readonly int kernelSize; + public const float DefaultSigma = 3f; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. + /// + public GaussianBlurProcessor() + : this(DefaultSigma, CalculateDefaultRadius(DefaultSigma)) + { + } + + /// + /// Initializes a new instance of the class. /// /// The 'sigma' value representing the weight of the blur. - public GaussianBlurProcessor(float sigma = 3F) - : this(sigma, (int)MathF.Ceiling(sigma * 3)) + public GaussianBlurProcessor(float sigma) + : this(sigma, CalculateDefaultRadius(sigma)) { - // Kernel radius is calculated using the minimum viable value. - // http://chemaguerra.com/gaussian-filter-radius/ } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// The 'radius' value representing the size of the area to sample. @@ -43,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// The 'sigma' value representing the weight of the blur. @@ -54,10 +57,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// public GaussianBlurProcessor(float sigma, int radius) { - this.kernelSize = (radius * 2) + 1; this.Sigma = sigma; - this.KernelX = this.CreateGaussianKernel(); - this.KernelY = this.KernelX.Transpose(); + this.Radius = radius; } /// @@ -66,47 +67,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution public float Sigma { get; } /// - /// Gets the horizontal gradient operator. - /// - public DenseMatrix KernelX { get; } - - /// - /// Gets the vertical gradient operator. + /// Gets the radius defining the size of the area to sample. /// - public DenseMatrix KernelY { get; } + public int Radius { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - => new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply(source, sourceRectangle, configuration); + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + return new GaussianBlurProcessor(this); + } /// - /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function + /// Kernel radius is calculated using the minimum viable value. + /// . /// - /// The - private DenseMatrix CreateGaussianKernel() + private static int CalculateDefaultRadius(float sigma) { - int size = this.kernelSize; - float weight = this.Sigma; - var kernel = new DenseMatrix(size, 1); - - float sum = 0F; - float midpoint = (size - 1) / 2F; - - for (int i = 0; i < size; i++) - { - float x = i - midpoint; - float gx = ImageMaths.Gaussian(x, weight); - sum += gx; - kernel[0, i] = gx; - } - - // Normalize kernel so that the sum of all weights equals 1 - for (int i = 0; i < size; i++) - { - kernel[0, i] /= sum; - } - - return kernel; + return (int)MathF.Ceiling(sigma * 3); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs new file mode 100644 index 000000000..9b60fb2d2 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs @@ -0,0 +1,79 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + /// + /// Applies Gaussian blur processing to an image. + /// + /// The pixel format. + internal class GaussianBlurProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly GaussianBlurProcessor definition; + + /// + /// Initializes a new instance of the class. + /// + /// The defining the processor parameters. + public GaussianBlurProcessor(GaussianBlurProcessor definition) + { + this.definition = definition; + int kernelSize = (definition.Radius * 2) + 1; + this.KernelX = CreateGaussianKernel(kernelSize, definition.Sigma); + this.KernelY = this.KernelX.Transpose(); + } + + /// + /// Gets the horizontal gradient operator. + /// + public DenseMatrix KernelX { get; } + + /// + /// Gets the vertical gradient operator. + /// + public DenseMatrix KernelY { get; } + + /// + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) => + new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply( + source, + sourceRectangle, + configuration); + + /// + /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function + /// + /// The + private static DenseMatrix CreateGaussianKernel(int size, float weight) + { + var kernel = new DenseMatrix(size, 1); + + float sum = 0F; + float midpoint = (size - 1) / 2F; + + for (int i = 0; i < size; i++) + { + float x = i - midpoint; + float gx = ImageMaths.Gaussian(x, weight); + sum += gx; + kernel[0, i] = gx; + } + + // Normalize kernel so that the sum of all weights equals 1 + for (int i = 0; i < size; i++) + { + kernel[0, i] /= sum; + } + + return kernel; + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs index e425b6315..8c659848f 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution public void BoxBlur_BoxBlurProcessorDefaultsSet() { this.operations.BoxBlur(); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(7, processor.Radius); } @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution public void BoxBlur_amount_BoxBlurProcessorDefaultsSet() { this.operations.BoxBlur(34); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(34, processor.Radius); } @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution public void BoxBlur_amount_rect_BoxBlurProcessorDefaultsSet() { this.operations.BoxBlur(5, this.rect); - var processor = this.Verify>(this.rect); + var processor = this.Verify(this.rect); Assert.Equal(5, processor.Radius); } diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs index c87a834eb..0f64ebbeb 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution public void GaussianBlur_GaussianBlurProcessorDefaultsSet() { this.operations.GaussianBlur(); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(3f, processor.Sigma); } @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution public void GaussianBlur_amount_GaussianBlurProcessorDefaultsSet() { this.operations.GaussianBlur(0.2f); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(.2f, processor.Sigma); } @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution public void GaussianBlur_amount_rect_GaussianBlurProcessorDefaultsSet() { this.operations.GaussianBlur(0.6f, this.rect); - var processor = this.Verify>(this.rect); + var processor = this.Verify(this.rect); Assert.Equal(.6f, processor.Sigma); } From c198ad544debe0a50bc06fd720c0801df1e2e719 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 23:27:28 +0200 Subject: [PATCH 125/223] making filters public --- .../Filters/AchromatomalyProcessor.cs | 2 +- .../Filters/AchromatopsiaProcessor.cs | 2 +- .../Processors/Filters/BlackWhiteProcessor.cs | 4 +- .../Processors/Filters/BrightnessProcessor.cs | 2 +- .../Processors/Filters/ContrastProcessor.cs | 4 +- .../Filters/DeuteranomalyProcessor.cs | 2 +- .../Filters/DeuteranopiaProcessor.cs | 2 +- .../Processors/Filters/FilterProcessor.cs | 4 +- .../Filters/GrayscaleBt601Processor.cs | 2 +- .../Filters/GrayscaleBt709Processor.cs | 2 +- .../Processors/Filters/HueProcessor.cs | 2 +- .../Processors/Filters/InvertProcessor.cs | 2 +- .../Processors/Filters/KodachromeProcessor.cs | 2 +- .../Processors/Filters/LomographProcessor.cs | 3 +- .../Filters/LomographProcessor{TPixel}.cs | 4 ++ .../Processors/Filters/OpacityProcessor.cs | 4 +- .../Filters/PolaroidProcessor{TPixel}.cs | 6 +- .../Filters/ProtanomalyProcessor.cs | 2 +- .../Processors/Filters/ProtanopiaProcessor.cs | 2 +- .../Processors/Filters/SaturateProcessor.cs | 2 +- .../Processors/Filters/SepiaProcessor.cs | 2 +- .../Filters/TritanomalyProcessor.cs | 2 +- .../Processors/Filters/TritanopiaProcessor.cs | 2 +- .../Processing/Processors/IImageProcessor.cs | 56 +------------------ .../Processors/IImageProcessor{TPixel}.cs | 31 ++++++++++ .../Processors/ImageProcessorExtensions.cs | 37 ++++++++++++ 26 files changed, 106 insertions(+), 79 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/IImageProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs diff --git a/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs index 2dac6b827..7c3789c38 100644 --- a/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness. /// - internal class AchromatomalyProcessor : FilterProcessor + public class AchromatomalyProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs index 4df94a760..ab04a30ba 100644 --- a/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness. /// - internal class AchromatopsiaProcessor : FilterProcessor + public class AchromatopsiaProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs index 698f11cbf..7e2e7f2f4 100644 --- a/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs @@ -6,9 +6,9 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// - /// Applies a black and white filter matrix to the image + /// Applies a black and white filter matrix to the image. /// - internal class BlackWhiteProcessor : FilterProcessor + public class BlackWhiteProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs index 6a1f3869a..94a7a394a 100644 --- a/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a brightness filter matrix using the given amount. /// - internal class BrightnessProcessor : FilterProcessor + public class BrightnessProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs index 3bea695b9..1f74a1d64 100644 --- a/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a contrast filter matrix using the given amount. /// - internal class ContrastProcessor : FilterProcessor + public class ContrastProcessor : FilterProcessor { /// /// Initializes a new instance of the class. @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters } /// - /// Gets the proportion of the conversion + /// Gets the proportion of the conversion. /// public float Amount { get; } } diff --git a/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs index 395489d56..7ad0630aa 100644 --- a/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Deuteranomaly (Green-Weak) color blindness. /// - internal class DeuteranomalyProcessor : FilterProcessor + public class DeuteranomalyProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs index 51f8361e6..188d02dc8 100644 --- a/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Deuteranopia (Green-Blind) color blindness. /// - internal class DeuteranopiaProcessor : FilterProcessor + public class DeuteranopiaProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs index b615b7bc6..36c43d844 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; @@ -7,7 +7,7 @@ using SixLabors.ImageSharp.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// - /// Provides methods that accept a matrix to apply free-form filters to images. + /// Defines a free-form color filter by a . /// public class FilterProcessor : IImageProcessor { diff --git a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs index b39e01b9a..c24992b44 100644 --- a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a grayscale filter matrix using the given amount and the formula as specified by ITU-R Recommendation BT.601 /// - internal class GrayscaleBt601Processor : FilterProcessor + public class GrayscaleBt601Processor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs index 7bbd91556..dc5294ccf 100644 --- a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a grayscale filter matrix using the given amount and the formula as specified by ITU-R Recommendation BT.709 /// - internal class GrayscaleBt709Processor : FilterProcessor + public class GrayscaleBt709Processor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs index a69fd5075..65f7eef33 100644 --- a/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a hue filter matrix using the given angle of rotation in degrees /// - internal class HueProcessor : FilterProcessor + public class HueProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs index d7631970d..cc41e6572 100644 --- a/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a filter matrix that inverts the colors of an image /// - internal class InvertProcessor : FilterProcessor + public class InvertProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs index 5570f23d7..a5215a434 100644 --- a/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a filter matrix recreating an old Kodachrome camera effect matrix to the image /// - internal class KodachromeProcessor : FilterProcessor + public class KodachromeProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs index b102f4daf..dae168e2c 100644 --- a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs @@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating an old Lomograph effect. /// - internal class LomographProcessor : FilterProcessor + public class LomographProcessor : FilterProcessor { /// /// Initializes a new instance of the class. @@ -16,6 +16,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters { } + /// public override IImageProcessor CreatePixelSpecificProcessor() => new LomographProcessor(this); } diff --git a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs index 8ec4ec258..c15cf6fc9 100644 --- a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs @@ -15,6 +15,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters { private static readonly TPixel VeryDarkGreen = ColorBuilder.FromRGBA(0, 10, 0, 255); + /// + /// Initializes a new instance of the class. + /// + /// The defining the parameters. public LomographProcessor(LomographProcessor definition) : base(definition) { diff --git a/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs index e790753f3..0ee5dd59e 100644 --- a/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies an opacity filter matrix using the given amount. /// - internal class OpacityProcessor : FilterProcessor + public class OpacityProcessor : FilterProcessor { /// /// Initializes a new instance of the class. @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters } /// - /// Gets the proportion of the conversion + /// Gets the proportion of the conversion. /// public float Amount { get; } } diff --git a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs index a73aa28de..befcfc1f4 100644 --- a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs @@ -16,7 +16,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters private static readonly TPixel VeryDarkOrange = ColorBuilder.FromRGB(102, 34, 0); private static readonly TPixel LightOrange = ColorBuilder.FromRGBA(255, 153, 102, 128); - public PolaroidProcessor(FilterProcessor definition) + /// + /// Initializes a new instance of the class. + /// + /// The defining the parameters. + public PolaroidProcessor(PolaroidProcessor definition) : base(definition) { } diff --git a/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs index 95e369b37..755bc0f81 100644 --- a/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Protanomaly (Red-Weak) color blindness. /// - internal class ProtanomalyProcessor : FilterProcessor + public class ProtanomalyProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs index bd9257913..c4f4a7661 100644 --- a/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Protanopia (Red-Blind) color blindness. /// - internal class ProtanopiaProcessor : FilterProcessor + public class ProtanopiaProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs index 424eeb461..770fb9827 100644 --- a/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a saturation filter matrix using the given amount. /// - internal class SaturateProcessor : FilterProcessor + public class SaturateProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs index 538db4b52..9da48993a 100644 --- a/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a sepia filter matrix using the given amount. /// - internal class SepiaProcessor : FilterProcessor + public class SepiaProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs index 3eda05a11..c64475b99 100644 --- a/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Tritanomaly (Blue-Weak) color blindness. /// - internal class TritanomalyProcessor : FilterProcessor + public class TritanomalyProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs index f5ed26c83..722840e74 100644 --- a/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating Tritanopia (Blue-Blind) color blindness. /// - internal class TritanopiaProcessor : FilterProcessor + public class TritanopiaProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/IImageProcessor.cs b/src/ImageSharp/Processing/Processors/IImageProcessor.cs index e9b2c9c0e..9b030a6fe 100644 --- a/src/ImageSharp/Processing/Processors/IImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/IImageProcessor.cs @@ -2,12 +2,14 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors { /// /// Defines an algorithm to alter the pixels of an image. + /// Non-generic implementations are responsible for: + /// 1. Encapsulating the parameters of the algorithm. + /// 2. Creating the generic instance to execute the algorithm. /// public interface IImageProcessor { @@ -20,56 +22,4 @@ namespace SixLabors.ImageSharp.Processing.Processors IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel; } - - /// - /// Implements an algorithm to alter the pixels of an image. - /// - /// The pixel format. - public interface IImageProcessor - where TPixel : struct, IPixel - { - /// - /// Applies the process to the specified portion of the specified . - /// - /// The source image. Cannot be null. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// - /// is null. - /// - /// - /// doesn't fit the dimension of the image. - /// - void Apply(Image source, Rectangle sourceRectangle); - } - - internal static class ImageProcessorExtensions - { - public static void Apply(this IImageProcessor processor, Image source, Rectangle sourceRectangle) - { - var visitor = new ApplyVisitor(processor, sourceRectangle); - source.AcceptVisitor(visitor); - } - - private class ApplyVisitor : IImageVisitor - { - private readonly IImageProcessor processor; - - private readonly Rectangle sourceRectangle; - - public ApplyVisitor(IImageProcessor processor, Rectangle sourceRectangle) - { - this.processor = processor; - this.sourceRectangle = sourceRectangle; - } - - public void Visit(Image image) - where TPixel : struct, IPixel - { - var processorImpl = this.processor.CreatePixelSpecificProcessor(); - processorImpl.Apply(image, this.sourceRectangle); - } - } - } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/IImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/IImageProcessor{TPixel}.cs new file mode 100644 index 000000000..f2c7ef29c --- /dev/null +++ b/src/ImageSharp/Processing/Processors/IImageProcessor{TPixel}.cs @@ -0,0 +1,31 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors +{ + /// + /// Implements an algorithm to alter the pixels of an image. + /// + /// The pixel format. + public interface IImageProcessor + where TPixel : struct, IPixel + { + /// + /// Applies the process to the specified portion of the specified . + /// + /// The source image. Cannot be null. + /// + /// The structure that specifies the portion of the image object to draw. + /// + /// + /// is null. + /// + /// + /// doesn't fit the dimension of the image. + /// + void Apply(Image source, Rectangle sourceRectangle); + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs b/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs new file mode 100644 index 000000000..1e189b9c7 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs @@ -0,0 +1,37 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors +{ + internal static class ImageProcessorExtensions + { + public static void Apply(this IImageProcessor processor, Image source, Rectangle sourceRectangle) + { + var visitor = new ApplyVisitor(processor, sourceRectangle); + source.AcceptVisitor(visitor); + } + + private class ApplyVisitor : IImageVisitor + { + private readonly IImageProcessor processor; + + private readonly Rectangle sourceRectangle; + + public ApplyVisitor(IImageProcessor processor, Rectangle sourceRectangle) + { + this.processor = processor; + this.sourceRectangle = sourceRectangle; + } + + public void Visit(Image image) + where TPixel : struct, IPixel + { + var processorImpl = this.processor.CreatePixelSpecificProcessor(); + processorImpl.Apply(image, this.sourceRectangle); + } + } + } +} \ No newline at end of file From a117dbb873afaa993b56b8630a7817f4f67ab114 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 4 May 2019 23:53:00 +0200 Subject: [PATCH 126/223] Further refactor on Gaussian stuff --- .../Processing/GaussianSharpenExtensions.cs | 26 ++--- .../ConvolutionProcessorHelpers.cs | 93 ++++++++++++++++ .../Convolution/GaussianBlurProcessor.cs | 16 +-- .../GaussianBlurProcessor{TPixel}.cs | 37 +------ .../Convolution/GaussianSharpenProcessor.cs | 101 +++++------------- .../GaussianSharpenProcessor{TPixel}.cs | 42 ++++++++ .../Convolution/GaussianSharpenTest.cs | 6 +- 7 files changed, 180 insertions(+), 141 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs create mode 100644 src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs diff --git a/src/ImageSharp/Processing/GaussianSharpenExtensions.cs b/src/ImageSharp/Processing/GaussianSharpenExtensions.cs index 675bbc142..64aa7b5db 100644 --- a/src/ImageSharp/Processing/GaussianSharpenExtensions.cs +++ b/src/ImageSharp/Processing/GaussianSharpenExtensions.cs @@ -1,50 +1,46 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Convolution; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds Gaussian sharpening extensions to the type. + /// Adds Gaussian sharpening extensions to the type. /// public static class GaussianSharpenExtensions { /// /// Applies a Gaussian sharpening filter to the image. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source) - where TPixel : struct, IPixel - => source.ApplyProcessor(new GaussianSharpenProcessor()); + public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source) => + source.ApplyProcessor(new GaussianSharpenProcessor()); /// /// Applies a Gaussian sharpening filter to the image. /// - /// The pixel format. /// The image this method extends. /// The 'sigma' value representing the weight of the blur. /// The . - public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source, float sigma) - where TPixel : struct, IPixel - => source.ApplyProcessor(new GaussianSharpenProcessor(sigma)); + public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source, float sigma) => + source.ApplyProcessor(new GaussianSharpenProcessor(sigma)); /// /// Applies a Gaussian sharpening filter to the image. /// - /// The pixel format. /// The image this method extends. /// The 'sigma' value representing the weight of the blur. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source, float sigma, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new GaussianSharpenProcessor(sigma), rectangle); + public static IImageProcessingContext GaussianSharpen( + this IImageProcessingContext source, + float sigma, + Rectangle rectangle) => + source.ApplyProcessor(new GaussianSharpenProcessor(sigma), rectangle); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs new file mode 100644 index 000000000..bb0072b82 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs @@ -0,0 +1,93 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + internal static class ConvolutionProcessorHelpers + { + /// + /// Kernel radius is calculated using the minimum viable value. + /// . + /// + internal static int GetDefaultGaussianRadius(float sigma) + { + return (int)MathF.Ceiling(sigma * 3); + } + + /// + /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function + /// + /// The . + internal static DenseMatrix CreateGaussianBlurKernel(int size, float weight) + { + var kernel = new DenseMatrix(size, 1); + + float sum = 0F; + float midpoint = (size - 1) / 2F; + + for (int i = 0; i < size; i++) + { + float x = i - midpoint; + float gx = ImageMaths.Gaussian(x, weight); + sum += gx; + kernel[0, i] = gx; + } + + // Normalize kernel so that the sum of all weights equals 1 + for (int i = 0; i < size; i++) + { + kernel[0, i] /= sum; + } + + return kernel; + } + + /// + /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function + /// + /// The . + internal static DenseMatrix CreateGaussianSharpenKernel(int size, float weight) + { + var kernel = new DenseMatrix(size, 1); + + float sum = 0; + + float midpoint = (size - 1) / 2F; + for (int i = 0; i < size; i++) + { + float x = i - midpoint; + float gx = ImageMaths.Gaussian(x, weight); + sum += gx; + kernel[0, i] = gx; + } + + // Invert the kernel for sharpening. + int midpointRounded = (int)midpoint; + for (int i = 0; i < size; i++) + { + if (i == midpointRounded) + { + // Calculate central value + kernel[0, i] = (2F * sum) - kernel[0, i]; + } + else + { + // invert value + kernel[0, i] = -kernel[0, i]; + } + } + + // Normalize kernel so that the sum of all weights equals 1 + for (int i = 0; i < size; i++) + { + kernel[0, i] /= sum; + } + + return kernel; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs index 33e2ef955..c64a024f9 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs @@ -1,14 +1,13 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Defines a gaussian blur processor with a (Sigma, Radius) pair. + /// Defines Gaussian blur by a (Sigma, Radius) pair. /// public class GaussianBlurProcessor : IImageProcessor { @@ -21,7 +20,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Initializes a new instance of the class. /// public GaussianBlurProcessor() - : this(DefaultSigma, CalculateDefaultRadius(DefaultSigma)) + : this(DefaultSigma, ConvolutionProcessorHelpers.GetDefaultGaussianRadius(DefaultSigma)) { } @@ -30,7 +29,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// The 'sigma' value representing the weight of the blur. public GaussianBlurProcessor(float sigma) - : this(sigma, CalculateDefaultRadius(sigma)) + : this(sigma, ConvolutionProcessorHelpers.GetDefaultGaussianRadius(sigma)) { } @@ -77,14 +76,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { return new GaussianBlurProcessor(this); } - - /// - /// Kernel radius is calculated using the minimum viable value. - /// . - /// - private static int CalculateDefaultRadius(float sigma) - { - return (int)MathF.Ceiling(sigma * 3); - } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs index 9b60fb2d2..a129ff547 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs @@ -1,5 +1,5 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; @@ -14,17 +14,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution internal class GaussianBlurProcessor : ImageProcessor where TPixel : struct, IPixel { - private readonly GaussianBlurProcessor definition; - /// /// Initializes a new instance of the class. /// /// The defining the processor parameters. public GaussianBlurProcessor(GaussianBlurProcessor definition) { - this.definition = definition; int kernelSize = (definition.Radius * 2) + 1; - this.KernelX = CreateGaussianKernel(kernelSize, definition.Sigma); + this.KernelX = ConvolutionProcessorHelpers.CreateGaussianBlurKernel(kernelSize, definition.Sigma); this.KernelY = this.KernelX.Transpose(); } @@ -47,33 +44,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution source, sourceRectangle, configuration); - - /// - /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function - /// - /// The - private static DenseMatrix CreateGaussianKernel(int size, float weight) - { - var kernel = new DenseMatrix(size, 1); - - float sum = 0F; - float midpoint = (size - 1) / 2F; - - for (int i = 0; i < size; i++) - { - float x = i - midpoint; - float gx = ImageMaths.Gaussian(x, weight); - sum += gx; - kernel[0, i] = gx; - } - - // Normalize kernel so that the sum of all weights equals 1 - for (int i = 0; i < size; i++) - { - kernel[0, i] /= sum; - } - - return kernel; - } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs index 001471720..bc06ee618 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs @@ -3,38 +3,38 @@ using System; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Applies Gaussian sharpening processing to the image. + /// Defines Gaussian sharpening by a (Sigma, Radius) pair. /// - /// The pixel format. - internal class GaussianSharpenProcessor : ImageProcessor - where TPixel : struct, IPixel + public class GaussianSharpenProcessor : IImageProcessor { + /// + /// The default value for . + /// + public const float DefaultSigma = 3f; + /// - /// The maximum size of the kernel in either direction. + /// Initializes a new instance of the class. /// - private readonly int kernelSize; + public GaussianSharpenProcessor() + : this(DefaultSigma, ConvolutionProcessorHelpers.GetDefaultGaussianRadius(DefaultSigma)) + { + } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// - /// The 'sigma' value representing the weight of the sharpening. - /// - public GaussianSharpenProcessor(float sigma = 3F) - : this(sigma, (int)MathF.Ceiling(sigma * 3)) + /// The 'sigma' value representing the weight of the blur. + public GaussianSharpenProcessor(float sigma) + : this(sigma, ConvolutionProcessorHelpers.GetDefaultGaussianRadius(sigma)) { - // Kernel radius is calculated using the minimum viable value. - // http://chemaguerra.com/gaussian-filter-radius/ } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// The 'radius' value representing the size of the area to sample. @@ -45,10 +45,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// - /// The 'sigma' value representing the weight of the sharpen. + /// The 'sigma' value representing the weight of the blur. /// /// /// The 'radius' value representing the size of the area to sample. @@ -56,10 +56,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// public GaussianSharpenProcessor(float sigma, int radius) { - this.kernelSize = (radius * 2) + 1; this.Sigma = sigma; - this.KernelX = this.CreateGaussianKernel(); - this.KernelY = this.KernelX.Transpose(); + this.Radius = radius; } /// @@ -68,63 +66,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution public float Sigma { get; } /// - /// Gets the horizontal gradient operator. - /// - public DenseMatrix KernelX { get; } - - /// - /// Gets the vertical gradient operator. + /// Gets the radius defining the size of the area to sample. /// - public DenseMatrix KernelY { get; } + public int Radius { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - => new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply(source, sourceRectangle, configuration); - - /// - /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function - /// - /// The - private DenseMatrix CreateGaussianKernel() + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - int size = this.kernelSize; - float weight = this.Sigma; - var kernel = new DenseMatrix(size, 1); - - float sum = 0; - - float midpoint = (size - 1) / 2F; - for (int i = 0; i < size; i++) - { - float x = i - midpoint; - float gx = ImageMaths.Gaussian(x, weight); - sum += gx; - kernel[0, i] = gx; - } - - // Invert the kernel for sharpening. - int midpointRounded = (int)midpoint; - for (int i = 0; i < size; i++) - { - if (i == midpointRounded) - { - // Calculate central value - kernel[0, i] = (2F * sum) - kernel[0, i]; - } - else - { - // invert value - kernel[0, i] = -kernel[0, i]; - } - } - - // Normalize kernel so that the sum of all weights equals 1 - for (int i = 0; i < size; i++) - { - kernel[0, i] /= sum; - } - - return kernel; + return new GaussianSharpenProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs new file mode 100644 index 000000000..edde9f9e7 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs @@ -0,0 +1,42 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + /// + /// Applies Gaussian sharpening processing to the image. + /// + /// The pixel format. + internal class GaussianSharpenProcessor : ImageProcessor + where TPixel : struct, IPixel + { + /// + /// Initializes a new instance of the class. + /// + /// The defining the processor parameters. + public GaussianSharpenProcessor(GaussianSharpenProcessor definition) + { + int kernelSize = (definition.Radius * 2) + 1; + this.KernelX = ConvolutionProcessorHelpers.CreateGaussianSharpenKernel(kernelSize, definition.Sigma); + this.KernelY = this.KernelX.Transpose(); + } + + /// + /// Gets the horizontal gradient operator. + /// + public DenseMatrix KernelX { get; } + + /// + /// Gets the vertical gradient operator. + /// + public DenseMatrix KernelY { get; } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + => new Convolution2PassProcessor(this.KernelX, this.KernelY, false).Apply(source, sourceRectangle, configuration); + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs index 675498745..7c2205f4e 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution public void GaussianSharpen_GaussianSharpenProcessorDefaultsSet() { this.operations.GaussianSharpen(); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(3f, processor.Sigma); } @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution public void GaussianSharpen_amount_GaussianSharpenProcessorDefaultsSet() { this.operations.GaussianSharpen(0.2f); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(.2f, processor.Sigma); } @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution public void GaussianSharpen_amount_rect_GaussianSharpenProcessorDefaultsSet() { this.operations.GaussianSharpen(0.6f, this.rect); - var processor = this.Verify>(this.rect); + var processor = this.Verify(this.rect); Assert.Equal(.6f, processor.Sigma); } From d050f652a82891572120b7c77797281ab9263b3d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 00:18:23 +0200 Subject: [PATCH 127/223] drop IEdgeDetectorProcessor --- .../Processing/DetectEdgesExtensions.cs | 9 +++--- .../Convolution/BoxBlurProcessor{TPixel}.cs | 5 ++-- .../ConvolutionProcessorHelpers.cs | 8 +++--- .../Convolution/EdgeDetector2DProcessor.cs | 2 +- .../EdgeDetectorCompassProcessor.cs | 2 +- .../Convolution/EdgeDetectorProcessor.cs | 2 +- .../Convolution/GaussianSharpenProcessor.cs | 1 + .../Convolution/IEdgeDetectorProcessor.cs | 28 ------------------- .../Processors/IImageProcessor{TPixel}.cs | 4 +-- .../Processors/ImageProcessorExtensions.cs | 4 +-- .../Transforms/Resize/ResizeProcessor.cs | 2 +- .../Processing/Convolution/DetectEdgesTest.cs | 4 +-- 12 files changed, 22 insertions(+), 49 deletions(-) delete mode 100644 src/ImageSharp/Processing/Processors/Convolution/IEdgeDetectorProcessor.cs diff --git a/src/ImageSharp/Processing/DetectEdgesExtensions.cs b/src/ImageSharp/Processing/DetectEdgesExtensions.cs index 5ac89df29..a3be298d0 100644 --- a/src/ImageSharp/Processing/DetectEdgesExtensions.cs +++ b/src/ImageSharp/Processing/DetectEdgesExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors; using SixLabors.ImageSharp.Processing.Processors.Convolution; using SixLabors.Primitives; @@ -82,7 +83,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The filter for detecting edges. /// The . - public static IImageProcessingContext DetectEdges(this IImageProcessingContext source, IEdgeDetectorProcessor filter) + private static IImageProcessingContext DetectEdges(this IImageProcessingContext source, IImageProcessor filter) where TPixel : struct, IPixel { return source.ApplyProcessor(filter); @@ -98,17 +99,17 @@ namespace SixLabors.ImageSharp.Processing /// /// The filter for detecting edges. /// The . - public static IImageProcessingContext DetectEdges(this IImageProcessingContext source, Rectangle rectangle, IEdgeDetectorProcessor filter) + private static IImageProcessingContext DetectEdges(this IImageProcessingContext source, Rectangle rectangle, IImageProcessor filter) where TPixel : struct, IPixel { source.ApplyProcessor(filter, rectangle); return source; } - private static IEdgeDetectorProcessor GetProcessor(EdgeDetectionOperators filter, bool grayscale) + private static IImageProcessor GetProcessor(EdgeDetectionOperators filter, bool grayscale) where TPixel : struct, IPixel { - IEdgeDetectorProcessor processor; + IImageProcessor processor; switch (filter) { diff --git a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs index ba092cb42..f4252e840 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs @@ -1,5 +1,5 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; @@ -38,7 +38,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// public DenseMatrix KernelY { get; } - /// protected override void OnFrameApply( ImageFrame source, diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs index bb0072b82..1fb26c976 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs @@ -1,5 +1,5 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. using System; @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// /// Kernel radius is calculated using the minimum viable value. - /// . + /// See http://chemaguerra.com/gaussian-filter-radius/ . /// internal static int GetDefaultGaussianRadius(float sigma) { @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution } /// - /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function + /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function. /// /// The . internal static DenseMatrix CreateGaussianBlurKernel(int size, float weight) diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs index b4ac89139..ef185a01f 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines a processor that detects edges within an image using two one-dimensional matrices. /// /// The pixel format. - internal abstract class EdgeDetector2DProcessor : ImageProcessor, IEdgeDetectorProcessor + internal abstract class EdgeDetector2DProcessor : ImageProcessor where TPixel : struct, IPixel { /// diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs index aa33699f5..1205b02dc 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines a processor that detects edges within an image using a eight two dimensional matrices. /// /// The pixel format. - internal abstract class EdgeDetectorCompassProcessor : ImageProcessor, IEdgeDetectorProcessor + internal abstract class EdgeDetectorCompassProcessor : ImageProcessor where TPixel : struct, IPixel { /// diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs index 9ec79da9e..b4d4763d0 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines a processor that detects edges within an image using a single two dimensional matrix. /// /// The pixel format. - internal abstract class EdgeDetectorProcessor : ImageProcessor, IEdgeDetectorProcessor + internal abstract class EdgeDetectorProcessor : ImageProcessor where TPixel : struct, IPixel { /// diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs index bc06ee618..84e56869d 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs @@ -70,6 +70,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// public int Radius { get; } + /// public IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel { diff --git a/src/ImageSharp/Processing/Processors/Convolution/IEdgeDetectorProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/IEdgeDetectorProcessor.cs deleted file mode 100644 index b2ecbf115..000000000 --- a/src/ImageSharp/Processing/Processors/Convolution/IEdgeDetectorProcessor.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors; - -namespace SixLabors.ImageSharp.Processing.Processors.Convolution -{ - /// - /// Provides properties and methods allowing the detection of edges within an image. - /// - /// The pixel format. - public interface IEdgeDetectorProcessor : IImageProcessor, IEdgeDetectorProcessor - where TPixel : struct, IPixel - { - } - - /// - /// Provides properties and methods allowing the detection of edges within an image. - /// - public interface IEdgeDetectorProcessor - { - /// - /// Gets a value indicating whether to convert the image to grayscale before performing edge detection. - /// - bool Grayscale { get; } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/IImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/IImageProcessor{TPixel}.cs index f2c7ef29c..90dfaf8db 100644 --- a/src/ImageSharp/Processing/Processors/IImageProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/IImageProcessor{TPixel}.cs @@ -1,5 +1,5 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs b/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs index 1e189b9c7..762d761c6 100644 --- a/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs +++ b/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs @@ -1,5 +1,5 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 5710c4bd8..8762d6b26 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -9,7 +9,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Implements resizing of images using various resamplers. + /// Defines an image resizing operation with the given and dimensional parameters. /// public class ResizeProcessor : IImageProcessor { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs index 60fa19b49..cf5feac27 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution [Theory] [MemberData(nameof(EdgeDetectionTheoryData))] public void DetectEdges_filter_SobelProcessorDefaultsSet(TestType type, EdgeDetectionOperators filter) - where TProcessor : IEdgeDetectorProcessor + where TProcessor : IImageProcessor { this.operations.DetectEdges(filter); @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution [Theory] [MemberData(nameof(EdgeDetectionTheoryData))] public void DetectEdges_filter_grayscale_SobelProcessorDefaultsSet(TestType type, EdgeDetectionOperators filter) - where TProcessor : IEdgeDetectorProcessor + where TProcessor : IImageProcessor { bool grey = (int)filter % 2 == 0; this.operations.DetectEdges(filter, grey); From d8bdac61a0b04df2396624fce1915abb3ecce4d3 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 01:10:24 +0200 Subject: [PATCH 128/223] Refactor edge detection --- src/ImageSharp/ImageSharp.csproj.DotSettings | 1 + .../Processing/DetectEdgesExtensions.cs | 96 +++++++++---------- .../ConvolutionProcessorHelpers.cs | 2 +- .../Convolution/EdgeDetector2DProcessor.cs | 5 +- .../EdgeDetectorCompassProcessor.cs | 54 ++--------- .../Convolution/EdgeDetectorProcessor.cs | 37 ++----- .../EdgeDetectorProcessor{TPixel}.cs | 49 ++++++++++ .../Convolution/KayyaliProcessor.cs | 22 +++-- .../Convolution/Kernels/CompassKernels.cs | 57 +++++++++++ .../{ => Kernels}/KayyaliKernels.cs | 0 .../{ => Kernels}/KirschKernels.cs | 18 ++-- .../{ => Kernels}/LaplacianKernelFactory.cs | 0 .../{ => Kernels}/LaplacianKernels.cs | 0 .../{ => Kernels}/PrewittKernels.cs | 0 .../{ => Kernels}/RobertsCrossKernels.cs | 0 .../{ => Kernels}/RobinsonKernels.cs | 20 ++-- .../{ => Kernels}/ScharrKernels.cs | 0 .../Convolution/{ => Kernels}/SobelKernels.cs | 0 .../Processors/Convolution/KirschProcessor.cs | 40 ++------ .../Convolution/Laplacian3x3Processor.cs | 14 ++- .../Convolution/Laplacian5x5Processor.cs | 20 ++-- .../LaplacianOfGaussianProcessor.cs | 18 ++-- .../Convolution/PrewittProcessor.cs | 20 ++-- .../Convolution/RobertsCrossProcessor.cs | 18 ++-- .../Convolution/RobinsonProcessor.cs | 38 ++------ .../Processors/Convolution/ScharrProcessor.cs | 16 ++-- .../Processors/Convolution/SobelProcessor.cs | 27 ++++-- .../Transforms/EntropyCropProcessor.cs | 2 +- .../Processing/Convolution/DetectEdgesTest.cs | 40 ++++---- 29 files changed, 329 insertions(+), 285 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Convolution/Kernels/CompassKernels.cs rename src/ImageSharp/Processing/Processors/Convolution/{ => Kernels}/KayyaliKernels.cs (100%) rename src/ImageSharp/Processing/Processors/Convolution/{ => Kernels}/KirschKernels.cs (81%) rename src/ImageSharp/Processing/Processors/Convolution/{ => Kernels}/LaplacianKernelFactory.cs (100%) rename src/ImageSharp/Processing/Processors/Convolution/{ => Kernels}/LaplacianKernels.cs (100%) rename src/ImageSharp/Processing/Processors/Convolution/{ => Kernels}/PrewittKernels.cs (100%) rename src/ImageSharp/Processing/Processors/Convolution/{ => Kernels}/RobertsCrossKernels.cs (100%) rename src/ImageSharp/Processing/Processors/Convolution/{ => Kernels}/RobinsonKernels.cs (78%) rename src/ImageSharp/Processing/Processors/Convolution/{ => Kernels}/ScharrKernels.cs (100%) rename src/ImageSharp/Processing/Processors/Convolution/{ => Kernels}/SobelKernels.cs (100%) diff --git a/src/ImageSharp/ImageSharp.csproj.DotSettings b/src/ImageSharp/ImageSharp.csproj.DotSettings index a7337240a..e446893e9 100644 --- a/src/ImageSharp/ImageSharp.csproj.DotSettings +++ b/src/ImageSharp/ImageSharp.csproj.DotSettings @@ -6,5 +6,6 @@ True True True + True True True \ No newline at end of file diff --git a/src/ImageSharp/Processing/DetectEdgesExtensions.cs b/src/ImageSharp/Processing/DetectEdgesExtensions.cs index a3be298d0..7527d601d 100644 --- a/src/ImageSharp/Processing/DetectEdgesExtensions.cs +++ b/src/ImageSharp/Processing/DetectEdgesExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; using SixLabors.ImageSharp.Processing.Processors.Convolution; using SixLabors.Primitives; @@ -9,82 +8,79 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds edge detection extensions to the type. + /// Adds edge detection extensions to the type. /// public static class DetectEdgesExtensions { /// - /// Detects any edges within the image. Uses the filter + /// Detects any edges within the image. Uses the filter /// operating in grayscale mode. /// - /// The pixel format. /// The image this method extends. - /// The . - public static IImageProcessingContext DetectEdges(this IImageProcessingContext source) - where TPixel : struct, IPixel - => DetectEdges(source, new SobelProcessor(true)); + /// The . + public static IImageProcessingContext DetectEdges(this IImageProcessingContext source) => + DetectEdges(source, new SobelProcessor(true)); /// - /// Detects any edges within the image. Uses the filter + /// Detects any edges within the image. Uses the filter /// operating in grayscale mode. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// - /// The . - public static IImageProcessingContext DetectEdges(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel - => DetectEdges(source, rectangle, new SobelProcessor(true)); + /// The . + public static IImageProcessingContext DetectEdges(this IImageProcessingContext source, Rectangle rectangle) => + DetectEdges(source, rectangle, new SobelProcessor(true)); /// /// Detects any edges within the image. /// - /// The pixel format. /// The image this method extends. /// The filter for detecting edges. - /// The . - public static IImageProcessingContext DetectEdges(this IImageProcessingContext source, EdgeDetectionOperators filter) - where TPixel : struct, IPixel - => DetectEdges(source, GetProcessor(filter, true)); + /// The . + public static IImageProcessingContext DetectEdges( + this IImageProcessingContext source, + EdgeDetectionOperators filter) => + DetectEdges(source, GetProcessor(filter, true)); /// /// Detects any edges within the image. /// - /// The pixel format. /// The image this method extends. /// The filter for detecting edges. /// Whether to convert the image to grayscale first. Defaults to true. - /// The . - public static IImageProcessingContext DetectEdges(this IImageProcessingContext source, EdgeDetectionOperators filter, bool grayscale) - where TPixel : struct, IPixel - => DetectEdges(source, GetProcessor(filter, grayscale)); + /// The . + public static IImageProcessingContext DetectEdges( + this IImageProcessingContext source, + EdgeDetectionOperators filter, + bool grayscale) => + DetectEdges(source, GetProcessor(filter, grayscale)); /// /// Detects any edges within the image. /// - /// The pixel format. /// The image this method extends. /// The filter for detecting edges. /// /// The structure that specifies the portion of the image object to alter. /// /// Whether to convert the image to grayscale first. Defaults to true. - /// The . - public static IImageProcessingContext DetectEdges(this IImageProcessingContext source, EdgeDetectionOperators filter, Rectangle rectangle, bool grayscale = true) - where TPixel : struct, IPixel - => DetectEdges(source, rectangle, GetProcessor(filter, grayscale)); + /// The . + public static IImageProcessingContext DetectEdges( + this IImageProcessingContext source, + EdgeDetectionOperators filter, + Rectangle rectangle, + bool grayscale = true) => + DetectEdges(source, rectangle, GetProcessor(filter, grayscale)); /// /// Detects any edges within the image. /// - /// The pixel format. /// The image this method extends. /// The filter for detecting edges. - /// The . - private static IImageProcessingContext DetectEdges(this IImageProcessingContext source, IImageProcessor filter) - where TPixel : struct, IPixel + /// The . + private static IImageProcessingContext DetectEdges(this IImageProcessingContext source, IImageProcessor filter) { return source.ApplyProcessor(filter); } @@ -92,65 +88,65 @@ namespace SixLabors.ImageSharp.Processing /// /// Detects any edges within the image. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// /// The filter for detecting edges. - /// The . - private static IImageProcessingContext DetectEdges(this IImageProcessingContext source, Rectangle rectangle, IImageProcessor filter) - where TPixel : struct, IPixel + /// The . + private static IImageProcessingContext DetectEdges( + this IImageProcessingContext source, + Rectangle rectangle, + IImageProcessor filter) { source.ApplyProcessor(filter, rectangle); return source; } - private static IImageProcessor GetProcessor(EdgeDetectionOperators filter, bool grayscale) - where TPixel : struct, IPixel + private static IImageProcessor GetProcessor(EdgeDetectionOperators filter, bool grayscale) { - IImageProcessor processor; + IImageProcessor processor; switch (filter) { case EdgeDetectionOperators.Kayyali: - processor = new KayyaliProcessor(grayscale); + processor = new KayyaliProcessor(grayscale); break; case EdgeDetectionOperators.Kirsch: - processor = new KirschProcessor(grayscale); + processor = new KirschProcessor(grayscale); break; case EdgeDetectionOperators.Laplacian3x3: - processor = new Laplacian3x3Processor(grayscale); + processor = new Laplacian3x3Processor(grayscale); break; case EdgeDetectionOperators.Laplacian5x5: - processor = new Laplacian5x5Processor(grayscale); + processor = new Laplacian5x5Processor(grayscale); break; case EdgeDetectionOperators.LaplacianOfGaussian: - processor = new LaplacianOfGaussianProcessor(grayscale); + processor = new LaplacianOfGaussianProcessor(grayscale); break; case EdgeDetectionOperators.Prewitt: - processor = new PrewittProcessor(grayscale); + processor = new PrewittProcessor(grayscale); break; case EdgeDetectionOperators.RobertsCross: - processor = new RobertsCrossProcessor(grayscale); + processor = new RobertsCrossProcessor(grayscale); break; case EdgeDetectionOperators.Robinson: - processor = new RobinsonProcessor(grayscale); + processor = new RobinsonProcessor(grayscale); break; case EdgeDetectionOperators.Scharr: - processor = new ScharrProcessor(grayscale); + processor = new ScharrProcessor(grayscale); break; default: - processor = new SobelProcessor(grayscale); + processor = new SobelProcessor(grayscale); break; } diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs index 1fb26c976..661ab523d 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// /// Kernel radius is calculated using the minimum viable value. - /// See http://chemaguerra.com/gaussian-filter-radius/ . + /// See . /// internal static int GetDefaultGaussianRadius(float sigma) { diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs index ef185a01f..5daf14fc3 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines a processor that detects edges within an image using two one-dimensional matrices. /// /// The pixel format. - internal abstract class EdgeDetector2DProcessor : ImageProcessor + internal class EdgeDetector2DProcessor : ImageProcessor where TPixel : struct, IPixel { /// @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// The horizontal gradient operator. /// The vertical gradient operator. /// Whether to convert the image to grayscale before performing edge detection. - protected EdgeDetector2DProcessor(in DenseMatrix kernelX, in DenseMatrix kernelY, bool grayscale) + internal EdgeDetector2DProcessor(in DenseMatrix kernelX, in DenseMatrix kernelY, bool grayscale) { Guard.IsTrue(kernelX.Size.Equals(kernelY.Size), $"{nameof(kernelX)} {nameof(kernelY)}", "Kernel sizes must be the same."); this.KernelX = kernelX; @@ -39,7 +39,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// public DenseMatrix KernelY { get; } - /// public bool Grayscale { get; } /// diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs index 1205b02dc..227003195 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs @@ -19,57 +19,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines a processor that detects edges within an image using a eight two dimensional matrices. /// /// The pixel format. - internal abstract class EdgeDetectorCompassProcessor : ImageProcessor + internal class EdgeDetectorCompassProcessor : ImageProcessor where TPixel : struct, IPixel { /// /// Initializes a new instance of the class. /// + /// Gets the kernels to use. /// Whether to convert the image to grayscale before performing edge detection. - protected EdgeDetectorCompassProcessor(bool grayscale) => this.Grayscale = grayscale; - - /// - /// Gets the North gradient operator - /// - public abstract DenseMatrix North { get; } - - /// - /// Gets the NorthWest gradient operator - /// - public abstract DenseMatrix NorthWest { get; } - - /// - /// Gets the West gradient operator - /// - public abstract DenseMatrix West { get; } - - /// - /// Gets the SouthWest gradient operator - /// - public abstract DenseMatrix SouthWest { get; } - - /// - /// Gets the South gradient operator - /// - public abstract DenseMatrix South { get; } - - /// - /// Gets the SouthEast gradient operator - /// - public abstract DenseMatrix SouthEast { get; } - - /// - /// Gets the East gradient operator - /// - public abstract DenseMatrix East { get; } + internal EdgeDetectorCompassProcessor(CompassKernels kernels, bool grayscale) + { + this.Grayscale = grayscale; + this.Kernels = kernels; + } - /// - /// Gets the NorthEast gradient operator - /// - public abstract DenseMatrix NorthEast { get; } + private CompassKernels Kernels { get; } - /// - public bool Grayscale { get; } + private bool Grayscale { get; } /// protected override void BeforeFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) @@ -83,7 +49,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { - DenseMatrix[] kernels = { this.North, this.NorthWest, this.West, this.SouthWest, this.South, this.SouthEast, this.East, this.NorthEast }; + DenseMatrix[] kernels = this.Kernels.Flatten(); int startY = sourceRectangle.Y; int endY = sourceRectangle.Bottom; diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs index b4d4763d0..75be15bcc 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor.cs @@ -2,49 +2,30 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing.Processors.Filters; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// /// Defines a processor that detects edges within an image using a single two dimensional matrix. /// - /// The pixel format. - internal abstract class EdgeDetectorProcessor : ImageProcessor - where TPixel : struct, IPixel + public abstract class EdgeDetectorProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The 2d gradient operator. - /// Whether to convert the image to grayscale before performing edge detection. - protected EdgeDetectorProcessor(in DenseMatrix kernelXY, bool grayscale) + /// A value indicating whether to convert the image to grayscale before performing edge detection. + protected EdgeDetectorProcessor(bool grayscale) { - this.KernelXY = kernelXY; this.Grayscale = grayscale; } - /// - public bool Grayscale { get; } - /// - /// Gets the 2d gradient operator. + /// Gets a value indicating whether to convert the image to grayscale before performing edge detection. /// - public DenseMatrix KernelXY { get; } - - /// - protected override void BeforeFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - if (this.Grayscale) - { - new GrayscaleBt709Processor(1F).ApplyToFrame(source, sourceRectangle, configuration); - } - } + public bool Grayscale { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - => new ConvolutionProcessor(this.KernelXY, true).Apply(source, sourceRectangle, configuration); + /// + public abstract IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel; } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs new file mode 100644 index 000000000..026313cc1 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs @@ -0,0 +1,49 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; +using SixLabors.ImageSharp.Processing.Processors.Filters; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + /// + /// Defines a processor that detects edges within an image using a single two dimensional matrix. + /// + /// The pixel format. + internal class EdgeDetectorProcessor : ImageProcessor + where TPixel : struct, IPixel + { + /// + /// Initializes a new instance of the class. + /// + /// The 2d gradient operator. + /// Whether to convert the image to grayscale before performing edge detection. + public EdgeDetectorProcessor(in DenseMatrix kernelXY, bool grayscale) + { + this.KernelXY = kernelXY; + this.Grayscale = grayscale; + } + + public bool Grayscale { get; } + + /// + /// Gets the 2d gradient operator. + /// + public DenseMatrix KernelXY { get; } + + /// + protected override void BeforeFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + if (this.Grayscale) + { + new GrayscaleBt709Processor(1F).ApplyToFrame(source, sourceRectangle, configuration); + } + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + => new ConvolutionProcessor(this.KernelXY, true).Apply(source, sourceRectangle, configuration); + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs index 8652efa12..99dfb17ff 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs @@ -1,24 +1,30 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Applies edge detection processing to the image using the Kayyali operator filter. + /// Defines edge detection processing using the Kayyali operator filter. + /// See . /// - /// The pixel format. - internal class KayyaliProcessor : EdgeDetector2DProcessor - where TPixel : struct, IPixel + public class KayyaliProcessor : EdgeDetectorProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. public KayyaliProcessor(bool grayscale) - : base(KayyaliKernels.KayyaliX, KayyaliKernels.KayyaliY, grayscale) + : base(grayscale) + { + } + + /// + public override IImageProcessor CreatePixelSpecificProcessor() { + return new EdgeDetector2DProcessor( + KayyaliKernels.KayyaliX, + KayyaliKernels.KayyaliY, + this.Grayscale); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/CompassKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/CompassKernels.cs new file mode 100644 index 000000000..f44de9105 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/CompassKernels.cs @@ -0,0 +1,57 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + internal abstract class CompassKernels + { + /// + /// Gets the North gradient operator. + /// + public abstract DenseMatrix North { get; } + + /// + /// Gets the NorthWest gradient operator. + /// + public abstract DenseMatrix NorthWest { get; } + + /// + /// Gets the West gradient operator. + /// + public abstract DenseMatrix West { get; } + + /// + /// Gets the SouthWest gradient operator. + /// + public abstract DenseMatrix SouthWest { get; } + + /// + /// Gets the South gradient operator. + /// + public abstract DenseMatrix South { get; } + + /// + /// Gets the SouthEast gradient operator. + /// + public abstract DenseMatrix SouthEast { get; } + + /// + /// Gets the East gradient operator. + /// + public abstract DenseMatrix East { get; } + + /// + /// Gets the NorthEast gradient operator. + /// + public abstract DenseMatrix NorthEast { get; } + + public DenseMatrix[] Flatten() => + new[] + { + this.North, this.NorthWest, this.West, this.SouthWest, + this.South, this.SouthEast, this.East, this.NorthEast + }; + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/KayyaliKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/KayyaliKernels.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/KayyaliKernels.cs rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/KayyaliKernels.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/KirschKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/KirschKernels.cs similarity index 81% rename from src/ImageSharp/Processing/Processors/Convolution/KirschKernels.cs rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/KirschKernels.cs index 86232e306..882b87075 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/KirschKernels.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/KirschKernels.cs @@ -8,12 +8,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Contains the eight matrices used for Kirsch edge detection /// - internal static class KirschKernels + internal class KirschKernels : CompassKernels { /// /// Gets the North gradient operator /// - public static DenseMatrix KirschNorth => + public override DenseMatrix North => new float[,] { { 5, 5, 5 }, @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the NorthWest gradient operator /// - public static DenseMatrix KirschNorthWest => + public override DenseMatrix NorthWest => new float[,] { { 5, 5, -3 }, @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the West gradient operator /// - public static DenseMatrix KirschWest => + public override DenseMatrix West => new float[,] { { 5, -3, -3 }, @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the SouthWest gradient operator /// - public static DenseMatrix KirschSouthWest => + public override DenseMatrix SouthWest => new float[,] { { -3, -3, -3 }, @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the South gradient operator /// - public static DenseMatrix KirschSouth => + public override DenseMatrix South => new float[,] { { -3, -3, -3 }, @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the SouthEast gradient operator /// - public static DenseMatrix KirschSouthEast => + public override DenseMatrix SouthEast => new float[,] { { -3, -3, -3 }, @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the East gradient operator /// - public static DenseMatrix KirschEast => + public override DenseMatrix East => new float[,] { { -3, -3, 5 }, @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the NorthEast gradient operator /// - public static DenseMatrix KirschNorthEast => + public override DenseMatrix NorthEast => new float[,] { { -3, 5, 5 }, diff --git a/src/ImageSharp/Processing/Processors/Convolution/LaplacianKernelFactory.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/LaplacianKernelFactory.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/LaplacianKernelFactory.cs rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/LaplacianKernelFactory.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/LaplacianKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/LaplacianKernels.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/LaplacianKernels.cs rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/LaplacianKernels.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/PrewittKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/PrewittKernels.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/PrewittKernels.cs rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/PrewittKernels.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/RobertsCrossKernels.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/RobertsCrossKernels.cs rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/RobertsCrossKernels.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/RobinsonKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/RobinsonKernels.cs similarity index 78% rename from src/ImageSharp/Processing/Processors/Convolution/RobinsonKernels.cs rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/RobinsonKernels.cs index 4f47184e3..699d669ec 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/RobinsonKernels.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/RobinsonKernels.cs @@ -6,14 +6,14 @@ using SixLabors.ImageSharp.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Contains the kernels used for Robinson edge detection + /// Contains the kernels used for Robinson edge detection. /// - internal static class RobinsonKernels + internal class RobinsonKernels : CompassKernels { /// /// Gets the North gradient operator /// - public static DenseMatrix RobinsonNorth => + public override DenseMatrix North => new float[,] { { 1, 2, 1 }, @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the NorthWest gradient operator /// - public static DenseMatrix RobinsonNorthWest => + public override DenseMatrix NorthWest => new float[,] { { 2, 1, 0 }, @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the West gradient operator /// - public static DenseMatrix RobinsonWest => + public override DenseMatrix West => new float[,] { { 1, 0, -1 }, @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the SouthWest gradient operator /// - public static DenseMatrix RobinsonSouthWest => + public override DenseMatrix SouthWest => new float[,] { { 0, -1, -2 }, @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the South gradient operator /// - public static DenseMatrix RobinsonSouth => + public override DenseMatrix South => new float[,] { { -1, -2, -1 }, @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the SouthEast gradient operator /// - public static DenseMatrix RobinsonSouthEast => + public override DenseMatrix SouthEast => new float[,] { { -2, -1, 0 }, @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the East gradient operator /// - public static DenseMatrix RobinsonEast => + public override DenseMatrix East => new float[,] { { -1, 0, 1 }, @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Gets the NorthEast gradient operator /// - public static DenseMatrix RobinsonNorthEast => + public override DenseMatrix NorthEast => new float[,] { { 0, 1, 2 }, diff --git a/src/ImageSharp/Processing/Processors/Convolution/ScharrKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/ScharrKernels.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/ScharrKernels.cs rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/ScharrKernels.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/SobelKernels.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/SobelKernels.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/SobelKernels.cs rename to src/ImageSharp/Processing/Processors/Convolution/Kernels/SobelKernels.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs index c3188676f..fc73903c7 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs @@ -1,20 +1,16 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Primitives; - namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Applies edge detection processing to the image using the Kirsch operator filter. + /// Defines edge detection using the Kirsch operator filter. + /// See . /// - /// The pixel format. - internal class KirschProcessor : EdgeDetectorCompassProcessor - where TPixel : struct, IPixel + public class KirschProcessor : EdgeDetectorProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. public KirschProcessor(bool grayscale) @@ -22,28 +18,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { } - /// - public override DenseMatrix North => KirschKernels.KirschNorth; - - /// - public override DenseMatrix NorthWest => KirschKernels.KirschNorthWest; - - /// - public override DenseMatrix West => KirschKernels.KirschWest; - - /// - public override DenseMatrix SouthWest => KirschKernels.KirschSouthWest; - - /// - public override DenseMatrix South => KirschKernels.KirschSouth; - - /// - public override DenseMatrix SouthEast => KirschKernels.KirschSouthEast; - - /// - public override DenseMatrix East => KirschKernels.KirschEast; - - /// - public override DenseMatrix NorthEast => KirschKernels.KirschNorthEast; + /// + public override IImageProcessor CreatePixelSpecificProcessor() + { + return new EdgeDetectorCompassProcessor(new KirschKernels(), this.Grayscale); + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs b/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs index f498d374c..18a53cb13 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs @@ -9,17 +9,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Applies edge detection processing to the image using the Laplacian 3x3 operator filter. /// /// - /// The pixel format. - internal class Laplacian3x3Processor : EdgeDetectorProcessor - where TPixel : struct, IPixel + public class Laplacian3x3Processor : EdgeDetectorProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. public Laplacian3x3Processor(bool grayscale) - : base(LaplacianKernels.Laplacian3x3, grayscale) + : base(grayscale) { } + + /// + public override IImageProcessor CreatePixelSpecificProcessor() + { + return new EdgeDetectorProcessor(LaplacianKernels.Laplacian3x3, this.Grayscale); + } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs b/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs index 558acf7b3..1c95ca490 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs @@ -1,25 +1,27 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Applies edge detection processing to the image using the Laplacian 5x5 operator filter. - /// + /// Defines edge detection processing using the Laplacian 5x5 operator filter. + /// . /// - /// The pixel format. - internal class Laplacian5x5Processor : EdgeDetectorProcessor - where TPixel : struct, IPixel + public class Laplacian5x5Processor : EdgeDetectorProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. public Laplacian5x5Processor(bool grayscale) - : base(LaplacianKernels.Laplacian5x5, grayscale) + : base(grayscale) + { + } + + /// + public override IImageProcessor CreatePixelSpecificProcessor() { + return new EdgeDetectorProcessor(LaplacianKernels.Laplacian5x5, this.Grayscale); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs index 6cc65dc58..d904d69b1 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs @@ -1,25 +1,27 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// /// Applies edge detection processing to the image using the Laplacian of Gaussian operator filter. - /// + /// See . /// - /// The pixel format. - internal class LaplacianOfGaussianProcessor : EdgeDetectorProcessor - where TPixel : struct, IPixel + public class LaplacianOfGaussianProcessor : EdgeDetectorProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. public LaplacianOfGaussianProcessor(bool grayscale) - : base(LaplacianKernels.LaplacianOfGaussianXY, grayscale) + : base(grayscale) + { + } + + /// + public override IImageProcessor CreatePixelSpecificProcessor() { + return new EdgeDetectorProcessor(LaplacianKernels.LaplacianOfGaussianXY, this.Grayscale); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs index 75ef4dac6..939b1e0c5 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs @@ -1,25 +1,27 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Applies edge detection processing to the image using the Prewitt operator filter. - /// + /// Defines edge detection using the Prewitt operator filter. + /// See . /// - /// The pixel format. - internal class PrewittProcessor : EdgeDetector2DProcessor - where TPixel : struct, IPixel + public class PrewittProcessor : EdgeDetectorProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. public PrewittProcessor(bool grayscale) - : base(PrewittKernels.PrewittX, PrewittKernels.PrewittY, grayscale) + : base(grayscale) + { + } + + /// + public override IImageProcessor CreatePixelSpecificProcessor() { + return new EdgeDetector2DProcessor(PrewittKernels.PrewittX, PrewittKernels.PrewittY, this.Grayscale); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs index d685860f6..ff41b6c69 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs @@ -6,20 +6,24 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Applies edge detection processing to the image using the Roberts Cross operator filter. - /// + /// Defines edge detection processing using the Roberts Cross operator filter. + /// See . /// - /// The pixel format. - internal class RobertsCrossProcessor : EdgeDetector2DProcessor - where TPixel : struct, IPixel + public class RobertsCrossProcessor : EdgeDetectorProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. public RobertsCrossProcessor(bool grayscale) - : base(RobertsCrossKernels.RobertsCrossX, RobertsCrossKernels.RobertsCrossY, grayscale) + : base(grayscale) { } + + /// + public override IImageProcessor CreatePixelSpecificProcessor() + { + return new EdgeDetector2DProcessor(RobertsCrossKernels.RobertsCrossX, RobertsCrossKernels.RobertsCrossY, this.Grayscale); + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs index 193c1008d..603a81f67 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs @@ -7,15 +7,13 @@ using SixLabors.ImageSharp.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Applies edge detection processing to the image using the Robinson operator filter. - /// + /// Defines edge detection using the Robinson operator filter. + /// See . /// - /// The pixel format. - internal class RobinsonProcessor : EdgeDetectorCompassProcessor - where TPixel : struct, IPixel + internal class RobinsonProcessor : EdgeDetectorProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. public RobinsonProcessor(bool grayscale) @@ -23,28 +21,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { } - /// - public override DenseMatrix North => RobinsonKernels.RobinsonNorth; - - /// - public override DenseMatrix NorthWest => RobinsonKernels.RobinsonNorthWest; - - /// - public override DenseMatrix West => RobinsonKernels.RobinsonWest; - - /// - public override DenseMatrix SouthWest => RobinsonKernels.RobinsonSouthWest; - - /// - public override DenseMatrix South => RobinsonKernels.RobinsonSouth; - - /// - public override DenseMatrix SouthEast => RobinsonKernels.RobinsonSouthEast; - - /// - public override DenseMatrix East => RobinsonKernels.RobinsonEast; - - /// - public override DenseMatrix NorthEast => RobinsonKernels.RobinsonNorthEast; + /// + public override IImageProcessor CreatePixelSpecificProcessor() + { + return new EdgeDetectorCompassProcessor(new RobinsonKernels(), this.Grayscale); + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs index 79fc0e79f..d23ba5338 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs @@ -6,20 +6,24 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// Applies edge detection processing to the image using the Scharr operator filter. + /// Defines edge detection processing using the Scharr operator filter. /// /// - /// The pixel format. - internal class ScharrProcessor : EdgeDetector2DProcessor - where TPixel : struct, IPixel + public class ScharrProcessor : EdgeDetectorProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. public ScharrProcessor(bool grayscale) - : base(ScharrKernels.ScharrX, ScharrKernels.ScharrY, grayscale) + : base(grayscale) { } + + /// + public override IImageProcessor CreatePixelSpecificProcessor() + { + return new EdgeDetector2DProcessor(ScharrKernels.ScharrX, ScharrKernels.ScharrY, this.Grayscale); + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs index 3ca53f6f0..157bb62e5 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs @@ -2,24 +2,37 @@ // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Convolution { /// - /// The Sobel operator filter. - /// + /// Defines edge detection using the Sobel operator filter. + /// See . /// - /// The pixel format. - internal class SobelProcessor : EdgeDetector2DProcessor - where TPixel : struct, IPixel + public class SobelProcessor : EdgeDetectorProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Whether to convert the image to grayscale before performing edge detection. public SobelProcessor(bool grayscale) - : base(SobelKernels.SobelX, SobelKernels.SobelY, grayscale) + : base(grayscale) { } + + /// + public override IImageProcessor CreatePixelSpecificProcessor() + { + return new EdgeDetector2DProcessor(SobelKernels.SobelX, SobelKernels.SobelY, this.Grayscale); + } + + // TODO: Move this to an appropriate extension method if possible. + internal void ApplyToFrame(ImageFrame frame, Rectangle sourceRectangle, Configuration configuration) + where TPixel : struct, IPixel + { + var processorImpl = new EdgeDetector2DProcessor(SobelKernels.SobelX, SobelKernels.SobelY, this.Grayscale); + processorImpl.Apply(frame, sourceRectangle, configuration); + } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor.cs index 6de717afd..0e744dd96 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor.cs @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Configuration configuration = source.GetConfiguration(); // Detect the edges. - new SobelProcessor(false).Apply(temp, sourceRectangle, configuration); + new SobelProcessor(false).ApplyToFrame(temp, sourceRectangle, configuration); // Apply threshold binarization filter. new BinaryThresholdProcessor(this.Threshold).Apply(temp, sourceRectangle, configuration); diff --git a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs index cf5feac27..07b9b1b8c 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs @@ -21,8 +21,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution this.operations.DetectEdges(); // TODO: Enable once we have updated the images - // SobelProcessor processor = this.Verify>(); - // Assert.True(processor.Grayscale); + SobelProcessor processor = this.Verify(); + Assert.True(processor.Grayscale); } [Fact] @@ -31,45 +31,45 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution this.operations.DetectEdges(this.rect); // TODO: Enable once we have updated the images - // SobelProcessor processor = this.Verify>(this.rect); - // Assert.True(processor.Grayscale); + SobelProcessor processor = this.Verify(this.rect); + Assert.True(processor.Grayscale); } public static IEnumerable EdgeDetectionTheoryData => new[] { - new object[]{ new TestType>(), EdgeDetectionOperators.Kayyali }, - new object[]{ new TestType>(), EdgeDetectionOperators.Kirsch }, - new object[]{ new TestType>(), EdgeDetectionOperators.Laplacian3x3 }, - new object[]{ new TestType>(), EdgeDetectionOperators.Laplacian5x5 }, - new object[]{ new TestType>(), EdgeDetectionOperators.LaplacianOfGaussian }, - new object[]{ new TestType>(), EdgeDetectionOperators.Prewitt }, - new object[]{ new TestType>(), EdgeDetectionOperators.RobertsCross }, - new object[]{ new TestType>(), EdgeDetectionOperators.Robinson }, - new object[]{ new TestType>(), EdgeDetectionOperators.Scharr }, - new object[]{ new TestType>(), EdgeDetectionOperators.Sobel }, + new object[]{ new TestType(), EdgeDetectionOperators.Kayyali }, + new object[]{ new TestType(), EdgeDetectionOperators.Kirsch }, + new object[]{ new TestType(), EdgeDetectionOperators.Laplacian3x3 }, + new object[]{ new TestType(), EdgeDetectionOperators.Laplacian5x5 }, + new object[]{ new TestType(), EdgeDetectionOperators.LaplacianOfGaussian }, + new object[]{ new TestType(), EdgeDetectionOperators.Prewitt }, + new object[]{ new TestType(), EdgeDetectionOperators.RobertsCross }, + new object[]{ new TestType(), EdgeDetectionOperators.Robinson }, + new object[]{ new TestType(), EdgeDetectionOperators.Scharr }, + new object[]{ new TestType(), EdgeDetectionOperators.Sobel }, }; [Theory] [MemberData(nameof(EdgeDetectionTheoryData))] public void DetectEdges_filter_SobelProcessorDefaultsSet(TestType type, EdgeDetectionOperators filter) - where TProcessor : IImageProcessor + where TProcessor : EdgeDetectorProcessor { this.operations.DetectEdges(filter); // TODO: Enable once we have updated the images - // var processor = this.Verify(); - // Assert.True(processor.Grayscale); + var processor = this.Verify(); + Assert.True(processor.Grayscale); } [Theory] [MemberData(nameof(EdgeDetectionTheoryData))] public void DetectEdges_filter_grayscale_SobelProcessorDefaultsSet(TestType type, EdgeDetectionOperators filter) - where TProcessor : IImageProcessor + where TProcessor : EdgeDetectorProcessor { bool grey = (int)filter % 2 == 0; this.operations.DetectEdges(filter, grey); // TODO: Enable once we have updated the images - // var processor = this.Verify() - // Assert.Equal(grey, processor.Grayscale); + var processor = this.Verify(); + Assert.Equal(grey, processor.Grayscale); } } } \ No newline at end of file From ded79e737895760dcecf3febeb7e9b7efc558d2c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 01:36:44 +0200 Subject: [PATCH 129/223] refactor Effects processors --- .../Processing/OilPaintExtensions.cs | 31 ++--- .../Processing/PixelateExtensions.cs | 23 ++-- .../Processors/Dithering/ErrorDiffuserBase.cs | 6 +- .../Effects/OilPaintingProcessor.cs | 119 ++-------------- .../Effects/OilPaintingProcessor{TPixel}.cs | 129 ++++++++++++++++++ .../Processors/Effects/PixelateProcessor.cs | 91 +----------- .../Effects/PixelateProcessor{TPixel}.cs | 111 +++++++++++++++ .../Processing/Effects/OilPaintTest.cs | 8 +- .../Processing/Effects/PixelateTest.cs | 6 +- 9 files changed, 288 insertions(+), 236 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Effects/PixelateProcessor{TPixel}.cs diff --git a/src/ImageSharp/Processing/OilPaintExtensions.cs b/src/ImageSharp/Processing/OilPaintExtensions.cs index b6fa4149a..ee51b31fa 100644 --- a/src/ImageSharp/Processing/OilPaintExtensions.cs +++ b/src/ImageSharp/Processing/OilPaintExtensions.cs @@ -1,14 +1,13 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Effects; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds oil painting effect extensions to the type. + /// Adds oil painting effect extensions to the type. /// public static class OilPaintExtensions { @@ -16,43 +15,36 @@ namespace SixLabors.ImageSharp.Processing /// Alters the colors of the image recreating an oil painting effect with levels and brushSize /// set to 10 and 15 respectively. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext OilPaint(this IImageProcessingContext source) - where TPixel : struct, IPixel - => OilPaint(source, 10, 15); + public static IImageProcessingContext OilPaint(this IImageProcessingContext source) => OilPaint(source, 10, 15); /// /// Alters the colors of the image recreating an oil painting effect with levels and brushSize /// set to 10 and 15 respectively. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext OilPaint(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel - => OilPaint(source, 10, 15, rectangle); + public static IImageProcessingContext OilPaint(this IImageProcessingContext source, Rectangle rectangle) => + OilPaint(source, 10, 15, rectangle); /// /// Alters the colors of the image recreating an oil painting effect. /// - /// The pixel format. /// The image this method extends. /// The number of intensity levels. Higher values result in a broader range of color intensities forming part of the result image. /// The number of neighboring pixels used in calculating each individual pixel value. /// The . - public static IImageProcessingContext OilPaint(this IImageProcessingContext source, int levels, int brushSize) - where TPixel : struct, IPixel - => source.ApplyProcessor(new OilPaintingProcessor(levels, brushSize)); + public static IImageProcessingContext + OilPaint(this IImageProcessingContext source, int levels, int brushSize) => + source.ApplyProcessor(new OilPaintingProcessor(levels, brushSize)); /// /// Alters the colors of the image recreating an oil painting effect. /// - /// The pixel format. /// The image this method extends. /// The number of intensity levels. Higher values result in a broader range of color intensities forming part of the result image. /// The number of neighboring pixels used in calculating each individual pixel value. @@ -60,8 +52,11 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext OilPaint(this IImageProcessingContext source, int levels, int brushSize, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new OilPaintingProcessor(levels, brushSize), rectangle); + public static IImageProcessingContext OilPaint( + this IImageProcessingContext source, + int levels, + int brushSize, + Rectangle rectangle) => + source.ApplyProcessor(new OilPaintingProcessor(levels, brushSize), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/PixelateExtensions.cs b/src/ImageSharp/Processing/PixelateExtensions.cs index 4507f6392..d9f7f9be5 100644 --- a/src/ImageSharp/Processing/PixelateExtensions.cs +++ b/src/ImageSharp/Processing/PixelateExtensions.cs @@ -1,50 +1,45 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Effects; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds pixelation effect extensions to the type. + /// Adds pixelation effect extensions to the type. /// public static class PixelateExtensions { /// /// Pixelates an image with the given pixel size. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext Pixelate(this IImageProcessingContext source) - where TPixel : struct, IPixel - => Pixelate(source, 4); + public static IImageProcessingContext Pixelate(this IImageProcessingContext source) => Pixelate(source, 4); /// /// Pixelates an image with the given pixel size. /// - /// The pixel format. /// The image this method extends. /// The size of the pixels. /// The . - public static IImageProcessingContext Pixelate(this IImageProcessingContext source, int size) - where TPixel : struct, IPixel - => source.ApplyProcessor(new PixelateProcessor(size)); + public static IImageProcessingContext Pixelate(this IImageProcessingContext source, int size) => + source.ApplyProcessor(new PixelateProcessor(size)); /// /// Pixelates an image with the given pixel size. /// - /// The pixel format. /// The image this method extends. /// The size of the pixels. /// /// The structure that specifies the portion of the image object to alter. /// /// The . - public static IImageProcessingContext Pixelate(this IImageProcessingContext source, int size, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new PixelateProcessor(size), rectangle); + public static IImageProcessingContext Pixelate( + this IImageProcessingContext source, + int size, + Rectangle rectangle) => + source.ApplyProcessor(new PixelateProcessor(size), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs index abf5dce18..327828c39 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs @@ -21,12 +21,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering private readonly Vector4 divisorVector; /// - /// The matrix width + /// The matrix width. /// private readonly int matrixHeight; /// - /// The matrix height + /// The matrix height. /// private readonly int matrixWidth; @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering private readonly int startingOffset; /// - /// The diffusion matrix + /// The diffusion matrix. /// private readonly DenseMatrix matrix; diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs index 1b17c470e..14e164fb7 100644 --- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs @@ -1,27 +1,17 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Numerics; - -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Effects { /// - /// Applies oil painting effect processing to the image. + /// Defines an oil painting effect. /// - /// Adapted from by Dewald Esterhuizen. - /// The pixel format. - internal class OilPaintingProcessor : ImageProcessor - where TPixel : struct, IPixel + public class OilPaintingProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// The number of intensity levels. Higher values result in a broader range of color intensities forming part of the result image. @@ -39,111 +29,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects } /// - /// Gets the intensity levels + /// Gets the number of intensity levels. /// public int Levels { get; } /// - /// Gets the brush size + /// Gets the brush size. /// public int BrushSize { get; } - /// - protected override void OnFrameApply( - ImageFrame source, - Rectangle sourceRectangle, - Configuration configuration) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - if (this.BrushSize <= 0 || this.BrushSize > source.Height || this.BrushSize > source.Width) - { - throw new ArgumentOutOfRangeException(nameof(this.BrushSize)); - } - - int startY = sourceRectangle.Y; - int endY = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int maxY = endY - 1; - int maxX = endX - 1; - - int radius = this.BrushSize >> 1; - int levels = this.Levels; - - using (Buffer2D targetPixels = configuration.MemoryAllocator.Allocate2D(source.Size())) - { - source.CopyTo(targetPixels); - - var workingRect = Rectangle.FromLTRB(startX, startY, endX, endY); - ParallelHelper.IterateRows( - workingRect, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span sourceRow = source.GetPixelRowSpan(y); - Span targetRow = targetPixels.GetRowSpan(y); - - for (int x = startX; x < endX; x++) - { - int maxIntensity = 0; - int maxIndex = 0; - - int[] intensityBin = new int[levels]; - float[] redBin = new float[levels]; - float[] blueBin = new float[levels]; - float[] greenBin = new float[levels]; - - for (int fy = 0; fy <= radius; fy++) - { - int fyr = fy - radius; - int offsetY = y + fyr; - - offsetY = offsetY.Clamp(0, maxY); - - Span sourceOffsetRow = source.GetPixelRowSpan(offsetY); - - for (int fx = 0; fx <= radius; fx++) - { - int fxr = fx - radius; - int offsetX = x + fxr; - offsetX = offsetX.Clamp(0, maxX); - - var vector = sourceOffsetRow[offsetX].ToVector4(); - - float sourceRed = vector.X; - float sourceBlue = vector.Z; - float sourceGreen = vector.Y; - - int currentIntensity = (int)MathF.Round( - (sourceBlue + sourceGreen + sourceRed) / 3F * (levels - 1)); - - intensityBin[currentIntensity]++; - blueBin[currentIntensity] += sourceBlue; - greenBin[currentIntensity] += sourceGreen; - redBin[currentIntensity] += sourceRed; - - if (intensityBin[currentIntensity] > maxIntensity) - { - maxIntensity = intensityBin[currentIntensity]; - maxIndex = currentIntensity; - } - } - - float red = MathF.Abs(redBin[maxIndex] / maxIntensity); - float green = MathF.Abs(greenBin[maxIndex] / maxIntensity); - float blue = MathF.Abs(blueBin[maxIndex] / maxIntensity); - - ref TPixel pixel = ref targetRow[x]; - pixel.FromVector4( - new Vector4(red, green, blue, sourceRow[x].ToVector4().W)); - } - } - } - }); - - Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); - } + return new OilPaintingProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs new file mode 100644 index 000000000..9775e5ca9 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs @@ -0,0 +1,129 @@ +// Copyright (c) Six Labors and contributors. +/// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Effects +{ + /// + /// Applies oil painting effect processing to the image. + /// + /// Adapted from by Dewald Esterhuizen. + /// The pixel format. + internal class OilPaintingProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly OilPaintingProcessor definition; + + public OilPaintingProcessor(OilPaintingProcessor definition) + { + this.definition = definition; + } + + /// + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) + { + int brushSize = this.definition.BrushSize; + if (brushSize <= 0 || brushSize > source.Height || brushSize > source.Width) + { + throw new ArgumentOutOfRangeException(nameof(brushSize)); + } + + int startY = sourceRectangle.Y; + int endY = sourceRectangle.Bottom; + int startX = sourceRectangle.X; + int endX = sourceRectangle.Right; + int maxY = endY - 1; + int maxX = endX - 1; + + int radius = brushSize >> 1; + int levels = this.definition.Levels; + + using (Buffer2D targetPixels = configuration.MemoryAllocator.Allocate2D(source.Size())) + { + source.CopyTo(targetPixels); + + var workingRect = Rectangle.FromLTRB(startX, startY, endX, endY); + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span sourceRow = source.GetPixelRowSpan(y); + Span targetRow = targetPixels.GetRowSpan(y); + + for (int x = startX; x < endX; x++) + { + int maxIntensity = 0; + int maxIndex = 0; + + int[] intensityBin = new int[levels]; + float[] redBin = new float[levels]; + float[] blueBin = new float[levels]; + float[] greenBin = new float[levels]; + + for (int fy = 0; fy <= radius; fy++) + { + int fyr = fy - radius; + int offsetY = y + fyr; + + offsetY = offsetY.Clamp(0, maxY); + + Span sourceOffsetRow = source.GetPixelRowSpan(offsetY); + + for (int fx = 0; fx <= radius; fx++) + { + int fxr = fx - radius; + int offsetX = x + fxr; + offsetX = offsetX.Clamp(0, maxX); + + var vector = sourceOffsetRow[offsetX].ToVector4(); + + float sourceRed = vector.X; + float sourceBlue = vector.Z; + float sourceGreen = vector.Y; + + int currentIntensity = (int)MathF.Round( + (sourceBlue + sourceGreen + sourceRed) / 3F * (levels - 1)); + + intensityBin[currentIntensity]++; + blueBin[currentIntensity] += sourceBlue; + greenBin[currentIntensity] += sourceGreen; + redBin[currentIntensity] += sourceRed; + + if (intensityBin[currentIntensity] > maxIntensity) + { + maxIntensity = intensityBin[currentIntensity]; + maxIndex = currentIntensity; + } + } + + float red = MathF.Abs(redBin[maxIndex] / maxIntensity); + float green = MathF.Abs(greenBin[maxIndex] / maxIntensity); + float blue = MathF.Abs(blueBin[maxIndex] / maxIntensity); + + ref TPixel pixel = ref targetRow[x]; + pixel.FromVector4( + new Vector4(red, green, blue, sourceRow[x].ToVector4().W)); + } + } + } + }); + + Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs index 50f76efed..eeb2aafcb 100644 --- a/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs @@ -1,25 +1,17 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Common; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Effects { /// - /// Applies a pixelation effect processing to the image. + /// Defines a pixelation effect of a given size. /// - /// The pixel format. - internal class PixelateProcessor : ImageProcessor - where TPixel : struct, IPixel + public class PixelateProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The size of the pixels. Must be greater than 0. /// @@ -36,80 +28,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects /// public int Size { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - if (this.Size <= 0 || this.Size > source.Height || this.Size > source.Width) - { - throw new ArgumentOutOfRangeException(nameof(this.Size)); - } - - int startY = sourceRectangle.Y; - int endY = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int size = this.Size; - int offset = this.Size / 2; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - // Get the range on the y-plane to choose from. - IEnumerable range = EnumerableExtensions.SteppedRange(minY, i => i < maxY, size); - - Parallel.ForEach( - range, - configuration.GetParallelOptions(), - y => - { - int offsetY = y - startY; - int offsetPy = offset; - - // Make sure that the offset is within the boundary of the image. - while (offsetY + offsetPy >= maxY) - { - offsetPy--; - } - - Span row = source.GetPixelRowSpan(offsetY + offsetPy); - - for (int x = minX; x < maxX; x += size) - { - int offsetX = x - startX; - int offsetPx = offset; - - while (x + offsetPx >= maxX) - { - offsetPx--; - } - - // Get the pixel color in the centre of the soon to be pixelated area. - TPixel pixel = row[offsetX + offsetPx]; - - // For each pixel in the pixelate size, set it to the centre color. - for (int l = offsetY; l < offsetY + size && l < maxY; l++) - { - for (int k = offsetX; k < offsetX + size && k < maxX; k++) - { - source[k, l] = pixel; - } - } - } - }); + return new PixelateProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor{TPixel}.cs new file mode 100644 index 000000000..21f3bb774 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor{TPixel}.cs @@ -0,0 +1,111 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Common; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Effects +{ + /// + /// Applies a pixelation effect processing to the image. + /// + /// The pixel format. + internal class PixelateProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly PixelateProcessor definition; + + /// + /// Initializes a new instance of the class. + /// + /// The . + public PixelateProcessor(PixelateProcessor definition) + { + this.definition = definition; + } + + private int Size => this.definition.Size; + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + if (this.Size <= 0 || this.Size > source.Height || this.Size > source.Width) + { + throw new ArgumentOutOfRangeException(nameof(this.Size)); + } + + int startY = sourceRectangle.Y; + int endY = sourceRectangle.Bottom; + int startX = sourceRectangle.X; + int endX = sourceRectangle.Right; + int size = this.Size; + int offset = this.Size / 2; + + // Align start/end positions. + int minX = Math.Max(0, startX); + int maxX = Math.Min(source.Width, endX); + int minY = Math.Max(0, startY); + int maxY = Math.Min(source.Height, endY); + + // Reset offset if necessary. + if (minX > 0) + { + startX = 0; + } + + if (minY > 0) + { + startY = 0; + } + + // Get the range on the y-plane to choose from. + IEnumerable range = EnumerableExtensions.SteppedRange(minY, i => i < maxY, size); + + Parallel.ForEach( + range, + configuration.GetParallelOptions(), + y => + { + int offsetY = y - startY; + int offsetPy = offset; + + // Make sure that the offset is within the boundary of the image. + while (offsetY + offsetPy >= maxY) + { + offsetPy--; + } + + Span row = source.GetPixelRowSpan(offsetY + offsetPy); + + for (int x = minX; x < maxX; x += size) + { + int offsetX = x - startX; + int offsetPx = offset; + + while (x + offsetPx >= maxX) + { + offsetPx--; + } + + // Get the pixel color in the centre of the soon to be pixelated area. + TPixel pixel = row[offsetX + offsetPx]; + + // For each pixel in the pixelate size, set it to the centre color. + for (int l = offsetY; l < offsetY + size && l < maxY; l++) + { + for (int k = offsetX; k < offsetX + size && k < maxX; k++) + { + source[k, l] = pixel; + } + } + } + }); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs b/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs index 9cd24fc6d..6e1ee40f5 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Effects public void OilPaint_OilPaintingProcessorDefaultsSet() { this.operations.OilPaint(); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(10, processor.Levels); Assert.Equal(15, processor.BrushSize); @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Effects public void OilPaint_rect_OilPaintingProcessorDefaultsSet() { this.operations.OilPaint(this.rect); - var processor = this.Verify>(this.rect); + var processor = this.Verify(this.rect); Assert.Equal(10, processor.Levels); Assert.Equal(15, processor.BrushSize); @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Effects public void OilPaint_Levels_Brsuh_OilPaintingProcessorDefaultsSet() { this.operations.OilPaint(34, 65); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(34, processor.Levels); Assert.Equal(65, processor.BrushSize); @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Effects public void OilPaint_Levels_Brsuh_rect_OilPaintingProcessorDefaultsSet() { this.operations.OilPaint(54, 43, this.rect); - var processor = this.Verify>(this.rect); + var processor = this.Verify(this.rect); Assert.Equal(54, processor.Levels); Assert.Equal(43, processor.BrushSize); diff --git a/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs b/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs index a93eaf0bc..d8ce29170 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Effects public void Pixelate_PixelateProcessorDefaultsSet() { this.operations.Pixelate(); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(4, processor.Size); } @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Effects public void Pixelate_Size_PixelateProcessorDefaultsSet() { this.operations.Pixelate(12); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(12, processor.Size); } @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Effects public void Pixelate_Size_rect_PixelateProcessorDefaultsSet() { this.operations.Pixelate(23, this.rect); - var processor = this.Verify>(this.rect); + var processor = this.Verify(this.rect); Assert.Equal(23, processor.Size); } From 0fbf85ff2f2459ad8b84f213a52debdf156dea36 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 02:27:36 +0200 Subject: [PATCH 130/223] Finished refactoring transforms --- src/ImageSharp/Processing/CropExtensions.cs | 15 +- .../Processing/EntropyCropExtensions.cs | 19 +- src/ImageSharp/Processing/FlipExtensions.cs | 9 +- .../Effects/OilPaintingProcessor{TPixel}.cs | 2 +- .../Transforms/AffineTransformProcessor.cs | 106 +-------- .../AffineTransformProcessor{TPixel}.cs | 127 +++++++++++ .../Transforms/AutoOrientProcessor.cs | 92 +------- .../Transforms/AutoOrientProcessor{TPixel}.cs | 103 +++++++++ .../Processors/Transforms/CropProcessor.cs | 59 +---- .../Transforms/CropProcessor{TPixel}.cs | 75 ++++++ .../Transforms/EntropyCropProcessor.cs | 46 +--- .../EntropyCropProcessor{TPixel}.cs | 59 +++++ .../Processors/Transforms/FlipProcessor.cs | 76 +------ .../Transforms/FlipProcessor{TPixel}.cs | 87 +++++++ .../ProjectiveTransformProcessor.cs | 109 +-------- .../ProjectiveTransformProcessor{TPixel}.cs | 126 ++++++++++ .../Processors/Transforms/RotateProcessor.cs | 207 +---------------- .../Transforms/RotateProcessor{TPixel}.cs | 215 ++++++++++++++++++ .../Processors/Transforms/SkewProcessor.cs | 10 +- .../Transforms/TransformProcessorBase.cs | 2 +- .../Transforms/TransformProcessorHelpers.cs | 2 +- src/ImageSharp/Processing/RotateExtensions.cs | 24 +- .../Processing/RotateFlipExtensions.cs | 6 +- src/ImageSharp/Processing/SkewExtensions.cs | 24 +- .../Processing/TransformExtensions.cs | 97 ++++---- .../ImageSharp.Tests/Drawing/DrawImageTest.cs | 3 +- .../Processing/Transforms/CropTest.cs | 4 +- .../Processing/Transforms/EntropyCropTest.cs | 2 +- .../Processing/Transforms/FlipTests.cs | 2 +- .../Processing/Transforms/PadTest.cs | 8 +- .../Processing/Transforms/RotateFlipTests.cs | 4 +- .../Processing/Transforms/RotateTests.cs | 4 +- .../Processing/Transforms/SkewTest.cs | 2 +- .../Transforms/TransformsHelpersTest.cs | 2 +- 34 files changed, 953 insertions(+), 775 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Transforms/FlipProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Transforms/RotateProcessor{TPixel}.cs diff --git a/src/ImageSharp/Processing/CropExtensions.cs b/src/ImageSharp/Processing/CropExtensions.cs index 1c0d80afc..6aaff5656 100644 --- a/src/ImageSharp/Processing/CropExtensions.cs +++ b/src/ImageSharp/Processing/CropExtensions.cs @@ -1,40 +1,35 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of cropping operations to the type. + /// Adds extensions that allow the application of cropping operations to the type. /// public static class CropExtensions { /// /// Crops an image to the given width and height. /// - /// The pixel format. /// The image to resize. /// The target image width. /// The target image height. /// The - public static IImageProcessingContext Crop(this IImageProcessingContext source, int width, int height) - where TPixel : struct, IPixel - => Crop(source, new Rectangle(0, 0, width, height)); + public static IImageProcessingContext Crop(this IImageProcessingContext source, int width, int height) => + Crop(source, new Rectangle(0, 0, width, height)); /// /// Crops an image to the given rectangle. /// - /// The pixel format. /// The image to crop. /// /// The structure that specifies the portion of the image object to retain. /// /// The - public static IImageProcessingContext Crop(this IImageProcessingContext source, Rectangle cropRectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new CropProcessor(cropRectangle, source.GetCurrentSize())); + public static IImageProcessingContext Crop(this IImageProcessingContext source, Rectangle cropRectangle) => + source.ApplyProcessor(new CropProcessor(cropRectangle, source.GetCurrentSize())); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/EntropyCropExtensions.cs b/src/ImageSharp/Processing/EntropyCropExtensions.cs index 157e69ef2..34bc5daeb 100644 --- a/src/ImageSharp/Processing/EntropyCropExtensions.cs +++ b/src/ImageSharp/Processing/EntropyCropExtensions.cs @@ -1,35 +1,30 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of entropy cropping operations to the type. + /// Adds extensions that allow the application of entropy cropping operations to the type. /// public static class EntropyCropExtensions { /// /// Crops an image to the area of greatest entropy using a threshold for entropic density of .5F. /// - /// The pixel format. /// The image to crop. - /// The - public static IImageProcessingContext EntropyCrop(this IImageProcessingContext source) - where TPixel : struct, IPixel - => source.ApplyProcessor(new EntropyCropProcessor()); + /// The . + public static IImageProcessingContext EntropyCrop(this IImageProcessingContext source) => + source.ApplyProcessor(new EntropyCropProcessor()); /// /// Crops an image to the area of greatest entropy. /// - /// The pixel format. /// The image to crop. /// The threshold for entropic density. - /// The - public static IImageProcessingContext EntropyCrop(this IImageProcessingContext source, float threshold) - where TPixel : struct, IPixel - => source.ApplyProcessor(new EntropyCropProcessor(threshold)); + /// The . + public static IImageProcessingContext EntropyCrop(this IImageProcessingContext source, float threshold) => + source.ApplyProcessor(new EntropyCropProcessor(threshold)); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/FlipExtensions.cs b/src/ImageSharp/Processing/FlipExtensions.cs index dfbff7e4d..bc862972e 100644 --- a/src/ImageSharp/Processing/FlipExtensions.cs +++ b/src/ImageSharp/Processing/FlipExtensions.cs @@ -1,25 +1,22 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of flipping operations to the type. + /// Adds extensions that allow the application of flipping operations to the type. /// public static class FlipExtensions { /// /// Flips an image by the given instructions. /// - /// The pixel format. /// The image to rotate, flip, or both. /// The to perform the flip. /// The - public static IImageProcessingContext Flip(this IImageProcessingContext source, FlipMode flipMode) - where TPixel : struct, IPixel - => source.ApplyProcessor(new FlipProcessor(flipMode)); + public static IImageProcessingContext Flip(this IImageProcessingContext source, FlipMode flipMode) + => source.ApplyProcessor(new FlipProcessor(flipMode)); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs index 9775e5ca9..7efb71fa1 100644 --- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs @@ -1,5 +1,5 @@ // Copyright (c) Six Labors and contributors. -/// Licensed under the Apache License, Version 2.0. +// Licensed under the Apache License, Version 2.0. using System; using System.Numerics; diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs index 7633ed441..713f04265 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs @@ -1,26 +1,20 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Collections.Generic; -using System.Linq; using System.Numerics; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.ParallelUtils; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Provides the base methods to perform affine transforms on an image. + /// Defines an affine transformation applicable on an . /// - /// The pixel format. - internal class AffineTransformProcessor : TransformProcessorBase - where TPixel : struct, IPixel + public class AffineTransformProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The transform matrix. /// The sampler to perform the transform operation. @@ -48,95 +42,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public Size TargetDimensions { get; } - /// - protected override Image CreateDestination(Image source, Rectangle sourceRectangle) + /// + public virtual IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = - source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions, x.Metadata.DeepClone())); - - // Use the overload to prevent an extra frame being added - return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); - } - - /// - protected override void OnFrameApply( - ImageFrame source, - ImageFrame destination, - Rectangle sourceRectangle, - Configuration configuration) - { - // Handle tranforms that result in output identical to the original. - if (this.TransformMatrix.Equals(default) || this.TransformMatrix.Equals(Matrix3x2.Identity)) - { - // The clone will be blank here copy all the pixel data over - source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); - return; - } - - int width = this.TargetDimensions.Width; - var targetBounds = new Rectangle(Point.Empty, this.TargetDimensions); - - // Convert from screen to world space. - Matrix3x2.Invert(this.TransformMatrix, out Matrix3x2 matrix); - - if (this.Sampler is NearestNeighborResampler) - { - ParallelHelper.IterateRows( - targetBounds, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span destRow = destination.GetPixelRowSpan(y); - - for (int x = 0; x < width; x++) - { - var point = Point.Transform(new Point(x, y), matrix); - if (sourceRectangle.Contains(point.X, point.Y)) - { - destRow[x] = source[point.X, point.Y]; - } - } - } - }); - - return; - } - - var kernel = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.Sampler); - try - { - ParallelHelper.IterateRowsWithTempBuffer( - targetBounds, - configuration, - (rows, vectorBuffer) => - { - Span vectorSpan = vectorBuffer.Span; - for (int y = rows.Min; y < rows.Max; y++) - { - Span targetRowSpan = destination.GetPixelRowSpan(y); - PixelOperations.Instance.ToVector4(configuration, targetRowSpan, vectorSpan); - ref float ySpanRef = ref kernel.GetYStartReference(y); - ref float xSpanRef = ref kernel.GetXStartReference(y); - - for (int x = 0; x < width; x++) - { - // Use the single precision position to calculate correct bounding pixels - // otherwise we get rogue pixels outside of the bounds. - var point = Vector2.Transform(new Vector2(x, y), matrix); - kernel.Convolve(point, x, ref ySpanRef, ref xSpanRef, source.PixelBuffer, vectorSpan); - } - - PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); - } - }); - } - finally - { - kernel.Dispose(); - } + return new AffineTransformProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs new file mode 100644 index 000000000..e57ce826b --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs @@ -0,0 +1,127 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + /// + /// Provides the base methods to perform affine transforms on an image. + /// + /// The pixel format. + internal class AffineTransformProcessor : TransformProcessorBase + where TPixel : struct, IPixel + { + public AffineTransformProcessor(AffineTransformProcessor definition) + { + this.Definition = definition; + } + + private Size TargetDimensions => this.Definition.TargetDimensions; + + private Matrix3x2 TransformMatrix => this.Definition.TransformMatrix; + + protected AffineTransformProcessor Definition { get; } + + /// + protected override Image CreateDestination(Image source, Rectangle sourceRectangle) + { + // We will always be creating the clone even for mutate because we may need to resize the canvas + IEnumerable> frames = + source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions, x.Metadata.DeepClone())); + + // Use the overload to prevent an extra frame being added + return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); + } + + /// + protected override void OnFrameApply( + ImageFrame source, + ImageFrame destination, + Rectangle sourceRectangle, + Configuration configuration) + { + // Handle tranforms that result in output identical to the original. + if (this.TransformMatrix.Equals(default) || this.TransformMatrix.Equals(Matrix3x2.Identity)) + { + // The clone will be blank here copy all the pixel data over + source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); + return; + } + + int width = this.TargetDimensions.Width; + var targetBounds = new Rectangle(Point.Empty, this.TargetDimensions); + + // Convert from screen to world space. + Matrix3x2.Invert(this.TransformMatrix, out Matrix3x2 matrix); + + var sampler = this.Definition.Sampler; + + if (sampler is NearestNeighborResampler) + { + ParallelHelper.IterateRows( + targetBounds, + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span destRow = destination.GetPixelRowSpan(y); + + for (int x = 0; x < width; x++) + { + var point = Point.Transform(new Point(x, y), matrix); + if (sourceRectangle.Contains(point.X, point.Y)) + { + destRow[x] = source[point.X, point.Y]; + } + } + } + }); + + return; + } + + var kernel = new TransformKernelMap(configuration, source.Size(), destination.Size(), sampler); + try + { + ParallelHelper.IterateRowsWithTempBuffer( + targetBounds, + configuration, + (rows, vectorBuffer) => + { + Span vectorSpan = vectorBuffer.Span; + for (int y = rows.Min; y < rows.Max; y++) + { + Span targetRowSpan = destination.GetPixelRowSpan(y); + PixelOperations.Instance.ToVector4(configuration, targetRowSpan, vectorSpan); + ref float ySpanRef = ref kernel.GetYStartReference(y); + ref float xSpanRef = ref kernel.GetXStartReference(y); + + for (int x = 0; x < width; x++) + { + // Use the single precision position to calculate correct bounding pixels + // otherwise we get rogue pixels outside of the bounds. + var point = Vector2.Transform(new Vector2(x, y), matrix); + kernel.Convolve(point, x, ref ySpanRef, ref xSpanRef, source.PixelBuffer, vectorSpan); + } + + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); + } + }); + } + finally + { + kernel.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs index 5b9e3dde2..9bbbba843 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs @@ -1,103 +1,21 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// /// Adjusts an image so that its orientation is suitable for viewing. Adjustments are based on EXIF metadata embedded in the image. /// - /// The pixel format. - internal class AutoOrientProcessor : ImageProcessor - where TPixel : struct, IPixel + public sealed class AutoOrientProcessor : IImageProcessor { - /// - protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - OrientationMode orientation = GetExifOrientation(source); - Size size = sourceRectangle.Size; - switch (orientation) - { - case OrientationMode.TopRight: - new FlipProcessor(FlipMode.Horizontal).Apply(source, sourceRectangle); - break; - - case OrientationMode.BottomRight: - new RotateProcessor((int)RotateMode.Rotate180, size).Apply(source, sourceRectangle); - break; - - case OrientationMode.BottomLeft: - new FlipProcessor(FlipMode.Vertical).Apply(source, sourceRectangle); - break; - - case OrientationMode.LeftTop: - new RotateProcessor((int)RotateMode.Rotate90, size).Apply(source, sourceRectangle); - new FlipProcessor(FlipMode.Horizontal).Apply(source, sourceRectangle); - break; - - case OrientationMode.RightTop: - new RotateProcessor((int)RotateMode.Rotate90, size).Apply(source, sourceRectangle); - break; - - case OrientationMode.RightBottom: - new FlipProcessor(FlipMode.Vertical).Apply(source, sourceRectangle); - new RotateProcessor((int)RotateMode.Rotate270, size).Apply(source, sourceRectangle); - break; - - case OrientationMode.LeftBottom: - new RotateProcessor((int)RotateMode.Rotate270, size).Apply(source, sourceRectangle); - break; - - case OrientationMode.Unknown: - case OrientationMode.TopLeft: - default: - break; - } - } - - /// - protected override void OnFrameApply(ImageFrame sourceBase, Rectangle sourceRectangle, Configuration config) - { - // All processing happens at the image level within BeforeImageApply(); - } - - /// - /// Returns the current EXIF orientation - /// - /// The image to auto rotate. - /// The - private static OrientationMode GetExifOrientation(Image source) - { - if (source.Metadata.ExifProfile is null) - { - return OrientationMode.Unknown; - } - - ExifValue value = source.Metadata.ExifProfile.GetValue(ExifTag.Orientation); - if (value is null) - { - return OrientationMode.Unknown; - } - - OrientationMode orientation; - if (value.DataType == ExifDataType.Short) - { - orientation = (OrientationMode)value.Value; - } - else - { - orientation = (OrientationMode)Convert.ToUInt16(value.Value); - source.Metadata.ExifProfile.RemoveValue(ExifTag.Orientation); - } - - source.Metadata.ExifProfile.SetValue(ExifTag.Orientation, (ushort)OrientationMode.TopLeft); - - return orientation; + return new AutoOrientProcessor(); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs new file mode 100644 index 000000000..257c223dc --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs @@ -0,0 +1,103 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Metadata.Profiles.Exif; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + /// + /// Adjusts an image so that its orientation is suitable for viewing. Adjustments are based on EXIF metadata embedded in the image. + /// + /// The pixel format. + internal class AutoOrientProcessor : ImageProcessor + where TPixel : struct, IPixel + { + /// + protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) + { + OrientationMode orientation = GetExifOrientation(source); + Size size = sourceRectangle.Size; + switch (orientation) + { + case OrientationMode.TopRight: + new FlipProcessor(FlipMode.Horizontal).Apply(source, sourceRectangle); + break; + + case OrientationMode.BottomRight: + new RotateProcessor((int)RotateMode.Rotate180, size).Apply(source, sourceRectangle); + break; + + case OrientationMode.BottomLeft: + new FlipProcessor(FlipMode.Vertical).Apply(source, sourceRectangle); + break; + + case OrientationMode.LeftTop: + new RotateProcessor((int)RotateMode.Rotate90, size).Apply(source, sourceRectangle); + new FlipProcessor(FlipMode.Horizontal).Apply(source, sourceRectangle); + break; + + case OrientationMode.RightTop: + new RotateProcessor((int)RotateMode.Rotate90, size).Apply(source, sourceRectangle); + break; + + case OrientationMode.RightBottom: + new FlipProcessor(FlipMode.Vertical).Apply(source, sourceRectangle); + new RotateProcessor((int)RotateMode.Rotate270, size).Apply(source, sourceRectangle); + break; + + case OrientationMode.LeftBottom: + new RotateProcessor((int)RotateMode.Rotate270, size).Apply(source, sourceRectangle); + break; + + case OrientationMode.Unknown: + case OrientationMode.TopLeft: + default: + break; + } + } + + /// + protected override void OnFrameApply(ImageFrame sourceBase, Rectangle sourceRectangle, Configuration config) + { + // All processing happens at the image level within BeforeImageApply(); + } + + /// + /// Returns the current EXIF orientation + /// + /// The image to auto rotate. + /// The + private static OrientationMode GetExifOrientation(Image source) + { + if (source.Metadata.ExifProfile is null) + { + return OrientationMode.Unknown; + } + + ExifValue value = source.Metadata.ExifProfile.GetValue(ExifTag.Orientation); + if (value is null) + { + return OrientationMode.Unknown; + } + + OrientationMode orientation; + if (value.DataType == ExifDataType.Short) + { + orientation = (OrientationMode)value.Value; + } + else + { + orientation = (OrientationMode)Convert.ToUInt16(value.Value); + source.Metadata.ExifProfile.RemoveValue(ExifTag.Orientation); + } + + source.Metadata.ExifProfile.SetValue(ExifTag.Orientation, (ushort)OrientationMode.TopLeft); + + return orientation; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs index 5baa196a0..76f223e03 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs @@ -1,32 +1,28 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Collections.Generic; -using System.Linq; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Provides methods to allow the cropping of an image. + /// Defines a crop operation on an image. /// - /// The pixel format. - internal class CropProcessor : TransformProcessorBase - where TPixel : struct, IPixel + public sealed class CropProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target cropped rectangle. /// The source image size. public CropProcessor(Rectangle cropRectangle, Size sourceSize) { // Check bounds here and throw if we are passed a rectangle exceeding our source bounds. - Guard.IsTrue(new Rectangle(Point.Empty, sourceSize).Contains(cropRectangle), nameof(cropRectangle), "Crop rectangle should be smaller than the source bounds."); + Guard.IsTrue( + new Rectangle(Point.Empty, sourceSize).Contains(cropRectangle), + nameof(cropRectangle), + "Crop rectangle should be smaller than the source bounds."); this.CropRectangle = cropRectangle; } @@ -35,44 +31,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public Rectangle CropRectangle { get; } - /// - protected override Image CreateDestination(Image source, Rectangle sourceRectangle) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.CropRectangle.Width, this.CropRectangle.Height, x.Metadata.DeepClone())); - - // Use the overload to prevent an extra frame being added - return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); - } - - /// - protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) - { - // Handle resize dimensions identical to the original - if (source.Width == destination.Width && source.Height == destination.Height && sourceRectangle == this.CropRectangle) - { - // the cloned will be blank here copy all the pixel data over - source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); - return; - } - - Rectangle rect = this.CropRectangle; - - // Copying is cheap, we should process more pixels per task: - ParallelExecutionSettings parallelSettings = configuration.GetParallelSettings().MultiplyMinimumPixelsPerTask(4); - - ParallelHelper.IterateRows( - rect, - parallelSettings, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span sourceRow = source.GetPixelRowSpan(y).Slice(rect.Left); - Span targetRow = destination.GetPixelRowSpan(y - rect.Top); - sourceRow.Slice(0, rect.Width).CopyTo(targetRow); - } - }); + return new CropProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs new file mode 100644 index 000000000..9bddda382 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs @@ -0,0 +1,75 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.Linq; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + /// + /// Provides methods to allow the cropping of an image. + /// + /// The pixel format. + internal class CropProcessor : TransformProcessorBase + where TPixel : struct, IPixel + { + private readonly CropProcessor definition; + + /// + /// Initializes a new instance of the class. + /// + /// The . + public CropProcessor(CropProcessor definition) + { + this.definition = definition; + } + + private Rectangle CropRectangle => this.definition.CropRectangle; + + /// + protected override Image CreateDestination(Image source, Rectangle sourceRectangle) + { + // We will always be creating the clone even for mutate because we may need to resize the canvas + IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.CropRectangle.Width, this.CropRectangle.Height, x.Metadata.DeepClone())); + + // Use the overload to prevent an extra frame being added + return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); + } + + /// + protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) + { + // Handle resize dimensions identical to the original + if (source.Width == destination.Width && source.Height == destination.Height && sourceRectangle == this.CropRectangle) + { + // the cloned will be blank here copy all the pixel data over + source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); + return; + } + + Rectangle rect = this.CropRectangle; + + // Copying is cheap, we should process more pixels per task: + ParallelExecutionSettings parallelSettings = configuration.GetParallelSettings().MultiplyMinimumPixelsPerTask(4); + + ParallelHelper.IterateRows( + rect, + parallelSettings, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span sourceRow = source.GetPixelRowSpan(y).Slice(rect.Left); + Span targetRow = destination.GetPixelRowSpan(y - rect.Top); + sourceRow.Slice(0, rect.Width).CopyTo(targetRow); + } + }); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor.cs index 0e744dd96..dee5e7fb3 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor.cs @@ -1,31 +1,25 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors.Binarization; -using SixLabors.ImageSharp.Processing.Processors.Convolution; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Provides methods to allow the cropping of an image to preserve areas of highest entropy. + /// Defines cropping operation that preserves areas of highest entropy. /// - /// The pixel format. - internal class EntropyCropProcessor : ImageProcessor - where TPixel : struct, IPixel + public sealed class EntropyCropProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public EntropyCropProcessor() - : this(.5F) + : this(.5F) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The threshold to split the image. Must be between 0 and 1. /// @@ -42,33 +36,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public float Threshold { get; } - /// - protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - Rectangle rectangle; - - // All frames have be the same size so we only need to calculate the correct dimensions for the first frame - using (ImageFrame temp = source.Frames.RootFrame.Clone()) - { - Configuration configuration = source.GetConfiguration(); - - // Detect the edges. - new SobelProcessor(false).ApplyToFrame(temp, sourceRectangle, configuration); - - // Apply threshold binarization filter. - new BinaryThresholdProcessor(this.Threshold).Apply(temp, sourceRectangle, configuration); - - // Search for the first white pixels - rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0); - } - - new CropProcessor(rectangle, source.Size()).Apply(source, sourceRectangle); - } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - // All processing happens at the image level within BeforeImageApply(); + return new EntropyCropProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs new file mode 100644 index 000000000..eaeb6939e --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs @@ -0,0 +1,59 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Binarization; +using SixLabors.ImageSharp.Processing.Processors.Convolution; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + /// + /// Provides methods to allow the cropping of an image to preserve areas of highest entropy. + /// + /// The pixel format. + internal class EntropyCropProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly EntropyCropProcessor definition; + + /// + /// Initializes a new instance of the class. + /// + /// The . + public EntropyCropProcessor(EntropyCropProcessor definition) + { + this.definition = definition; + } + + /// + protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) + { + Rectangle rectangle; + + // All frames have be the same size so we only need to calculate the correct dimensions for the first frame + using (ImageFrame temp = source.Frames.RootFrame.Clone()) + { + Configuration configuration = source.GetConfiguration(); + + // Detect the edges. + new SobelProcessor(false).ApplyToFrame(temp, sourceRectangle, configuration); + + // Apply threshold binarization filter. + new BinaryThresholdProcessor(this.definition.Threshold).Apply(temp, sourceRectangle, configuration); + + // Search for the first white pixels + rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0); + } + + new CropProcessor(rectangle, source.Size()).Apply(source, sourceRectangle); + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + // All processing happens at the image level within BeforeImageApply(); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs index c6f5e9d7b..9a3eab6cc 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs @@ -1,27 +1,17 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; -using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Provides methods that allow the flipping of an image around its center point. + /// Defines a flipping around the center point of the image. /// - /// The pixel format. - internal class FlipProcessor : ImageProcessor - where TPixel : struct, IPixel + public class FlipProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The used to perform flipping. public FlipProcessor(FlipMode flipMode) @@ -34,63 +24,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public FlipMode FlipMode { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - switch (this.FlipMode) - { - // No default needed as we have already set the pixels. - case FlipMode.Vertical: - this.FlipX(source, configuration); - break; - case FlipMode.Horizontal: - this.FlipY(source, configuration); - break; - } - } - - /// - /// Swaps the image at the X-axis, which goes horizontally through the middle at half the height of the image. - /// - /// The source image to apply the process to. - /// The configuration. - private void FlipX(ImageFrame source, Configuration configuration) - { - int height = source.Height; - - using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(source.Width)) - { - Span temp = tempBuffer.Memory.Span; - - for (int yTop = 0; yTop < height / 2; yTop++) - { - int yBottom = height - yTop - 1; - Span topRow = source.GetPixelRowSpan(yBottom); - Span bottomRow = source.GetPixelRowSpan(yTop); - topRow.CopyTo(temp); - bottomRow.CopyTo(topRow); - temp.CopyTo(bottomRow); - } - } - } - - /// - /// Swaps the image at the Y-axis, which goes vertically through the middle at half of the width of the image. - /// - /// The source image to apply the process to. - /// The configuration. - private void FlipY(ImageFrame source, Configuration configuration) - { - ParallelHelper.IterateRows( - source.Bounds(), - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - source.GetPixelRowSpan(y).Reverse(); - } - }); + return new FlipProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor{TPixel}.cs new file mode 100644 index 000000000..024786209 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor{TPixel}.cs @@ -0,0 +1,87 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + /// + /// Provides methods that allow the flipping of an image around its center point. + /// + /// The pixel format. + internal class FlipProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly FlipProcessor definition; + + public FlipProcessor(FlipProcessor definition) + { + this.definition = definition; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + switch (this.definition.FlipMode) + { + // No default needed as we have already set the pixels. + case FlipMode.Vertical: + this.FlipX(source, configuration); + break; + case FlipMode.Horizontal: + this.FlipY(source, configuration); + break; + } + } + + /// + /// Swaps the image at the X-axis, which goes horizontally through the middle at half the height of the image. + /// + /// The source image to apply the process to. + /// The configuration. + private void FlipX(ImageFrame source, Configuration configuration) + { + int height = source.Height; + + using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(source.Width)) + { + Span temp = tempBuffer.Memory.Span; + + for (int yTop = 0; yTop < height / 2; yTop++) + { + int yBottom = height - yTop - 1; + Span topRow = source.GetPixelRowSpan(yBottom); + Span bottomRow = source.GetPixelRowSpan(yTop); + topRow.CopyTo(temp); + bottomRow.CopyTo(topRow); + temp.CopyTo(bottomRow); + } + } + } + + /// + /// Swaps the image at the Y-axis, which goes vertically through the middle at half of the width of the image. + /// + /// The source image to apply the process to. + /// The configuration. + private void FlipY(ImageFrame source, Configuration configuration) + { + ParallelHelper.IterateRows( + source.Bounds(), + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + source.GetPixelRowSpan(y).Reverse(); + } + }); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs index 6c7271c5e..3a86b3fe4 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs @@ -1,26 +1,20 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Collections.Generic; -using System.Linq; using System.Numerics; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.ParallelUtils; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Provides the base methods to perform non-affine transforms on an image. + /// Defines a projective transformation applicable to an . /// - /// The pixel format. - internal class ProjectiveTransformProcessor : TransformProcessorBase - where TPixel : struct, IPixel + public sealed class ProjectiveTransformProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The transform matrix. /// The sampler to perform the transform operation. @@ -39,103 +33,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public IResampler Sampler { get; } /// - /// Gets the matrix used to supply the projective transform + /// Gets the matrix used to supply the projective transform. /// public Matrix4x4 TransformMatrix { get; } /// - /// Gets the target dimensions to constrain the transformed image to + /// Gets the target dimensions to constrain the transformed image to. /// public Size TargetDimensions { get; } - /// - protected override Image CreateDestination(Image source, Rectangle sourceRectangle) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = - source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions.Width, this.TargetDimensions.Height, x.Metadata.DeepClone())); - - // Use the overload to prevent an extra frame being added - return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); - } - - /// - protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) - { - // Handle tranforms that result in output identical to the original. - if (this.TransformMatrix.Equals(default) || this.TransformMatrix.Equals(Matrix4x4.Identity)) - { - // The clone will be blank here copy all the pixel data over - source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); - return; - } - - int width = this.TargetDimensions.Width; - var targetBounds = new Rectangle(Point.Empty, this.TargetDimensions); - - // Convert from screen to world space. - Matrix4x4.Invert(this.TransformMatrix, out Matrix4x4 matrix); - - if (this.Sampler is NearestNeighborResampler) - { - ParallelHelper.IterateRows( - targetBounds, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span destRow = destination.GetPixelRowSpan(y); - - for (int x = 0; x < width; x++) - { - Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, matrix); - int px = (int)MathF.Round(point.X); - int py = (int)MathF.Round(point.Y); - - if (sourceRectangle.Contains(px, py)) - { - destRow[x] = source[px, py]; - } - } - } - }); - - return; - } - - var kernel = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.Sampler); - try - { - ParallelHelper.IterateRowsWithTempBuffer( - targetBounds, - configuration, - (rows, vectorBuffer) => - { - Span vectorSpan = vectorBuffer.Span; - for (int y = rows.Min; y < rows.Max; y++) - { - Span targetRowSpan = destination.GetPixelRowSpan(y); - PixelOperations.Instance.ToVector4(configuration, targetRowSpan, vectorSpan); - ref float ySpanRef = ref kernel.GetYStartReference(y); - ref float xSpanRef = ref kernel.GetXStartReference(y); - - for (int x = 0; x < width; x++) - { - // Use the single precision position to calculate correct bounding pixels - // otherwise we get rogue pixels outside of the bounds. - Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, matrix); - kernel.Convolve(point, x, ref ySpanRef, ref xSpanRef, source.PixelBuffer, vectorSpan); - } - - PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); - } - }); - } - finally - { - kernel.Dispose(); - } + return new ProjectiveTransformProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs new file mode 100644 index 000000000..e6d885803 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs @@ -0,0 +1,126 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + /// + /// Provides the base methods to perform non-affine transforms on an image. + /// + /// The pixel format. + internal class ProjectiveTransformProcessor : TransformProcessorBase + where TPixel : struct, IPixel + { + private readonly ProjectiveTransformProcessor definition; + + public ProjectiveTransformProcessor(ProjectiveTransformProcessor definition) + { + this.definition = definition; + } + + private Size TargetDimensions => this.definition.TargetDimensions; + + /// + protected override Image CreateDestination(Image source, Rectangle sourceRectangle) + { + // We will always be creating the clone even for mutate because we may need to resize the canvas + IEnumerable> frames = + source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions.Width, this.TargetDimensions.Height, x.Metadata.DeepClone())); + + // Use the overload to prevent an extra frame being added + return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); + } + + /// + protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) + { + Matrix4x4 transformMatrix = this.definition.TransformMatrix; + + // Handle tranforms that result in output identical to the original. + if (transformMatrix.Equals(default) || transformMatrix.Equals(Matrix4x4.Identity)) + { + // The clone will be blank here copy all the pixel data over + source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); + return; + } + + int width = this.TargetDimensions.Width; + var targetBounds = new Rectangle(Point.Empty, this.TargetDimensions); + + // Convert from screen to world space. + Matrix4x4.Invert(transformMatrix, out Matrix4x4 matrix); + + IResampler sampler = this.definition.Sampler; + + if (sampler is NearestNeighborResampler) + { + ParallelHelper.IterateRows( + targetBounds, + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span destRow = destination.GetPixelRowSpan(y); + + for (int x = 0; x < width; x++) + { + Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, matrix); + int px = (int)MathF.Round(point.X); + int py = (int)MathF.Round(point.Y); + + if (sourceRectangle.Contains(px, py)) + { + destRow[x] = source[px, py]; + } + } + } + }); + + return; + } + + var kernel = new TransformKernelMap(configuration, source.Size(), destination.Size(), sampler); + try + { + ParallelHelper.IterateRowsWithTempBuffer( + targetBounds, + configuration, + (rows, vectorBuffer) => + { + Span vectorSpan = vectorBuffer.Span; + for (int y = rows.Min; y < rows.Max; y++) + { + Span targetRowSpan = destination.GetPixelRowSpan(y); + PixelOperations.Instance.ToVector4(configuration, targetRowSpan, vectorSpan); + ref float ySpanRef = ref kernel.GetYStartReference(y); + ref float xSpanRef = ref kernel.GetXStartReference(y); + + for (int x = 0; x < width; x++) + { + // Use the single precision position to calculate correct bounding pixels + // otherwise we get rogue pixels outside of the bounds. + Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, matrix); + kernel.Convolve(point, x, ref ySpanRef, ref xSpanRef, source.PixelBuffer, vectorSpan); + } + + PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); + } + }); + } + finally + { + kernel.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs index 57902a5e6..ef0671d20 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs @@ -1,26 +1,19 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Numerics; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Metadata.Profiles.Exif; -using SixLabors.ImageSharp.ParallelUtils; -using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Provides methods that allow the rotating of images. + /// Defines a rotation applicable to an . /// - /// The pixel format. - internal class RotateProcessor : AffineTransformProcessor - where TPixel : struct, IPixel + public sealed class RotateProcessor : AffineTransformProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The angle of rotation in degrees. /// The source image size @@ -30,16 +23,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The angle of rotation in degrees. /// The sampler to perform the rotating operation. /// The source image size public RotateProcessor(float degrees, IResampler sampler, Size sourceSize) : this( - TransformUtils.CreateRotationMatrixDegrees(degrees, sourceSize), - sampler, - sourceSize) + TransformUtils.CreateRotationMatrixDegrees(degrees, sourceSize), + sampler, + sourceSize) => this.Degrees = degrees; // Helper constructor @@ -53,190 +46,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public float Degrees { get; } - /// - protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) + /// + public override IImageProcessor CreatePixelSpecificProcessor() { - if (this.OptimizedApply(source, destination, configuration)) - { - return; - } - - base.OnFrameApply(source, destination, sourceRectangle, configuration); - } - - /// - protected override void AfterImageApply(Image source, Image destination, Rectangle sourceRectangle) - { - ExifProfile profile = destination.Metadata.ExifProfile; - if (profile is null) - { - return; - } - - if (MathF.Abs(WrapDegrees(this.Degrees)) < Constants.Epsilon) - { - // No need to do anything so return. - return; - } - - profile.RemoveValue(ExifTag.Orientation); - - base.AfterImageApply(source, destination, sourceRectangle); - } - - /// - /// Wraps a given angle in degrees so that it falls withing the 0-360 degree range - /// - /// The angle of rotation in degrees. - /// The - private static float WrapDegrees(float degrees) - { - degrees %= 360; - - while (degrees < 0) - { - degrees += 360; - } - - return degrees; - } - - /// - /// Rotates the images with an optimized method when the angle is 90, 180 or 270 degrees. - /// - /// The source image. - /// The destination image. - /// The configuration. - /// - /// The - /// - private bool OptimizedApply(ImageFrame source, ImageFrame destination, Configuration configuration) - { - // Wrap the degrees to keep within 0-360 so we can apply optimizations when possible. - float degrees = WrapDegrees(this.Degrees); - - if (MathF.Abs(degrees) < Constants.Epsilon) - { - // The destination will be blank here so copy all the pixel data over - source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); - return true; - } - - if (MathF.Abs(degrees - 90) < Constants.Epsilon) - { - this.Rotate90(source, destination, configuration); - return true; - } - - if (MathF.Abs(degrees - 180) < Constants.Epsilon) - { - this.Rotate180(source, destination, configuration); - return true; - } - - if (MathF.Abs(degrees - 270) < Constants.Epsilon) - { - this.Rotate270(source, destination, configuration); - return true; - } - - return false; - } - - /// - /// Rotates the image 270 degrees clockwise at the centre point. - /// - /// The source image. - /// The destination image. - /// The configuration. - private void Rotate270(ImageFrame source, ImageFrame destination, Configuration configuration) - { - int width = source.Width; - int height = source.Height; - Rectangle destinationBounds = destination.Bounds(); - - ParallelHelper.IterateRows( - source.Bounds(), - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span sourceRow = source.GetPixelRowSpan(y); - for (int x = 0; x < width; x++) - { - int newX = height - y - 1; - newX = height - newX - 1; - int newY = width - x - 1; - - if (destinationBounds.Contains(newX, newY)) - { - destination[newX, newY] = sourceRow[x]; - } - } - } - }); - } - - /// - /// Rotates the image 180 degrees clockwise at the centre point. - /// - /// The source image. - /// The destination image. - /// The configuration. - private void Rotate180(ImageFrame source, ImageFrame destination, Configuration configuration) - { - int width = source.Width; - int height = source.Height; - - ParallelHelper.IterateRows( - source.Bounds(), - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span sourceRow = source.GetPixelRowSpan(y); - Span targetRow = destination.GetPixelRowSpan(height - y - 1); - - for (int x = 0; x < width; x++) - { - targetRow[width - x - 1] = sourceRow[x]; - } - } - }); - } - - /// - /// Rotates the image 90 degrees clockwise at the centre point. - /// - /// The source image. - /// The destination image. - /// The configuration. - private void Rotate90(ImageFrame source, ImageFrame destination, Configuration configuration) - { - int width = source.Width; - int height = source.Height; - Rectangle destinationBounds = destination.Bounds(); - - ParallelHelper.IterateRows( - source.Bounds(), - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span sourceRow = source.GetPixelRowSpan(y); - int newX = height - y - 1; - for (int x = 0; x < width; x++) - { - if (destinationBounds.Contains(newX, x)) - { - destination[newX, x] = sourceRow[x]; - } - } - } - }); + return new RotateProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor{TPixel}.cs new file mode 100644 index 000000000..aac6f6514 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor{TPixel}.cs @@ -0,0 +1,215 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Metadata.Profiles.Exif; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + /// + /// Provides methods that allow the rotating of images. + /// + /// The pixel format. + internal class RotateProcessor : AffineTransformProcessor + where TPixel : struct, IPixel + { + public RotateProcessor(RotateProcessor definition) + : base(definition) + { + this.Degrees = definition.Degrees; + } + + private float Degrees { get; } + + /// + protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) + { + if (this.OptimizedApply(source, destination, configuration)) + { + return; + } + + base.OnFrameApply(source, destination, sourceRectangle, configuration); + } + + /// + protected override void AfterImageApply(Image source, Image destination, Rectangle sourceRectangle) + { + ExifProfile profile = destination.Metadata.ExifProfile; + if (profile is null) + { + return; + } + + if (MathF.Abs(WrapDegrees(this.Degrees)) < Constants.Epsilon) + { + // No need to do anything so return. + return; + } + + profile.RemoveValue(ExifTag.Orientation); + + base.AfterImageApply(source, destination, sourceRectangle); + } + + /// + /// Wraps a given angle in degrees so that it falls withing the 0-360 degree range + /// + /// The angle of rotation in degrees. + /// The . + private static float WrapDegrees(float degrees) + { + degrees %= 360; + + while (degrees < 0) + { + degrees += 360; + } + + return degrees; + } + + /// + /// Rotates the images with an optimized method when the angle is 90, 180 or 270 degrees. + /// + /// The source image. + /// The destination image. + /// The configuration. + /// + /// The + /// + private bool OptimizedApply(ImageFrame source, ImageFrame destination, Configuration configuration) + { + // Wrap the degrees to keep within 0-360 so we can apply optimizations when possible. + float degrees = WrapDegrees(this.Degrees); + + if (MathF.Abs(degrees) < Constants.Epsilon) + { + // The destination will be blank here so copy all the pixel data over + source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); + return true; + } + + if (MathF.Abs(degrees - 90) < Constants.Epsilon) + { + this.Rotate90(source, destination, configuration); + return true; + } + + if (MathF.Abs(degrees - 180) < Constants.Epsilon) + { + this.Rotate180(source, destination, configuration); + return true; + } + + if (MathF.Abs(degrees - 270) < Constants.Epsilon) + { + this.Rotate270(source, destination, configuration); + return true; + } + + return false; + } + + /// + /// Rotates the image 270 degrees clockwise at the centre point. + /// + /// The source image. + /// The destination image. + /// The configuration. + private void Rotate270(ImageFrame source, ImageFrame destination, Configuration configuration) + { + int width = source.Width; + int height = source.Height; + Rectangle destinationBounds = destination.Bounds(); + + ParallelHelper.IterateRows( + source.Bounds(), + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span sourceRow = source.GetPixelRowSpan(y); + for (int x = 0; x < width; x++) + { + int newX = height - y - 1; + newX = height - newX - 1; + int newY = width - x - 1; + + if (destinationBounds.Contains(newX, newY)) + { + destination[newX, newY] = sourceRow[x]; + } + } + } + }); + } + + /// + /// Rotates the image 180 degrees clockwise at the centre point. + /// + /// The source image. + /// The destination image. + /// The configuration. + private void Rotate180(ImageFrame source, ImageFrame destination, Configuration configuration) + { + int width = source.Width; + int height = source.Height; + + ParallelHelper.IterateRows( + source.Bounds(), + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span sourceRow = source.GetPixelRowSpan(y); + Span targetRow = destination.GetPixelRowSpan(height - y - 1); + + for (int x = 0; x < width; x++) + { + targetRow[width - x - 1] = sourceRow[x]; + } + } + }); + } + + /// + /// Rotates the image 90 degrees clockwise at the centre point. + /// + /// The source image. + /// The destination image. + /// The configuration. + private void Rotate90(ImageFrame source, ImageFrame destination, Configuration configuration) + { + int width = source.Width; + int height = source.Height; + Rectangle destinationBounds = destination.Bounds(); + + ParallelHelper.IterateRows( + source.Bounds(), + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span sourceRow = source.GetPixelRowSpan(y); + int newX = height - y - 1; + for (int x = 0; x < width; x++) + { + if (destinationBounds.Contains(newX, x)) + { + destination[newX, x] = sourceRow[x]; + } + } + } + }); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs index c7b1d7410..35c3717ee 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs @@ -9,14 +9,12 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Provides methods that allow the skewing of images. + /// Defines a skew transformation applicable to an . /// - /// The pixel format. - internal class SkewProcessor : AffineTransformProcessor - where TPixel : struct, IPixel + internal class SkewProcessor : AffineTransformProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The angle in degrees to perform the skew along the x-axis. /// The angle in degrees to perform the skew along the y-axis. @@ -27,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The angle in degrees to perform the skew along the x-axis. /// The angle in degrees to perform the skew along the y-axis. diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorBase.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorBase.cs index 4973b90f4..286ada2e5 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorBase.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorBase.cs @@ -16,6 +16,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// protected override void AfterImageApply(Image source, Image destination, Rectangle sourceRectangle) - => TransformProcessorHelpers.UpdateDimensionalMetData(destination); + => TransformProcessorHelpers.UpdateDimensionalMetadata(destination); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs index 7bb666bce..00c1227a6 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// The pixel format. /// The image to update - public static void UpdateDimensionalMetData(Image image) + public static void UpdateDimensionalMetadata(Image image) where TPixel : struct, IPixel { ExifProfile profile = image.Metadata.ExifProfile; diff --git a/src/ImageSharp/Processing/RotateExtensions.cs b/src/ImageSharp/Processing/RotateExtensions.cs index 398a634d1..cb637a1b8 100644 --- a/src/ImageSharp/Processing/RotateExtensions.cs +++ b/src/ImageSharp/Processing/RotateExtensions.cs @@ -1,48 +1,44 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of rotate operations to the type. + /// Adds extensions that allow the application of rotate operations to the type. /// public static class RotateExtensions { /// /// Rotates and flips an image by the given instructions. /// - /// The pixel format. /// The image to rotate. /// The to perform the rotation. /// The - public static IImageProcessingContext Rotate(this IImageProcessingContext source, RotateMode rotateMode) - where TPixel : struct, IPixel - => Rotate(source, (float)rotateMode); + public static IImageProcessingContext Rotate(this IImageProcessingContext source, RotateMode rotateMode) => + Rotate(source, (float)rotateMode); /// /// Rotates an image by the given angle in degrees. /// - /// The pixel format. /// The image to rotate. /// The angle in degrees to perform the rotation. /// The - public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees) - where TPixel : struct, IPixel - => Rotate(source, degrees, KnownResamplers.Bicubic); + public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees) => + Rotate(source, degrees, KnownResamplers.Bicubic); /// /// Rotates an image by the given angle in degrees using the specified sampling algorithm. /// - /// The pixel format. /// The image to rotate. /// The angle in degrees to perform the rotation. /// The to perform the resampling. /// The - public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees, IResampler sampler) - where TPixel : struct, IPixel - => source.ApplyProcessor(new RotateProcessor(degrees, sampler, source.GetCurrentSize())); + public static IImageProcessingContext Rotate( + this IImageProcessingContext source, + float degrees, + IResampler sampler) => + source.ApplyProcessor(new RotateProcessor(degrees, sampler, source.GetCurrentSize())); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/RotateFlipExtensions.cs b/src/ImageSharp/Processing/RotateFlipExtensions.cs index 27ddc8de9..5030c942e 100644 --- a/src/ImageSharp/Processing/RotateFlipExtensions.cs +++ b/src/ImageSharp/Processing/RotateFlipExtensions.cs @@ -6,20 +6,18 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of rotate-flip operations to the type. + /// Adds extensions that allow the application of rotate-flip operations to the type. /// public static class RotateFlipExtensions { /// /// Rotates and flips an image by the given instructions. /// - /// The pixel format. /// The image to rotate, flip, or both. /// The to perform the rotation. /// The to perform the flip. /// The - public static IImageProcessingContext RotateFlip(this IImageProcessingContext source, RotateMode rotateMode, FlipMode flipMode) - where TPixel : struct, IPixel + public static IImageProcessingContext RotateFlip(this IImageProcessingContext source, RotateMode rotateMode, FlipMode flipMode) => source.Rotate(rotateMode).Flip(flipMode); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/SkewExtensions.cs b/src/ImageSharp/Processing/SkewExtensions.cs index 07e3c6087..7f378d248 100644 --- a/src/ImageSharp/Processing/SkewExtensions.cs +++ b/src/ImageSharp/Processing/SkewExtensions.cs @@ -1,39 +1,39 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of skew operations to the type. + /// Adds extensions that allow the application of skew operations to the type. /// public static class SkewExtensions { /// /// Skews an image by the given angles in degrees. /// - /// The pixel format. /// The image to skew. /// The angle in degrees to perform the skew along the x-axis. /// The angle in degrees to perform the skew along the y-axis. - /// The - public static IImageProcessingContext Skew(this IImageProcessingContext source, float degreesX, float degreesY) - where TPixel : struct, IPixel - => Skew(source, degreesX, degreesY, KnownResamplers.Bicubic); + /// The . + public static IImageProcessingContext + Skew(this IImageProcessingContext source, float degreesX, float degreesY) => + Skew(source, degreesX, degreesY, KnownResamplers.Bicubic); /// /// Skews an image by the given angles in degrees using the specified sampling algorithm. /// - /// The pixel format. /// The image to skew. /// The angle in degrees to perform the skew along the x-axis. /// The angle in degrees to perform the skew along the y-axis. /// The to perform the resampling. - /// The - public static IImageProcessingContext Skew(this IImageProcessingContext source, float degreesX, float degreesY, IResampler sampler) - where TPixel : struct, IPixel - => source.ApplyProcessor(new SkewProcessor(degreesX, degreesY, sampler, source.GetCurrentSize())); + /// The . + public static IImageProcessingContext Skew( + this IImageProcessingContext source, + float degreesX, + float degreesY, + IResampler sampler) => + source.ApplyProcessor(new SkewProcessor(degreesX, degreesY, sampler, source.GetCurrentSize())); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/TransformExtensions.cs b/src/ImageSharp/Processing/TransformExtensions.cs index db14b6baf..35f374d01 100644 --- a/src/ImageSharp/Processing/TransformExtensions.cs +++ b/src/ImageSharp/Processing/TransformExtensions.cs @@ -3,60 +3,53 @@ using System.Numerics; -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of composable transform operations to the type. + /// Adds extensions that allow the application of composable transform operations to the type. /// public static class TransformExtensions { /// /// Performs an affine transform of an image. /// - /// The pixel format. /// The image to transform. /// The affine transform builder. /// The - public static IImageProcessingContext Transform( - this IImageProcessingContext source, - AffineTransformBuilder builder) - where TPixel : struct, IPixel - => Transform(source, builder, KnownResamplers.Bicubic); + public static IImageProcessingContext Transform( + this IImageProcessingContext source, + AffineTransformBuilder builder) => + Transform(source, builder, KnownResamplers.Bicubic); /// /// Performs an affine transform of an image using the specified sampling algorithm. /// - /// The pixel format. - /// The . + /// The . /// The affine transform builder. /// The to perform the resampling. - /// The - public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + /// The . + public static IImageProcessingContext Transform( + this IImageProcessingContext ctx, AffineTransformBuilder builder, - IResampler sampler) - where TPixel : struct, IPixel - => ctx.Transform(new Rectangle(Point.Empty, ctx.GetCurrentSize()), builder, sampler); + IResampler sampler) => + ctx.Transform(new Rectangle(Point.Empty, ctx.GetCurrentSize()), builder, sampler); /// /// Performs an affine transform of an image using the specified sampling algorithm. /// - /// The pixel format. - /// The . + /// The . /// The source rectangle /// The affine transform builder. /// The to perform the resampling. - /// The - public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + /// The . + public static IImageProcessingContext Transform( + this IImageProcessingContext ctx, Rectangle sourceRectangle, AffineTransformBuilder builder, IResampler sampler) - where TPixel : struct, IPixel { Matrix3x2 transform = builder.BuildMatrix(sourceRectangle); Size targetDimensions = TransformUtils.GetTransformedSize(sourceRectangle.Size, transform); @@ -66,69 +59,61 @@ namespace SixLabors.ImageSharp.Processing /// /// Performs an affine transform of an image using the specified sampling algorithm. /// - /// The pixel format. - /// The . + /// The . /// The source rectangle /// The transformation matrix. /// The size of the result image. /// The to perform the resampling. - /// The - public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + /// The . + public static IImageProcessingContext Transform( + this IImageProcessingContext ctx, Rectangle sourceRectangle, Matrix3x2 transform, Size targetDimensions, IResampler sampler) - where TPixel : struct, IPixel { return ctx.ApplyProcessor( - new AffineTransformProcessor(transform, sampler, targetDimensions), + new AffineTransformProcessor(transform, sampler, targetDimensions), sourceRectangle); } /// /// Performs a projective transform of an image. /// - /// The pixel format. /// The image to transform. /// The affine transform builder. - /// The - public static IImageProcessingContext Transform( - this IImageProcessingContext source, - ProjectiveTransformBuilder builder) - where TPixel : struct, IPixel - => Transform(source, builder, KnownResamplers.Bicubic); + /// The . + public static IImageProcessingContext Transform( + this IImageProcessingContext source, + ProjectiveTransformBuilder builder) => + Transform(source, builder, KnownResamplers.Bicubic); /// /// Performs a projective transform of an image using the specified sampling algorithm. /// - /// The pixel format. - /// The . + /// The . /// The projective transform builder. /// The to perform the resampling. - /// The - public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + /// The . + public static IImageProcessingContext Transform( + this IImageProcessingContext ctx, ProjectiveTransformBuilder builder, - IResampler sampler) - where TPixel : struct, IPixel - => ctx.Transform(new Rectangle(Point.Empty, ctx.GetCurrentSize()), builder, sampler); + IResampler sampler) => + ctx.Transform(new Rectangle(Point.Empty, ctx.GetCurrentSize()), builder, sampler); /// /// Performs a projective transform of an image using the specified sampling algorithm. /// - /// The pixel format. - /// The . + /// The . /// The source rectangle /// The projective transform builder. /// The to perform the resampling. - /// The - public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + /// The . + public static IImageProcessingContext Transform( + this IImageProcessingContext ctx, Rectangle sourceRectangle, ProjectiveTransformBuilder builder, IResampler sampler) - where TPixel : struct, IPixel { Matrix4x4 transform = builder.BuildMatrix(sourceRectangle); Size targetDimensions = TransformUtils.GetTransformedSize(sourceRectangle.Size, transform); @@ -138,23 +123,21 @@ namespace SixLabors.ImageSharp.Processing /// /// Performs a projective transform of an image using the specified sampling algorithm. /// - /// The pixel format. - /// The . + /// The . /// The source rectangle /// The transformation matrix. /// The size of the result image. /// The to perform the resampling. - /// The - public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + /// The . + public static IImageProcessingContext Transform( + this IImageProcessingContext ctx, Rectangle sourceRectangle, Matrix4x4 transform, Size targetDimensions, IResampler sampler) - where TPixel : struct, IPixel { return ctx.ApplyProcessor( - new ProjectiveTransformProcessor(transform, sampler, targetDimensions), + new ProjectiveTransformProcessor(transform, sampler, targetDimensions), sourceRectangle); } } diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs index b07f50883..ee04d4388 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs @@ -79,7 +79,8 @@ namespace SixLabors.ImageSharp.Tests .AppendTranslation(new PointF(10, 10)); // Apply a background color so we can see the translation. - blend.Mutate(x => x.Transform(builder).BackgroundColor(NamedColors.HotPink)); + blend.Mutate(x => x.Transform(builder)); + blend.Mutate(x => x.BackgroundColor(NamedColors.HotPink)); // Lets center the matrix so we can tell whether any cut-off issues we may have belong to the drawing processor var position = new Point((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); diff --git a/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs index 6731debd3..1c3bf2e90 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public void CropWidthHeightCropProcessorWithRectangleSet(int width, int height) { this.operations.Crop(width, height); - CropProcessor processor = this.Verify>(); + CropProcessor processor = this.Verify(); Assert.Equal(new Rectangle(0, 0, width, height), processor.CropRectangle); } @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms { var cropRectangle = new Rectangle(x, y, width, height); this.operations.Crop(cropRectangle); - CropProcessor processor = this.Verify>(); + CropProcessor processor = this.Verify(); Assert.Equal(cropRectangle, processor.CropRectangle); } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs index 03a8628a5..aa684acd5 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public void EntropyCropThresholdFloatEntropyCropProcessorWithThreshold(float threshold) { this.operations.EntropyCrop(threshold); - EntropyCropProcessor processor = this.Verify>(); + EntropyCropProcessor processor = this.Verify(); Assert.Equal(threshold, processor.Threshold); } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs index 39adcaa3f..9fe2977ad 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public void Flip_degreesFloat_RotateProcessorWithAnglesSetAndExpandTrue(FlipMode flip) { this.operations.Flip(flip); - FlipProcessor flipProcessor = this.Verify>(); + FlipProcessor flipProcessor = this.Verify(); Assert.Equal(flip, flipProcessor.FlipMode); } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs index 82d768255..b870ddd08 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs @@ -1,15 +1,13 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Transforms; + using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Transforms { - using SixLabors.ImageSharp.Processing; - using SixLabors.ImageSharp.Processing.Processors.Transforms; - public class PadTest : BaseImageOperationsExtensionTest { [Fact] @@ -20,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms IResampler sampler = KnownResamplers.NearestNeighbor; this.operations.Pad(width, height); - ResizeProcessor resizeProcessor = this.Verify>(); + ResizeProcessor resizeProcessor = this.Verify(); Assert.Equal(width, resizeProcessor.Width); Assert.Equal(height, resizeProcessor.Height); diff --git a/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs index dccf7afa6..079ff67b7 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs @@ -26,8 +26,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public void RotateDegreesFloatRotateProcessorWithAnglesSet(RotateMode angle, FlipMode flip, float expectedAngle) { this.operations.RotateFlip(angle, flip); - RotateProcessor rotateProcessor = this.Verify>(0); - FlipProcessor flipProcessor = this.Verify>(1); + RotateProcessor rotateProcessor = this.Verify(0); + FlipProcessor flipProcessor = this.Verify(1); Assert.Equal(expectedAngle, rotateProcessor.Degrees); Assert.Equal(flip, flipProcessor.FlipMode); diff --git a/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs index ae312d723..3e2b85971 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public void RotateDegreesFloatRotateProcessorWithAnglesSet(float angle) { this.operations.Rotate(angle); - RotateProcessor processor = this.Verify>(); + RotateProcessor processor = this.Verify(); Assert.Equal(angle, processor.Degrees); } @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public void RotateRotateTypeRotateProcessorWithAnglesConvertedFromEnum(RotateMode angle, float expectedAngle) { this.operations.Rotate(angle); // is this api needed ??? - RotateProcessor processor = this.Verify>(); + RotateProcessor processor = this.Verify(); Assert.Equal(expectedAngle, processor.Degrees); } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs index 73754b971..38033e80d 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public void SkewXYCreateSkewProcessorWithAnglesSet() { this.operations.Skew(10, 20); - SkewProcessor processor = this.Verify>(); + SkewProcessor processor = this.Verify(); Assert.Equal(10, processor.DegreesX); Assert.Equal(20, processor.DegreesY); diff --git a/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs index a62f4fc7c..3ac9af960 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms Assert.Equal(ExifDataType.Long, profile.GetValue(ExifTag.PixelXDimension).DataType); Assert.Equal(ExifDataType.Long, profile.GetValue(ExifTag.PixelYDimension).DataType); - TransformProcessorHelpers.UpdateDimensionalMetData(img); + TransformProcessorHelpers.UpdateDimensionalMetadata(img); Assert.Equal(ExifDataType.Short, profile.GetValue(ExifTag.PixelXDimension).DataType); Assert.Equal(ExifDataType.Short, profile.GetValue(ExifTag.PixelYDimension).DataType); From 484c08e0796da7c128547b2d20f70fc73770bddc Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 02:36:41 +0200 Subject: [PATCH 131/223] sealed everything --- .../Processing/Processors/Convolution/BoxBlurProcessor.cs | 2 +- ...lution2DProcessor.cs => Convolution2DProcessor{TPixel}.cs} | 3 ++- ...2PassProcessor.cs => Convolution2PassProcessor{TPixel}.cs} | 0 ...onvolutionProcessor.cs => ConvolutionProcessor{TPixel}.cs} | 0 ...ector2DProcessor.cs => EdgeDetector2DProcessor{TPixel}.cs} | 0 ...ssProcessor.cs => EdgeDetectorCompassProcessor{TPixel}.cs} | 0 .../Processors/Convolution/GaussianBlurProcessor.cs | 2 +- .../Processors/Convolution/GaussianSharpenProcessor.cs | 2 +- .../Processing/Processors/Convolution/KayyaliProcessor.cs | 2 +- .../Processing/Processors/Convolution/KirschProcessor.cs | 2 +- .../Processors/Convolution/Laplacian3x3Processor.cs | 2 +- .../Processors/Convolution/Laplacian5x5Processor.cs | 2 +- .../Processors/Convolution/LaplacianOfGaussianProcessor.cs | 2 +- .../Processing/Processors/Convolution/PrewittProcessor.cs | 2 +- .../Processors/Convolution/RobertsCrossProcessor.cs | 2 +- .../Processing/Processors/Convolution/RobinsonProcessor.cs | 2 +- .../Processing/Processors/Convolution/ScharrProcessor.cs | 2 +- .../Processing/Processors/Convolution/SobelProcessor.cs | 2 +- .../Processing/Processors/Effects/OilPaintingProcessor.cs | 2 +- .../Processing/Processors/Effects/PixelateProcessor.cs | 2 +- .../Processing/Processors/Filters/AchromatomalyProcessor.cs | 4 +--- .../Processing/Processors/Filters/AchromatopsiaProcessor.cs | 4 +--- .../Processing/Processors/Filters/BlackWhiteProcessor.cs | 4 +--- .../Processing/Processors/Filters/BrightnessProcessor.cs | 4 +--- .../Processing/Processors/Filters/ContrastProcessor.cs | 4 +--- .../Processing/Processors/Filters/DeuteranomalyProcessor.cs | 4 +--- .../Processing/Processors/Filters/DeuteranopiaProcessor.cs | 4 +--- .../Processing/Processors/Filters/GrayscaleBt601Processor.cs | 4 +--- .../Processing/Processors/Filters/GrayscaleBt709Processor.cs | 2 +- src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs | 4 +--- .../Processing/Processors/Filters/InvertProcessor.cs | 4 +--- .../Processing/Processors/Filters/KodachromeProcessor.cs | 2 +- .../Processing/Processors/Filters/LomographProcessor.cs | 2 +- .../Processing/Processors/Filters/OpacityProcessor.cs | 2 +- .../Processing/Processors/Filters/PolaroidProcessor.cs | 2 +- .../Processing/Processors/Filters/ProtanomalyProcessor.cs | 4 +--- .../Processing/Processors/Filters/ProtanopiaProcessor.cs | 4 +--- .../Processing/Processors/Filters/SaturateProcessor.cs | 4 +--- .../Processing/Processors/Filters/SepiaProcessor.cs | 4 +--- .../Processing/Processors/Filters/TritanomalyProcessor.cs | 4 +--- .../Processing/Processors/Filters/TritanopiaProcessor.cs | 4 +--- .../Processing/Processors/Transforms/FlipProcessor.cs | 2 +- .../Processing/Processors/Transforms/SkewProcessor.cs | 2 +- 43 files changed, 40 insertions(+), 71 deletions(-) rename src/ImageSharp/Processing/Processors/Convolution/{Convolution2DProcessor.cs => Convolution2DProcessor{TPixel}.cs} (99%) rename src/ImageSharp/Processing/Processors/Convolution/{Convolution2PassProcessor.cs => Convolution2PassProcessor{TPixel}.cs} (100%) rename src/ImageSharp/Processing/Processors/Convolution/{ConvolutionProcessor.cs => ConvolutionProcessor{TPixel}.cs} (100%) rename src/ImageSharp/Processing/Processors/Convolution/{EdgeDetector2DProcessor.cs => EdgeDetector2DProcessor{TPixel}.cs} (100%) rename src/ImageSharp/Processing/Processors/Convolution/{EdgeDetectorCompassProcessor.cs => EdgeDetectorCompassProcessor{TPixel}.cs} (100%) diff --git a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs index bb37489e1..4e56e75d3 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Defines a box blur processor of a given Radius. /// - public class BoxBlurProcessor : IImageProcessor + public sealed class BoxBlurProcessor : IImageProcessor { /// /// The default radius used by the parameterless constructor. diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs similarity index 99% rename from src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs rename to src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs index 633b50a9b..299b1d41c 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs @@ -1,9 +1,10 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using System.Numerics; using System.Runtime.InteropServices; + using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs rename to src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs rename to src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs rename to src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs similarity index 100% rename from src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs rename to src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs index c64a024f9..764f4ca51 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Defines Gaussian blur by a (Sigma, Radius) pair. /// - public class GaussianBlurProcessor : IImageProcessor + public sealed class GaussianBlurProcessor : IImageProcessor { /// /// The default value for . diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs index 84e56869d..23282af36 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Defines Gaussian sharpening by a (Sigma, Radius) pair. /// - public class GaussianSharpenProcessor : IImageProcessor + public sealed class GaussianSharpenProcessor : IImageProcessor { /// /// The default value for . diff --git a/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs index 99dfb17ff..2d0f056b6 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/KayyaliProcessor.cs @@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines edge detection processing using the Kayyali operator filter. /// See . /// - public class KayyaliProcessor : EdgeDetectorProcessor + public sealed class KayyaliProcessor : EdgeDetectorProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs index fc73903c7..9e9534422 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/KirschProcessor.cs @@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines edge detection using the Kirsch operator filter. /// See . /// - public class KirschProcessor : EdgeDetectorProcessor + public sealed class KirschProcessor : EdgeDetectorProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs b/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs index 18a53cb13..9c9488fec 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Laplacian3x3Processor.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Applies edge detection processing to the image using the Laplacian 3x3 operator filter. /// /// - public class Laplacian3x3Processor : EdgeDetectorProcessor + public sealed class Laplacian3x3Processor : EdgeDetectorProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs b/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs index 1c95ca490..fa0c8c5aa 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Laplacian5x5Processor.cs @@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines edge detection processing using the Laplacian 5x5 operator filter. /// . /// - public class Laplacian5x5Processor : EdgeDetectorProcessor + public sealed class Laplacian5x5Processor : EdgeDetectorProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs index d904d69b1..2caff8201 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/LaplacianOfGaussianProcessor.cs @@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Applies edge detection processing to the image using the Laplacian of Gaussian operator filter. /// See . /// - public class LaplacianOfGaussianProcessor : EdgeDetectorProcessor + public sealed class LaplacianOfGaussianProcessor : EdgeDetectorProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs index 939b1e0c5..29f6fc279 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/PrewittProcessor.cs @@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines edge detection using the Prewitt operator filter. /// See . /// - public class PrewittProcessor : EdgeDetectorProcessor + public sealed class PrewittProcessor : EdgeDetectorProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs index ff41b6c69..a9db37a07 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/RobertsCrossProcessor.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines edge detection processing using the Roberts Cross operator filter. /// See . /// - public class RobertsCrossProcessor : EdgeDetectorProcessor + public sealed class RobertsCrossProcessor : EdgeDetectorProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs index 603a81f67..fd7378902 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/RobinsonProcessor.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines edge detection using the Robinson operator filter. /// See . /// - internal class RobinsonProcessor : EdgeDetectorProcessor + public sealed class RobinsonProcessor : EdgeDetectorProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs index d23ba5338..ec0183dc6 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ScharrProcessor.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines edge detection processing using the Scharr operator filter. /// /// - public class ScharrProcessor : EdgeDetectorProcessor + public sealed class ScharrProcessor : EdgeDetectorProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs index 157bb62e5..bc4339e05 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Defines edge detection using the Sobel operator filter. /// See . /// - public class SobelProcessor : EdgeDetectorProcessor + public sealed class SobelProcessor : EdgeDetectorProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs index 14e164fb7..741ba9ece 100644 --- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects /// /// Defines an oil painting effect. /// - public class OilPaintingProcessor : IImageProcessor + public sealed class OilPaintingProcessor : IImageProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs index eeb2aafcb..1599c9dab 100644 --- a/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects /// /// Defines a pixelation effect of a given size. /// - public class PixelateProcessor : IImageProcessor + public sealed class PixelateProcessor : IImageProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs index 7c3789c38..0e6653d99 100644 --- a/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/AchromatomalyProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness. /// - public class AchromatomalyProcessor : FilterProcessor + public sealed class AchromatomalyProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs index ab04a30ba..10a201b1d 100644 --- a/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/AchromatopsiaProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness. /// - public class AchromatopsiaProcessor : FilterProcessor + public sealed class AchromatopsiaProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs index 7e2e7f2f4..425ae511f 100644 --- a/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/BlackWhiteProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Applies a black and white filter matrix to the image. /// - public class BlackWhiteProcessor : FilterProcessor + public sealed class BlackWhiteProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs index 94a7a394a..77862b3e3 100644 --- a/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/BrightnessProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Applies a brightness filter matrix using the given amount. /// - public class BrightnessProcessor : FilterProcessor + public sealed class BrightnessProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs index 1f74a1d64..3fdeafde3 100644 --- a/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/ContrastProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Applies a contrast filter matrix using the given amount. /// - public class ContrastProcessor : FilterProcessor + public sealed class ContrastProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs index 7ad0630aa..7e1c0ca50 100644 --- a/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/DeuteranomalyProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Converts the colors of the image recreating Deuteranomaly (Green-Weak) color blindness. /// - public class DeuteranomalyProcessor : FilterProcessor + public sealed class DeuteranomalyProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs index 188d02dc8..e4ed44e74 100644 --- a/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/DeuteranopiaProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Converts the colors of the image recreating Deuteranopia (Green-Blind) color blindness. /// - public class DeuteranopiaProcessor : FilterProcessor + public sealed class DeuteranopiaProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs index c24992b44..153a1a17c 100644 --- a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt601Processor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Applies a grayscale filter matrix using the given amount and the formula as specified by ITU-R Recommendation BT.601 /// - public class GrayscaleBt601Processor : FilterProcessor + public sealed class GrayscaleBt601Processor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs index dc5294ccf..2d7d2a1ea 100644 --- a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a grayscale filter matrix using the given amount and the formula as specified by ITU-R Recommendation BT.709 /// - public class GrayscaleBt709Processor : FilterProcessor + public sealed class GrayscaleBt709Processor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs index 65f7eef33..05d3cbdc7 100644 --- a/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/HueProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Applies a hue filter matrix using the given angle of rotation in degrees /// - public class HueProcessor : FilterProcessor + public sealed class HueProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs index cc41e6572..99b138033 100644 --- a/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/InvertProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Applies a filter matrix that inverts the colors of an image /// - public class InvertProcessor : FilterProcessor + public sealed class InvertProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs index a5215a434..012b10ee0 100644 --- a/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/KodachromeProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies a filter matrix recreating an old Kodachrome camera effect matrix to the image /// - public class KodachromeProcessor : FilterProcessor + public sealed class KodachromeProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs index dae168e2c..f5a1befff 100644 --- a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor.cs @@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating an old Lomograph effect. /// - public class LomographProcessor : FilterProcessor + public sealed class LomographProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs index 0ee5dd59e..922ca3233 100644 --- a/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/OpacityProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Applies an opacity filter matrix using the given amount. /// - public class OpacityProcessor : FilterProcessor + public sealed class OpacityProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs index 341c02acf..676bbc06b 100644 --- a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor.cs @@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// /// Converts the colors of the image recreating an old Polaroid effect. /// - public class PolaroidProcessor : FilterProcessor + public sealed class PolaroidProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs index 755bc0f81..1c01b608e 100644 --- a/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/ProtanomalyProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Converts the colors of the image recreating Protanomaly (Red-Weak) color blindness. /// - public class ProtanomalyProcessor : FilterProcessor + public sealed class ProtanomalyProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs index c4f4a7661..ec423bd9a 100644 --- a/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/ProtanopiaProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Converts the colors of the image recreating Protanopia (Red-Blind) color blindness. /// - public class ProtanopiaProcessor : FilterProcessor + public sealed class ProtanopiaProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs index 770fb9827..2cc40664b 100644 --- a/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/SaturateProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Applies a saturation filter matrix using the given amount. /// - public class SaturateProcessor : FilterProcessor + public sealed class SaturateProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs index 9da48993a..34af41067 100644 --- a/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/SepiaProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Applies a sepia filter matrix using the given amount. /// - public class SepiaProcessor : FilterProcessor + public sealed class SepiaProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs index c64475b99..a31e52c7e 100644 --- a/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/TritanomalyProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Converts the colors of the image recreating Tritanomaly (Blue-Weak) color blindness. /// - public class TritanomalyProcessor : FilterProcessor + public sealed class TritanomalyProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs index 722840e74..b622126f3 100644 --- a/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/TritanopiaProcessor.cs @@ -1,14 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; - namespace SixLabors.ImageSharp.Processing.Processors.Filters { /// /// Converts the colors of the image recreating Tritanopia (Blue-Blind) color blindness. /// - public class TritanopiaProcessor : FilterProcessor + public sealed class TritanopiaProcessor : FilterProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs index 9a3eab6cc..f604d8399 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// Defines a flipping around the center point of the image. /// - public class FlipProcessor : IImageProcessor + public sealed class FlipProcessor : IImageProcessor { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs index 35c3717ee..cb73bb66c 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// Defines a skew transformation applicable to an . /// - internal class SkewProcessor : AffineTransformProcessor + public sealed class SkewProcessor : AffineTransformProcessor { /// /// Initializes a new instance of the class. From a11141d568281fd995b019a4085d35251e0f3104 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 15:56:34 +0200 Subject: [PATCH 132/223] refactor HistogramEqualization --- .../HistogramEqualizationExtension.cs | 44 +- .../AdaptiveHistEqualizationProcessor.cs | 526 +---------------- ...aptiveHistEqualizationProcessor{TPixel}.cs | 546 ++++++++++++++++++ .../AdaptiveHistEqualizationSWProcessor.cs | 371 +----------- ...tiveHistEqualizationSWProcessor{TPixel}.cs | 390 +++++++++++++ .../GlobalHistogramEqualizationProcessor.cs | 99 +--- ...lHistogramEqualizationProcessor{TPixel}.cs | 107 ++++ .../HistogramEqualizationOptions.cs | 2 +- .../HistogramEqualizationProcessor.cs | 134 ++--- .../HistogramEqualizationProcessor{TPixel}.cs | 139 +++++ .../HistogramEqualizationTests.cs | 4 +- .../Processors/Dithering/DitherTests.cs | 3 +- 12 files changed, 1264 insertions(+), 1101 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs diff --git a/src/ImageSharp/Processing/HistogramEqualizationExtension.cs b/src/ImageSharp/Processing/HistogramEqualizationExtension.cs index d967ef362..aae3e997f 100644 --- a/src/ImageSharp/Processing/HistogramEqualizationExtension.cs +++ b/src/ImageSharp/Processing/HistogramEqualizationExtension.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Normalization; namespace SixLabors.ImageSharp.Processing @@ -14,49 +13,20 @@ namespace SixLabors.ImageSharp.Processing /// /// Equalizes the histogram of an image to increases the contrast. /// - /// The pixel format. /// The image this method extends. /// The . - public static IImageProcessingContext HistogramEqualization(this IImageProcessingContext source) - where TPixel : struct, IPixel - => HistogramEqualization(source, HistogramEqualizationOptions.Default); + public static IImageProcessingContext HistogramEqualization(this IImageProcessingContext source) => + HistogramEqualization(source, HistogramEqualizationOptions.Default); /// /// Equalizes the histogram of an image to increases the contrast. /// - /// The pixel format. /// The image this method extends. /// The histogram equalization options to use. /// The . - public static IImageProcessingContext HistogramEqualization(this IImageProcessingContext source, HistogramEqualizationOptions options) - where TPixel : struct, IPixel - => source.ApplyProcessor(GetProcessor(options)); - - private static HistogramEqualizationProcessor GetProcessor(HistogramEqualizationOptions options) - where TPixel : struct, IPixel - { - HistogramEqualizationProcessor processor; - - switch (options.Method) - { - case HistogramEqualizationMethod.Global: - processor = new GlobalHistogramEqualizationProcessor(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage); - break; - - case HistogramEqualizationMethod.AdaptiveTileInterpolation: - processor = new AdaptiveHistEqualizationProcessor(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage, options.Tiles); - break; - - case HistogramEqualizationMethod.AdaptiveSlidingWindow: - processor = new AdaptiveHistEqualizationSWProcessor(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage, options.Tiles); - break; - - default: - processor = new GlobalHistogramEqualizationProcessor(options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage); - break; - } - - return processor; - } + public static IImageProcessingContext HistogramEqualization( + this IImageProcessingContext source, + HistogramEqualizationOptions options) => + source.ApplyProcessor(HistogramEqualizationProcessor.FromOptions(options)); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs index cb52a88b7..4fd0f853d 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs @@ -1,545 +1,37 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Threading.Tasks; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; -using SixLabors.Primitives; - namespace SixLabors.ImageSharp.Processing.Processors.Normalization { /// /// Applies an adaptive histogram equalization to the image. The image is split up in tiles. For each tile a cumulative distribution function (cdf) is calculated. /// To calculate the final equalized pixel value, the cdf value of four adjacent tiles will be interpolated. /// - /// The pixel format. - internal class AdaptiveHistEqualizationProcessor : HistogramEqualizationProcessor - where TPixel : struct, IPixel + internal class AdaptiveHistEqualizationProcessor : HistogramEqualizationProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images /// or 65536 for 16-bit grayscale images. /// Indicating whether to clip the histogram bins at a specific value. /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. - /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. - public AdaptiveHistEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int tiles) + /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. + public AdaptiveHistEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int numberOfTiles) : base(luminanceLevels, clipHistogram, clipLimitPercentage) { - Guard.MustBeGreaterThanOrEqualTo(tiles, 2, nameof(tiles)); - Guard.MustBeLessThanOrEqualTo(tiles, 100, nameof(tiles)); - - this.Tiles = tiles; + this.NumberOfTiles = numberOfTiles; } /// /// Gets the number of tiles the image is split into (horizontal and vertically) for the adaptive histogram equalization. /// - private int Tiles { get; } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - int sourceWidth = source.Width; - int sourceHeight = source.Height; - int numberOfPixels = sourceWidth * sourceHeight; - int tileWidth = (int)MathF.Ceiling(sourceWidth / (float)this.Tiles); - int tileHeight = (int)MathF.Ceiling(sourceHeight / (float)this.Tiles); - int pixelsInTile = tileWidth * tileHeight; - int halfTileWidth = tileWidth / 2; - int halfTileHeight = tileHeight / 2; - int luminanceLevels = this.LuminanceLevels; - - // The image is split up into tiles. For each tile the cumulative distribution function will be calculated. - using (var cdfData = new CdfTileData(configuration, sourceWidth, sourceHeight, this.Tiles, this.Tiles, tileWidth, tileHeight, luminanceLevels)) - { - cdfData.CalculateLookupTables(source, this); - - var tileYStartPositions = new List<(int y, int cdfY)>(); - int cdfY = 0; - for (int y = halfTileHeight; y < sourceHeight - halfTileHeight; y += tileHeight) - { - tileYStartPositions.Add((y, cdfY)); - cdfY++; - } - - Parallel.For( - 0, - tileYStartPositions.Count, - new ParallelOptions() { MaxDegreeOfParallelism = configuration.MaxDegreeOfParallelism }, - index => - { - int cdfX = 0; - int tileX = 0; - int tileY = 0; - int y = tileYStartPositions[index].y; - int cdfYY = tileYStartPositions[index].cdfY; - - // It's unfortunate that we have to do this per iteration. - ref TPixel sourceBase = ref source.GetPixelReference(0, 0); - - cdfX = 0; - for (int x = halfTileWidth; x < sourceWidth - halfTileWidth; x += tileWidth) - { - tileY = 0; - int yEnd = Math.Min(y + tileHeight, sourceHeight); - int xEnd = Math.Min(x + tileWidth, sourceWidth); - for (int dy = y; dy < yEnd; dy++) - { - int dyOffSet = dy * sourceWidth; - tileX = 0; - for (int dx = x; dx < xEnd; dx++) - { - ref TPixel pixel = ref Unsafe.Add(ref sourceBase, dyOffSet + dx); - float luminanceEqualized = InterpolateBetweenFourTiles( - pixel, - cdfData, - this.Tiles, - this.Tiles, - tileX, - tileY, - cdfX, - cdfYY, - tileWidth, - tileHeight, - luminanceLevels); - - pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); - tileX++; - } - - tileY++; - } - - cdfX++; - } - }); - - ref TPixel pixelsBase = ref source.GetPixelReference(0, 0); - - // Fix left column - ProcessBorderColumn(ref pixelsBase, cdfData, 0, sourceWidth, sourceHeight, tileWidth, tileHeight, xStart: 0, xEnd: halfTileWidth, luminanceLevels); - - // Fix right column - int rightBorderStartX = ((this.Tiles - 1) * tileWidth) + halfTileWidth; - ProcessBorderColumn(ref pixelsBase, cdfData, this.Tiles - 1, sourceWidth, sourceHeight, tileWidth, tileHeight, xStart: rightBorderStartX, xEnd: sourceWidth, luminanceLevels); - - // Fix top row - ProcessBorderRow(ref pixelsBase, cdfData, 0, sourceWidth, tileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); - - // Fix bottom row - int bottomBorderStartY = ((this.Tiles - 1) * tileHeight) + halfTileHeight; - ProcessBorderRow(ref pixelsBase, cdfData, this.Tiles - 1, sourceWidth, tileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); - - // Left top corner - ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, 0, 0, xStart: 0, xEnd: halfTileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); - - // Left bottom corner - ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, 0, this.Tiles - 1, xStart: 0, xEnd: halfTileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); - - // Right top corner - ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, this.Tiles - 1, 0, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); - - // Right bottom corner - ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, this.Tiles - 1, this.Tiles - 1, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); - } - } - - /// - /// Processes the part of a corner tile which was previously left out. It consists of 1 / 4 of a tile and does not need interpolation. - /// - /// The output pixels base reference. - /// The lookup table to remap the grey values. - /// The source image width. - /// The x-position in the CDF lookup map. - /// The y-position in the CDF lookup map. - /// X start position. - /// X end position. - /// Y start position. - /// Y end position. - /// - /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images - /// or 65536 for 16-bit grayscale images. - /// - private static void ProcessCornerTile( - ref TPixel pixelsBase, - CdfTileData cdfData, - int sourceWidth, - int cdfX, - int cdfY, - int xStart, - int xEnd, - int yStart, - int yEnd, - int luminanceLevels) - { - for (int dy = yStart; dy < yEnd; dy++) - { - int dyOffSet = dy * sourceWidth; - for (int dx = xStart; dx < xEnd; dx++) - { - ref TPixel pixel = ref Unsafe.Add(ref pixelsBase, dyOffSet + dx); - float luminanceEqualized = cdfData.RemapGreyValue(cdfX, cdfY, GetLuminance(pixel, luminanceLevels)); - pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); - } - } - } - - /// - /// Processes a border column of the image which is half the size of the tile width. - /// - /// The output pixels reference. - /// The pre-computed lookup tables to remap the grey values for each tiles. - /// The X index of the lookup table to use. - /// The source image width. - /// The source image height. - /// The width of a tile. - /// The height of a tile. - /// X start position in the image. - /// X end position of the image. - /// - /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images - /// or 65536 for 16-bit grayscale images. - /// - private static void ProcessBorderColumn( - ref TPixel pixelBase, - CdfTileData cdfData, - int cdfX, - int sourceWidth, - int sourceHeight, - int tileWidth, - int tileHeight, - int xStart, - int xEnd, - int luminanceLevels) - { - int halfTileWidth = tileWidth / 2; - int halfTileHeight = tileHeight / 2; - - int cdfY = 0; - for (int y = halfTileHeight; y < sourceHeight - halfTileHeight; y += tileHeight) - { - int yLimit = Math.Min(y + tileHeight, sourceHeight - 1); - int tileY = 0; - for (int dy = y; dy < yLimit; dy++) - { - int dyOffSet = dy * sourceWidth; - int tileX = halfTileWidth; - for (int dx = xStart; dx < xEnd; dx++) - { - ref TPixel pixel = ref Unsafe.Add(ref pixelBase, dyOffSet + dx); - float luminanceEqualized = InterpolateBetweenTwoTiles(pixel, cdfData, cdfX, cdfY, cdfX, cdfY + 1, tileY, tileHeight, luminanceLevels); - pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); - tileX++; - } - - tileY++; - } - - cdfY++; - } - } + public int NumberOfTiles { get; } - /// - /// Processes a border row of the image which is half of the size of the tile height. - /// - /// The output pixels base reference. - /// The pre-computed lookup tables to remap the grey values for each tiles. - /// The Y index of the lookup table to use. - /// The source image width. - /// The width of a tile. - /// Y start position in the image. - /// Y end position of the image. - /// - /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images - /// or 65536 for 16-bit grayscale images. - /// - private static void ProcessBorderRow( - ref TPixel pixelBase, - CdfTileData cdfData, - int cdfY, - int sourceWidth, - int tileWidth, - int yStart, - int yEnd, - int luminanceLevels) + /// + public override IImageProcessor CreatePixelSpecificProcessor() { - int halfTileWidth = tileWidth / 2; - - int cdfX = 0; - for (int x = halfTileWidth; x < sourceWidth - halfTileWidth; x += tileWidth) - { - int tileY = 0; - for (int dy = yStart; dy < yEnd; dy++) - { - int dyOffSet = dy * sourceWidth; - int tileX = 0; - int xLimit = Math.Min(x + tileWidth, sourceWidth - 1); - for (int dx = x; dx < xLimit; dx++) - { - ref TPixel pixel = ref Unsafe.Add(ref pixelBase, dyOffSet + dx); - float luminanceEqualized = InterpolateBetweenTwoTiles(pixel, cdfData, cdfX, cdfY, cdfX + 1, cdfY, tileX, tileWidth, luminanceLevels); - pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); - tileX++; - } - - tileY++; - } - - cdfX++; - } - } - - /// - /// Bilinear interpolation between four adjacent tiles. - /// - /// The pixel to remap the grey value from. - /// The pre-computed lookup tables to remap the grey values for each tiles. - /// The number of tiles in the x-direction. - /// The number of tiles in the y-direction. - /// X position inside the tile. - /// Y position inside the tile. - /// X index of the top left lookup table to use. - /// Y index of the top left lookup table to use. - /// Width of one tile in pixels. - /// Height of one tile in pixels. - /// - /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images - /// or 65536 for 16-bit grayscale images. - /// - /// A re-mapped grey value. - [MethodImpl(InliningOptions.ShortMethod)] - private static float InterpolateBetweenFourTiles( - TPixel sourcePixel, - CdfTileData cdfData, - int tileCountX, - int tileCountY, - int tileX, - int tileY, - int cdfX, - int cdfY, - int tileWidth, - int tileHeight, - int luminanceLevels) - { - int luminance = GetLuminance(sourcePixel, luminanceLevels); - float tx = tileX / (float)(tileWidth - 1); - float ty = tileY / (float)(tileHeight - 1); - - int yTop = cdfY; - int yBottom = Math.Min(tileCountY - 1, yTop + 1); - int xLeft = cdfX; - int xRight = Math.Min(tileCountX - 1, xLeft + 1); - - float cdfLeftTopLuminance = cdfData.RemapGreyValue(xLeft, yTop, luminance); - float cdfRightTopLuminance = cdfData.RemapGreyValue(xRight, yTop, luminance); - float cdfLeftBottomLuminance = cdfData.RemapGreyValue(xLeft, yBottom, luminance); - float cdfRightBottomLuminance = cdfData.RemapGreyValue(xRight, yBottom, luminance); - return BilinearInterpolation(tx, ty, cdfLeftTopLuminance, cdfRightTopLuminance, cdfLeftBottomLuminance, cdfRightBottomLuminance); - } - - /// - /// Linear interpolation between two tiles. - /// - /// The pixel to remap the grey value from. - /// The CDF lookup map. - /// X position inside the first tile. - /// Y position inside the first tile. - /// X position inside the second tile. - /// Y position inside the second tile. - /// Position inside the tile. - /// Width of the tile. - /// - /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images - /// or 65536 for 16-bit grayscale images. - /// - /// A re-mapped grey value. - [MethodImpl(InliningOptions.ShortMethod)] - private static float InterpolateBetweenTwoTiles( - TPixel sourcePixel, - CdfTileData cdfData, - int tileX1, - int tileY1, - int tileX2, - int tileY2, - int tilePos, - int tileWidth, - int luminanceLevels) - { - int luminance = GetLuminance(sourcePixel, luminanceLevels); - float tx = tilePos / (float)(tileWidth - 1); - - float cdfLuminance1 = cdfData.RemapGreyValue(tileX1, tileY1, luminance); - float cdfLuminance2 = cdfData.RemapGreyValue(tileX2, tileY2, luminance); - return LinearInterpolation(cdfLuminance1, cdfLuminance2, tx); - } - - /// - /// Bilinear interpolation between four tiles. - /// - /// The interpolation value in x direction in the range of [0, 1]. - /// The interpolation value in y direction in the range of [0, 1]. - /// Luminance from top left tile. - /// Luminance from right top tile. - /// Luminance from left bottom tile. - /// Luminance from right bottom tile. - /// Interpolated Luminance. - [MethodImpl(InliningOptions.ShortMethod)] - private static float BilinearInterpolation(float tx, float ty, float lt, float rt, float lb, float rb) - => LinearInterpolation(LinearInterpolation(lt, rt, tx), LinearInterpolation(lb, rb, tx), ty); - - /// - /// Linear interpolation between two grey values. - /// - /// The left value. - /// The right value. - /// The interpolation value between the two values in the range of [0, 1]. - /// The interpolated value. - [MethodImpl(InliningOptions.ShortMethod)] - private static float LinearInterpolation(float left, float right, float t) - => left + ((right - left) * t); - - /// - /// Contains the results of the cumulative distribution function for all tiles. - /// - private sealed class CdfTileData : IDisposable - { - private readonly Configuration configuration; - private readonly MemoryAllocator memoryAllocator; - - // Used for storing the minimum value for each CDF entry. - private readonly Buffer2D cdfMinBuffer2D; - - // Used for storing the LUT for each CDF entry. - private readonly Buffer2D cdfLutBuffer2D; - private readonly int pixelsInTile; - private readonly int sourceWidth; - private readonly int sourceHeight; - private readonly int tileWidth; - private readonly int tileHeight; - private readonly int luminanceLevels; - private readonly List<(int y, int cdfY)> tileYStartPositions; - - public CdfTileData( - Configuration configuration, - int sourceWidth, - int sourceHeight, - int tileCountX, - int tileCountY, - int tileWidth, - int tileHeight, - int luminanceLevels) - { - this.configuration = configuration; - this.memoryAllocator = configuration.MemoryAllocator; - this.luminanceLevels = luminanceLevels; - this.cdfMinBuffer2D = this.memoryAllocator.Allocate2D(tileCountX, tileCountY); - this.cdfLutBuffer2D = this.memoryAllocator.Allocate2D(tileCountX * luminanceLevels, tileCountY); - this.sourceWidth = sourceWidth; - this.sourceHeight = sourceHeight; - this.tileWidth = tileWidth; - this.tileHeight = tileHeight; - this.pixelsInTile = tileWidth * tileHeight; - - // Calculate the start positions and rent buffers. - this.tileYStartPositions = new List<(int y, int cdfY)>(); - int cdfY = 0; - for (int y = 0; y < sourceHeight; y += tileHeight) - { - this.tileYStartPositions.Add((y, cdfY)); - cdfY++; - } - } - - public void CalculateLookupTables(ImageFrame source, HistogramEqualizationProcessor processor) - { - int sourceWidth = this.sourceWidth; - int sourceHeight = this.sourceHeight; - int tileWidth = this.tileWidth; - int tileHeight = this.tileHeight; - int luminanceLevels = this.luminanceLevels; - MemoryAllocator memoryAllocator = this.memoryAllocator; - - Parallel.For( - 0, - this.tileYStartPositions.Count, - new ParallelOptions() { MaxDegreeOfParallelism = this.configuration.MaxDegreeOfParallelism }, - index => - { - int cdfX = 0; - int cdfY = this.tileYStartPositions[index].cdfY; - int y = this.tileYStartPositions[index].y; - int endY = Math.Min(y + tileHeight, sourceHeight); - ref TPixel sourceBase = ref source.GetPixelReference(0, 0); - ref int cdfMinBase = ref MemoryMarshal.GetReference(this.cdfMinBuffer2D.GetRowSpan(cdfY)); - - using (IMemoryOwner histogramBuffer = this.memoryAllocator.Allocate(luminanceLevels)) - { - Span histogram = histogramBuffer.GetSpan(); - ref int histogramBase = ref MemoryMarshal.GetReference(histogram); - - for (int x = 0; x < sourceWidth; x += tileWidth) - { - histogram.Clear(); - ref int cdfBase = ref MemoryMarshal.GetReference(this.GetCdfLutSpan(cdfX, index)); - - int xlimit = Math.Min(x + tileWidth, sourceWidth); - for (int dy = y; dy < endY; dy++) - { - int dyOffset = dy * sourceWidth; - for (int dx = x; dx < xlimit; dx++) - { - int luminace = GetLuminance(Unsafe.Add(ref sourceBase, dyOffset + dx), luminanceLevels); - histogram[luminace]++; - } - } - - if (processor.ClipHistogramEnabled) - { - processor.ClipHistogram(histogram, processor.ClipLimitPercentage, this.pixelsInTile); - } - - Unsafe.Add(ref cdfMinBase, cdfX) = processor.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); - - cdfX++; - } - } - }); - } - - [MethodImpl(InliningOptions.ShortMethod)] - public Span GetCdfLutSpan(int tileX, int tileY) => this.cdfLutBuffer2D.GetRowSpan(tileY).Slice(tileX * this.luminanceLevels, this.luminanceLevels); - - /// - /// Remaps the grey value with the cdf. - /// - /// The tiles x-position. - /// The tiles y-position. - /// The original luminance. - /// The remapped luminance. - [MethodImpl(InliningOptions.ShortMethod)] - public float RemapGreyValue(int tilesX, int tilesY, int luminance) - { - int cdfMin = this.cdfMinBuffer2D[tilesX, tilesY]; - Span cdfSpan = this.GetCdfLutSpan(tilesX, tilesY); - return (this.pixelsInTile - cdfMin) == 0 - ? cdfSpan[luminance] / this.pixelsInTile - : cdfSpan[luminance] / (float)(this.pixelsInTile - cdfMin); - } - - public void Dispose() - { - this.cdfMinBuffer2D.Dispose(); - this.cdfLutBuffer2D.Dispose(); - } + return new AdaptiveHistEqualizationProcessor(this.LuminanceLevels, this.ClipHistogram, this.ClipLimitPercentage, this.NumberOfTiles); } } } diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor{TPixel}.cs new file mode 100644 index 000000000..930c4010f --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor{TPixel}.cs @@ -0,0 +1,546 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Normalization +{ + /// + /// Applies an adaptive histogram equalization to the image. The image is split up in tiles. For each tile a cumulative distribution function (cdf) is calculated. + /// To calculate the final equalized pixel value, the cdf value of four adjacent tiles will be interpolated. + /// + /// The pixel format. + internal class AdaptiveHistEqualizationProcessor : HistogramEqualizationProcessor + where TPixel : struct, IPixel + { + /// + /// Initializes a new instance of the class. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// Indicating whether to clip the histogram bins at a specific value. + /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. + /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. + public AdaptiveHistEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int tiles) + : base(luminanceLevels, clipHistogram, clipLimitPercentage) + { + Guard.MustBeGreaterThanOrEqualTo(tiles, 2, nameof(tiles)); + Guard.MustBeLessThanOrEqualTo(tiles, 100, nameof(tiles)); + + this.Tiles = tiles; + } + + /// + /// Gets the number of tiles the image is split into (horizontal and vertically) for the adaptive histogram equalization. + /// + private int Tiles { get; } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + int sourceWidth = source.Width; + int sourceHeight = source.Height; + int numberOfPixels = sourceWidth * sourceHeight; + int tileWidth = (int)MathF.Ceiling(sourceWidth / (float)this.Tiles); + int tileHeight = (int)MathF.Ceiling(sourceHeight / (float)this.Tiles); + int pixelsInTile = tileWidth * tileHeight; + int halfTileWidth = tileWidth / 2; + int halfTileHeight = tileHeight / 2; + int luminanceLevels = this.LuminanceLevels; + + // The image is split up into tiles. For each tile the cumulative distribution function will be calculated. + using (var cdfData = new CdfTileData(configuration, sourceWidth, sourceHeight, this.Tiles, this.Tiles, tileWidth, tileHeight, luminanceLevels)) + { + cdfData.CalculateLookupTables(source, this); + + var tileYStartPositions = new List<(int y, int cdfY)>(); + int cdfY = 0; + for (int y = halfTileHeight; y < sourceHeight - halfTileHeight; y += tileHeight) + { + tileYStartPositions.Add((y, cdfY)); + cdfY++; + } + + Parallel.For( + 0, + tileYStartPositions.Count, + new ParallelOptions() { MaxDegreeOfParallelism = configuration.MaxDegreeOfParallelism }, + index => + { + int cdfX = 0; + int tileX = 0; + int tileY = 0; + int y = tileYStartPositions[index].y; + int cdfYY = tileYStartPositions[index].cdfY; + + // It's unfortunate that we have to do this per iteration. + ref TPixel sourceBase = ref source.GetPixelReference(0, 0); + + cdfX = 0; + for (int x = halfTileWidth; x < sourceWidth - halfTileWidth; x += tileWidth) + { + tileY = 0; + int yEnd = Math.Min(y + tileHeight, sourceHeight); + int xEnd = Math.Min(x + tileWidth, sourceWidth); + for (int dy = y; dy < yEnd; dy++) + { + int dyOffSet = dy * sourceWidth; + tileX = 0; + for (int dx = x; dx < xEnd; dx++) + { + ref TPixel pixel = ref Unsafe.Add(ref sourceBase, dyOffSet + dx); + float luminanceEqualized = InterpolateBetweenFourTiles( + pixel, + cdfData, + this.Tiles, + this.Tiles, + tileX, + tileY, + cdfX, + cdfYY, + tileWidth, + tileHeight, + luminanceLevels); + + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + tileX++; + } + + tileY++; + } + + cdfX++; + } + }); + + ref TPixel pixelsBase = ref source.GetPixelReference(0, 0); + + // Fix left column + ProcessBorderColumn(ref pixelsBase, cdfData, 0, sourceWidth, sourceHeight, tileWidth, tileHeight, xStart: 0, xEnd: halfTileWidth, luminanceLevels); + + // Fix right column + int rightBorderStartX = ((this.Tiles - 1) * tileWidth) + halfTileWidth; + ProcessBorderColumn(ref pixelsBase, cdfData, this.Tiles - 1, sourceWidth, sourceHeight, tileWidth, tileHeight, xStart: rightBorderStartX, xEnd: sourceWidth, luminanceLevels); + + // Fix top row + ProcessBorderRow(ref pixelsBase, cdfData, 0, sourceWidth, tileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + + // Fix bottom row + int bottomBorderStartY = ((this.Tiles - 1) * tileHeight) + halfTileHeight; + ProcessBorderRow(ref pixelsBase, cdfData, this.Tiles - 1, sourceWidth, tileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + + // Left top corner + ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, 0, 0, xStart: 0, xEnd: halfTileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + + // Left bottom corner + ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, 0, this.Tiles - 1, xStart: 0, xEnd: halfTileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + + // Right top corner + ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, this.Tiles - 1, 0, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + + // Right bottom corner + ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, this.Tiles - 1, this.Tiles - 1, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + } + } + + /// + /// Processes the part of a corner tile which was previously left out. It consists of 1 / 4 of a tile and does not need interpolation. + /// + /// The output pixels base reference. + /// The lookup table to remap the grey values. + /// The source image width. + /// The x-position in the CDF lookup map. + /// The y-position in the CDF lookup map. + /// X start position. + /// X end position. + /// Y start position. + /// Y end position. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + private static void ProcessCornerTile( + ref TPixel pixelsBase, + CdfTileData cdfData, + int sourceWidth, + int cdfX, + int cdfY, + int xStart, + int xEnd, + int yStart, + int yEnd, + int luminanceLevels) + { + for (int dy = yStart; dy < yEnd; dy++) + { + int dyOffSet = dy * sourceWidth; + for (int dx = xStart; dx < xEnd; dx++) + { + ref TPixel pixel = ref Unsafe.Add(ref pixelsBase, dyOffSet + dx); + float luminanceEqualized = cdfData.RemapGreyValue(cdfX, cdfY, GetLuminance(pixel, luminanceLevels)); + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + } + } + } + + /// + /// Processes a border column of the image which is half the size of the tile width. + /// + /// The output pixels reference. + /// The pre-computed lookup tables to remap the grey values for each tiles. + /// The X index of the lookup table to use. + /// The source image width. + /// The source image height. + /// The width of a tile. + /// The height of a tile. + /// X start position in the image. + /// X end position of the image. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + private static void ProcessBorderColumn( + ref TPixel pixelBase, + CdfTileData cdfData, + int cdfX, + int sourceWidth, + int sourceHeight, + int tileWidth, + int tileHeight, + int xStart, + int xEnd, + int luminanceLevels) + { + int halfTileWidth = tileWidth / 2; + int halfTileHeight = tileHeight / 2; + + int cdfY = 0; + for (int y = halfTileHeight; y < sourceHeight - halfTileHeight; y += tileHeight) + { + int yLimit = Math.Min(y + tileHeight, sourceHeight - 1); + int tileY = 0; + for (int dy = y; dy < yLimit; dy++) + { + int dyOffSet = dy * sourceWidth; + int tileX = halfTileWidth; + for (int dx = xStart; dx < xEnd; dx++) + { + ref TPixel pixel = ref Unsafe.Add(ref pixelBase, dyOffSet + dx); + float luminanceEqualized = InterpolateBetweenTwoTiles(pixel, cdfData, cdfX, cdfY, cdfX, cdfY + 1, tileY, tileHeight, luminanceLevels); + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + tileX++; + } + + tileY++; + } + + cdfY++; + } + } + + /// + /// Processes a border row of the image which is half of the size of the tile height. + /// + /// The output pixels base reference. + /// The pre-computed lookup tables to remap the grey values for each tiles. + /// The Y index of the lookup table to use. + /// The source image width. + /// The width of a tile. + /// Y start position in the image. + /// Y end position of the image. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + private static void ProcessBorderRow( + ref TPixel pixelBase, + CdfTileData cdfData, + int cdfY, + int sourceWidth, + int tileWidth, + int yStart, + int yEnd, + int luminanceLevels) + { + int halfTileWidth = tileWidth / 2; + + int cdfX = 0; + for (int x = halfTileWidth; x < sourceWidth - halfTileWidth; x += tileWidth) + { + int tileY = 0; + for (int dy = yStart; dy < yEnd; dy++) + { + int dyOffSet = dy * sourceWidth; + int tileX = 0; + int xLimit = Math.Min(x + tileWidth, sourceWidth - 1); + for (int dx = x; dx < xLimit; dx++) + { + ref TPixel pixel = ref Unsafe.Add(ref pixelBase, dyOffSet + dx); + float luminanceEqualized = InterpolateBetweenTwoTiles(pixel, cdfData, cdfX, cdfY, cdfX + 1, cdfY, tileX, tileWidth, luminanceLevels); + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + tileX++; + } + + tileY++; + } + + cdfX++; + } + } + + /// + /// Bilinear interpolation between four adjacent tiles. + /// + /// The pixel to remap the grey value from. + /// The pre-computed lookup tables to remap the grey values for each tiles. + /// The number of tiles in the x-direction. + /// The number of tiles in the y-direction. + /// X position inside the tile. + /// Y position inside the tile. + /// X index of the top left lookup table to use. + /// Y index of the top left lookup table to use. + /// Width of one tile in pixels. + /// Height of one tile in pixels. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + /// A re-mapped grey value. + [MethodImpl(InliningOptions.ShortMethod)] + private static float InterpolateBetweenFourTiles( + TPixel sourcePixel, + CdfTileData cdfData, + int tileCountX, + int tileCountY, + int tileX, + int tileY, + int cdfX, + int cdfY, + int tileWidth, + int tileHeight, + int luminanceLevels) + { + int luminance = GetLuminance(sourcePixel, luminanceLevels); + float tx = tileX / (float)(tileWidth - 1); + float ty = tileY / (float)(tileHeight - 1); + + int yTop = cdfY; + int yBottom = Math.Min(tileCountY - 1, yTop + 1); + int xLeft = cdfX; + int xRight = Math.Min(tileCountX - 1, xLeft + 1); + + float cdfLeftTopLuminance = cdfData.RemapGreyValue(xLeft, yTop, luminance); + float cdfRightTopLuminance = cdfData.RemapGreyValue(xRight, yTop, luminance); + float cdfLeftBottomLuminance = cdfData.RemapGreyValue(xLeft, yBottom, luminance); + float cdfRightBottomLuminance = cdfData.RemapGreyValue(xRight, yBottom, luminance); + return BilinearInterpolation(tx, ty, cdfLeftTopLuminance, cdfRightTopLuminance, cdfLeftBottomLuminance, cdfRightBottomLuminance); + } + + /// + /// Linear interpolation between two tiles. + /// + /// The pixel to remap the grey value from. + /// The CDF lookup map. + /// X position inside the first tile. + /// Y position inside the first tile. + /// X position inside the second tile. + /// Y position inside the second tile. + /// Position inside the tile. + /// Width of the tile. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + /// A re-mapped grey value. + [MethodImpl(InliningOptions.ShortMethod)] + private static float InterpolateBetweenTwoTiles( + TPixel sourcePixel, + CdfTileData cdfData, + int tileX1, + int tileY1, + int tileX2, + int tileY2, + int tilePos, + int tileWidth, + int luminanceLevels) + { + int luminance = GetLuminance(sourcePixel, luminanceLevels); + float tx = tilePos / (float)(tileWidth - 1); + + float cdfLuminance1 = cdfData.RemapGreyValue(tileX1, tileY1, luminance); + float cdfLuminance2 = cdfData.RemapGreyValue(tileX2, tileY2, luminance); + return LinearInterpolation(cdfLuminance1, cdfLuminance2, tx); + } + + /// + /// Bilinear interpolation between four tiles. + /// + /// The interpolation value in x direction in the range of [0, 1]. + /// The interpolation value in y direction in the range of [0, 1]. + /// Luminance from top left tile. + /// Luminance from right top tile. + /// Luminance from left bottom tile. + /// Luminance from right bottom tile. + /// Interpolated Luminance. + [MethodImpl(InliningOptions.ShortMethod)] + private static float BilinearInterpolation(float tx, float ty, float lt, float rt, float lb, float rb) + => LinearInterpolation(LinearInterpolation(lt, rt, tx), LinearInterpolation(lb, rb, tx), ty); + + /// + /// Linear interpolation between two grey values. + /// + /// The left value. + /// The right value. + /// The interpolation value between the two values in the range of [0, 1]. + /// The interpolated value. + [MethodImpl(InliningOptions.ShortMethod)] + private static float LinearInterpolation(float left, float right, float t) + => left + ((right - left) * t); + + /// + /// Contains the results of the cumulative distribution function for all tiles. + /// + private sealed class CdfTileData : IDisposable + { + private readonly Configuration configuration; + private readonly MemoryAllocator memoryAllocator; + + // Used for storing the minimum value for each CDF entry. + private readonly Buffer2D cdfMinBuffer2D; + + // Used for storing the LUT for each CDF entry. + private readonly Buffer2D cdfLutBuffer2D; + private readonly int pixelsInTile; + private readonly int sourceWidth; + private readonly int sourceHeight; + private readonly int tileWidth; + private readonly int tileHeight; + private readonly int luminanceLevels; + private readonly List<(int y, int cdfY)> tileYStartPositions; + + public CdfTileData( + Configuration configuration, + int sourceWidth, + int sourceHeight, + int tileCountX, + int tileCountY, + int tileWidth, + int tileHeight, + int luminanceLevels) + { + this.configuration = configuration; + this.memoryAllocator = configuration.MemoryAllocator; + this.luminanceLevels = luminanceLevels; + this.cdfMinBuffer2D = this.memoryAllocator.Allocate2D(tileCountX, tileCountY); + this.cdfLutBuffer2D = this.memoryAllocator.Allocate2D(tileCountX * luminanceLevels, tileCountY); + this.sourceWidth = sourceWidth; + this.sourceHeight = sourceHeight; + this.tileWidth = tileWidth; + this.tileHeight = tileHeight; + this.pixelsInTile = tileWidth * tileHeight; + + // Calculate the start positions and rent buffers. + this.tileYStartPositions = new List<(int y, int cdfY)>(); + int cdfY = 0; + for (int y = 0; y < sourceHeight; y += tileHeight) + { + this.tileYStartPositions.Add((y, cdfY)); + cdfY++; + } + } + + public void CalculateLookupTables(ImageFrame source, HistogramEqualizationProcessor processor) + { + int sourceWidth = this.sourceWidth; + int sourceHeight = this.sourceHeight; + int tileWidth = this.tileWidth; + int tileHeight = this.tileHeight; + int luminanceLevels = this.luminanceLevels; + MemoryAllocator memoryAllocator = this.memoryAllocator; + + Parallel.For( + 0, + this.tileYStartPositions.Count, + new ParallelOptions() { MaxDegreeOfParallelism = this.configuration.MaxDegreeOfParallelism }, + index => + { + int cdfX = 0; + int cdfY = this.tileYStartPositions[index].cdfY; + int y = this.tileYStartPositions[index].y; + int endY = Math.Min(y + tileHeight, sourceHeight); + ref TPixel sourceBase = ref source.GetPixelReference(0, 0); + ref int cdfMinBase = ref MemoryMarshal.GetReference(this.cdfMinBuffer2D.GetRowSpan(cdfY)); + + using (IMemoryOwner histogramBuffer = this.memoryAllocator.Allocate(luminanceLevels)) + { + Span histogram = histogramBuffer.GetSpan(); + ref int histogramBase = ref MemoryMarshal.GetReference(histogram); + + for (int x = 0; x < sourceWidth; x += tileWidth) + { + histogram.Clear(); + ref int cdfBase = ref MemoryMarshal.GetReference(this.GetCdfLutSpan(cdfX, index)); + + int xlimit = Math.Min(x + tileWidth, sourceWidth); + for (int dy = y; dy < endY; dy++) + { + int dyOffset = dy * sourceWidth; + for (int dx = x; dx < xlimit; dx++) + { + int luminace = GetLuminance(Unsafe.Add(ref sourceBase, dyOffset + dx), luminanceLevels); + histogram[luminace]++; + } + } + + if (processor.ClipHistogramEnabled) + { + processor.ClipHistogram(histogram, processor.ClipLimitPercentage, this.pixelsInTile); + } + + Unsafe.Add(ref cdfMinBase, cdfX) = processor.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); + + cdfX++; + } + } + }); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public Span GetCdfLutSpan(int tileX, int tileY) => this.cdfLutBuffer2D.GetRowSpan(tileY).Slice(tileX * this.luminanceLevels, this.luminanceLevels); + + /// + /// Remaps the grey value with the cdf. + /// + /// The tiles x-position. + /// The tiles y-position. + /// The original luminance. + /// The remapped luminance. + [MethodImpl(InliningOptions.ShortMethod)] + public float RemapGreyValue(int tilesX, int tilesY, int luminance) + { + int cdfMin = this.cdfMinBuffer2D[tilesX, tilesY]; + Span cdfSpan = this.GetCdfLutSpan(tilesX, tilesY); + return (this.pixelsInTile - cdfMin) == 0 + ? cdfSpan[luminance] / this.pixelsInTile + : cdfSpan[luminance] / (float)(this.pixelsInTile - cdfMin); + } + + public void Dispose() + { + this.cdfMinBuffer2D.Dispose(); + this.cdfLutBuffer2D.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs index aa9b530c6..cd4a9644f 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs @@ -1,389 +1,36 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; -using SixLabors.Primitives; - namespace SixLabors.ImageSharp.Processing.Processors.Normalization { /// /// Applies an adaptive histogram equalization to the image using an sliding window approach. /// - /// The pixel format. - internal class AdaptiveHistEqualizationSWProcessor : HistogramEqualizationProcessor - where TPixel : struct, IPixel + internal class AdaptiveHistEqualizationSWProcessor : HistogramEqualizationProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images /// or 65536 for 16-bit grayscale images. /// Indicating whether to clip the histogram bins at a specific value. /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. - /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. - public AdaptiveHistEqualizationSWProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int tiles) + /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. + public AdaptiveHistEqualizationSWProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int numberOfTiles) : base(luminanceLevels, clipHistogram, clipLimitPercentage) { - Guard.MustBeGreaterThanOrEqualTo(tiles, 2, nameof(tiles)); - Guard.MustBeLessThanOrEqualTo(tiles, 100, nameof(tiles)); - - this.Tiles = tiles; + this.NumberOfTiles = numberOfTiles; } /// /// Gets the number of tiles the image is split into (horizontal and vertically) for the adaptive histogram equalization. /// - private int Tiles { get; } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - MemoryAllocator memoryAllocator = configuration.MemoryAllocator; - int numberOfPixels = source.Width * source.Height; - Span pixels = source.GetPixelSpan(); - - var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = configuration.MaxDegreeOfParallelism }; - int tileWidth = source.Width / this.Tiles; - int tileHeight = tileWidth; - int pixeInTile = tileWidth * tileHeight; - int halfTileHeight = tileHeight / 2; - int halfTileWidth = halfTileHeight; - var slidingWindowInfos = new SlidingWindowInfos(tileWidth, tileHeight, halfTileWidth, halfTileHeight, pixeInTile); - - using (Buffer2D targetPixels = configuration.MemoryAllocator.Allocate2D(source.Width, source.Height)) - { - // Process the inner tiles, which do not require to check the borders. - Parallel.For( - halfTileWidth, - source.Width - halfTileWidth, - parallelOptions, - this.ProcessSlidingWindow( - source, - memoryAllocator, - targetPixels, - slidingWindowInfos, - yStart: halfTileHeight, - yEnd: source.Height - halfTileHeight, - useFastPath: true, - configuration)); - - // Process the left border of the image. - Parallel.For( - 0, - halfTileWidth, - parallelOptions, - this.ProcessSlidingWindow( - source, - memoryAllocator, - targetPixels, - slidingWindowInfos, - yStart: 0, - yEnd: source.Height, - useFastPath: false, - configuration)); - - // Process the right border of the image. - Parallel.For( - source.Width - halfTileWidth, - source.Width, - parallelOptions, - this.ProcessSlidingWindow( - source, - memoryAllocator, - targetPixels, - slidingWindowInfos, - yStart: 0, - yEnd: source.Height, - useFastPath: false, - configuration)); - - // Process the top border of the image. - Parallel.For( - halfTileWidth, - source.Width - halfTileWidth, - parallelOptions, - this.ProcessSlidingWindow( - source, - memoryAllocator, - targetPixels, - slidingWindowInfos, - yStart: 0, - yEnd: halfTileHeight, - useFastPath: false, - configuration)); - - // Process the bottom border of the image. - Parallel.For( - halfTileWidth, - source.Width - halfTileWidth, - parallelOptions, - this.ProcessSlidingWindow( - source, - memoryAllocator, - targetPixels, - slidingWindowInfos, - yStart: source.Height - halfTileHeight, - yEnd: source.Height, - useFastPath: false, - configuration)); - - Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); - } - } - - /// - /// Applies the sliding window equalization to one column of the image. The window is moved from top to bottom. - /// Moving the window one pixel down requires to remove one row from the top of the window from the histogram and - /// adding a new row at the bottom. - /// - /// The source image. - /// The memory allocator. - /// The target pixels. - /// Informations about the sliding window dimensions. - /// The y start position. - /// The y end position. - /// if set to true the borders of the image will not be checked. - /// The configuration. - /// Action Delegate. - private Action ProcessSlidingWindow( - ImageFrame source, - MemoryAllocator memoryAllocator, - Buffer2D targetPixels, - SlidingWindowInfos swInfos, - int yStart, - int yEnd, - bool useFastPath, - Configuration configuration) - { - return x => - { - using (IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) - using (IMemoryOwner histogramBufferCopy = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) - using (IMemoryOwner cdfBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) - using (IMemoryOwner pixelRowBuffer = memoryAllocator.Allocate(swInfos.TileWidth, AllocationOptions.Clean)) - { - Span histogram = histogramBuffer.GetSpan(); - ref int histogramBase = ref MemoryMarshal.GetReference(histogram); - - Span histogramCopy = histogramBufferCopy.GetSpan(); - ref int histogramCopyBase = ref MemoryMarshal.GetReference(histogramCopy); - - ref int cdfBase = ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()); - - Span pixelRow = pixelRowBuffer.GetSpan(); - ref Vector4 pixelRowBase = ref MemoryMarshal.GetReference(pixelRow); - - // Build the initial histogram of grayscale values. - for (int dy = yStart - swInfos.HalfTileHeight; dy < yStart + swInfos.HalfTileHeight; dy++) - { - if (useFastPath) - { - this.CopyPixelRowFast(source, pixelRow, x - swInfos.HalfTileWidth, dy, swInfos.TileWidth, configuration); - } - else - { - this.CopyPixelRow(source, pixelRow, x - swInfos.HalfTileWidth, dy, swInfos.TileWidth, configuration); - } - - this.AddPixelsToHistogram(ref pixelRowBase, ref histogramBase, this.LuminanceLevels, pixelRow.Length); - } - - for (int y = yStart; y < yEnd; y++) - { - if (this.ClipHistogramEnabled) - { - // Clipping the histogram, but doing it on a copy to keep the original un-clipped values for the next iteration. - histogram.CopyTo(histogramCopy); - this.ClipHistogram(histogramCopy, this.ClipLimitPercentage, swInfos.PixeInTile); - } - - // Calculate the cumulative distribution function, which will map each input pixel in the current tile to a new value. - int cdfMin = this.ClipHistogramEnabled - ? this.CalculateCdf(ref cdfBase, ref histogramCopyBase, histogram.Length - 1) - : this.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); - - float numberOfPixelsMinusCdfMin = swInfos.PixeInTile - cdfMin; - - // Map the current pixel to the new equalized value. - int luminance = GetLuminance(source[x, y], this.LuminanceLevels); - float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / numberOfPixelsMinusCdfMin; - targetPixels[x, y].FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, source[x, y].ToVector4().W)); - - // Remove top most row from the histogram, mirroring rows which exceeds the borders. - if (useFastPath) - { - this.CopyPixelRowFast(source, pixelRow, x - swInfos.HalfTileWidth, y - swInfos.HalfTileWidth, swInfos.TileWidth, configuration); - } - else - { - this.CopyPixelRow(source, pixelRow, x - swInfos.HalfTileWidth, y - swInfos.HalfTileWidth, swInfos.TileWidth, configuration); - } - - this.RemovePixelsFromHistogram(ref pixelRowBase, ref histogramBase, this.LuminanceLevels, pixelRow.Length); - - // Add new bottom row to the histogram, mirroring rows which exceeds the borders. - if (useFastPath) - { - this.CopyPixelRowFast(source, pixelRow, x - swInfos.HalfTileWidth, y + swInfos.HalfTileWidth, swInfos.TileWidth, configuration); - } - else - { - this.CopyPixelRow(source, pixelRow, x - swInfos.HalfTileWidth, y + swInfos.HalfTileWidth, swInfos.TileWidth, configuration); - } - - this.AddPixelsToHistogram(ref pixelRowBase, ref histogramBase, this.LuminanceLevels, pixelRow.Length); - } - } - }; - } - - /// - /// Get the a pixel row at a given position with a length of the tile width. Mirrors pixels which exceeds the edges. - /// - /// The source image. - /// Pre-allocated pixel row span of the size of a the tile width. - /// The x position. - /// The y position. - /// The width in pixels of a tile. - /// The configuration. - private void CopyPixelRow( - ImageFrame source, - Span rowPixels, - int x, - int y, - int tileWidth, - Configuration configuration) - { - if (y < 0) - { - y = ImageMaths.FastAbs(y); - } - else if (y >= source.Height) - { - int diff = y - source.Height; - y = source.Height - diff - 1; - } - - // Special cases for the left and the right border where GetPixelRowSpan can not be used. - if (x < 0) - { - rowPixels.Clear(); - int idx = 0; - for (int dx = x; dx < x + tileWidth; dx++) - { - rowPixels[idx] = source[ImageMaths.FastAbs(dx), y].ToVector4(); - idx++; - } - - return; - } - else if (x + tileWidth > source.Width) - { - rowPixels.Clear(); - int idx = 0; - for (int dx = x; dx < x + tileWidth; dx++) - { - if (dx >= source.Width) - { - int diff = dx - source.Width; - rowPixels[idx] = source[dx - diff - 1, y].ToVector4(); - } - else - { - rowPixels[idx] = source[dx, y].ToVector4(); - } - - idx++; - } + public int NumberOfTiles { get; } - return; - } - - this.CopyPixelRowFast(source, rowPixels, x, y, tileWidth, configuration); - } - - /// - /// Get the a pixel row at a given position with a length of the tile width. - /// - /// The source image. - /// Pre-allocated pixel row span of the size of a the tile width. - /// The x position. - /// The y position. - /// The width in pixels of a tile. - /// The configuration. - [MethodImpl(InliningOptions.ShortMethod)] - private void CopyPixelRowFast( - ImageFrame source, - Span rowPixels, - int x, - int y, - int tileWidth, - Configuration configuration) - => PixelOperations.Instance.ToVector4(configuration, source.GetPixelRowSpan(y).Slice(start: x, length: tileWidth), rowPixels); - - /// - /// Adds a column of grey values to the histogram. - /// - /// The reference to the span of grey values to add. - /// The reference to the histogram span. - /// The number of different luminance levels. - /// The grey values span length. - [MethodImpl(InliningOptions.ShortMethod)] - private void AddPixelsToHistogram(ref Vector4 greyValuesBase, ref int histogramBase, int luminanceLevels, int length) - { - for (int idx = 0; idx < length; idx++) - { - int luminance = GetLuminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels); - Unsafe.Add(ref histogramBase, luminance)++; - } - } - - /// - /// Removes a column of grey values from the histogram. - /// - /// The reference to the span of grey values to remove. - /// The reference to the histogram span. - /// The number of different luminance levels. - /// The grey values span length. - [MethodImpl(InliningOptions.ShortMethod)] - private void RemovePixelsFromHistogram(ref Vector4 greyValuesBase, ref int histogramBase, int luminanceLevels, int length) - { - for (int idx = 0; idx < length; idx++) - { - int luminance = GetLuminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels); - Unsafe.Add(ref histogramBase, luminance)--; - } - } - - private class SlidingWindowInfos + /// + public override IImageProcessor CreatePixelSpecificProcessor() { - public SlidingWindowInfos(int tileWidth, int tileHeight, int halfTileWidth, int halfTileHeight, int pixeInTile) - { - this.TileWidth = tileWidth; - this.TileHeight = tileHeight; - this.HalfTileWidth = halfTileWidth; - this.HalfTileHeight = halfTileHeight; - this.PixeInTile = pixeInTile; - } - - public int TileWidth { get; private set; } - - public int TileHeight { get; private set; } - - public int PixeInTile { get; private set; } - - public int HalfTileWidth { get; private set; } - - public int HalfTileHeight { get; private set; } + return new AdaptiveHistEqualizationSWProcessor(this.LuminanceLevels, this.ClipHistogram, this.ClipLimitPercentage, this.NumberOfTiles); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor{TPixel}.cs new file mode 100644 index 000000000..3584b1a88 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor{TPixel}.cs @@ -0,0 +1,390 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Normalization +{ + /// + /// Applies an adaptive histogram equalization to the image using an sliding window approach. + /// + /// The pixel format. + internal class AdaptiveHistEqualizationSWProcessor : HistogramEqualizationProcessor + where TPixel : struct, IPixel + { + /// + /// Initializes a new instance of the class. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// Indicating whether to clip the histogram bins at a specific value. + /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. + /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. + public AdaptiveHistEqualizationSWProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int tiles) + : base(luminanceLevels, clipHistogram, clipLimitPercentage) + { + Guard.MustBeGreaterThanOrEqualTo(tiles, 2, nameof(tiles)); + Guard.MustBeLessThanOrEqualTo(tiles, 100, nameof(tiles)); + + this.Tiles = tiles; + } + + /// + /// Gets the number of tiles the image is split into (horizontal and vertically) for the adaptive histogram equalization. + /// + private int Tiles { get; } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + MemoryAllocator memoryAllocator = configuration.MemoryAllocator; + int numberOfPixels = source.Width * source.Height; + Span pixels = source.GetPixelSpan(); + + var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = configuration.MaxDegreeOfParallelism }; + int tileWidth = source.Width / this.Tiles; + int tileHeight = tileWidth; + int pixeInTile = tileWidth * tileHeight; + int halfTileHeight = tileHeight / 2; + int halfTileWidth = halfTileHeight; + var slidingWindowInfos = new SlidingWindowInfos(tileWidth, tileHeight, halfTileWidth, halfTileHeight, pixeInTile); + + using (Buffer2D targetPixels = configuration.MemoryAllocator.Allocate2D(source.Width, source.Height)) + { + // Process the inner tiles, which do not require to check the borders. + Parallel.For( + halfTileWidth, + source.Width - halfTileWidth, + parallelOptions, + this.ProcessSlidingWindow( + source, + memoryAllocator, + targetPixels, + slidingWindowInfos, + yStart: halfTileHeight, + yEnd: source.Height - halfTileHeight, + useFastPath: true, + configuration)); + + // Process the left border of the image. + Parallel.For( + 0, + halfTileWidth, + parallelOptions, + this.ProcessSlidingWindow( + source, + memoryAllocator, + targetPixels, + slidingWindowInfos, + yStart: 0, + yEnd: source.Height, + useFastPath: false, + configuration)); + + // Process the right border of the image. + Parallel.For( + source.Width - halfTileWidth, + source.Width, + parallelOptions, + this.ProcessSlidingWindow( + source, + memoryAllocator, + targetPixels, + slidingWindowInfos, + yStart: 0, + yEnd: source.Height, + useFastPath: false, + configuration)); + + // Process the top border of the image. + Parallel.For( + halfTileWidth, + source.Width - halfTileWidth, + parallelOptions, + this.ProcessSlidingWindow( + source, + memoryAllocator, + targetPixels, + slidingWindowInfos, + yStart: 0, + yEnd: halfTileHeight, + useFastPath: false, + configuration)); + + // Process the bottom border of the image. + Parallel.For( + halfTileWidth, + source.Width - halfTileWidth, + parallelOptions, + this.ProcessSlidingWindow( + source, + memoryAllocator, + targetPixels, + slidingWindowInfos, + yStart: source.Height - halfTileHeight, + yEnd: source.Height, + useFastPath: false, + configuration)); + + Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); + } + } + + /// + /// Applies the sliding window equalization to one column of the image. The window is moved from top to bottom. + /// Moving the window one pixel down requires to remove one row from the top of the window from the histogram and + /// adding a new row at the bottom. + /// + /// The source image. + /// The memory allocator. + /// The target pixels. + /// Informations about the sliding window dimensions. + /// The y start position. + /// The y end position. + /// if set to true the borders of the image will not be checked. + /// The configuration. + /// Action Delegate. + private Action ProcessSlidingWindow( + ImageFrame source, + MemoryAllocator memoryAllocator, + Buffer2D targetPixels, + SlidingWindowInfos swInfos, + int yStart, + int yEnd, + bool useFastPath, + Configuration configuration) + { + return x => + { + using (IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + using (IMemoryOwner histogramBufferCopy = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + using (IMemoryOwner cdfBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + using (IMemoryOwner pixelRowBuffer = memoryAllocator.Allocate(swInfos.TileWidth, AllocationOptions.Clean)) + { + Span histogram = histogramBuffer.GetSpan(); + ref int histogramBase = ref MemoryMarshal.GetReference(histogram); + + Span histogramCopy = histogramBufferCopy.GetSpan(); + ref int histogramCopyBase = ref MemoryMarshal.GetReference(histogramCopy); + + ref int cdfBase = ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()); + + Span pixelRow = pixelRowBuffer.GetSpan(); + ref Vector4 pixelRowBase = ref MemoryMarshal.GetReference(pixelRow); + + // Build the initial histogram of grayscale values. + for (int dy = yStart - swInfos.HalfTileHeight; dy < yStart + swInfos.HalfTileHeight; dy++) + { + if (useFastPath) + { + this.CopyPixelRowFast(source, pixelRow, x - swInfos.HalfTileWidth, dy, swInfos.TileWidth, configuration); + } + else + { + this.CopyPixelRow(source, pixelRow, x - swInfos.HalfTileWidth, dy, swInfos.TileWidth, configuration); + } + + this.AddPixelsToHistogram(ref pixelRowBase, ref histogramBase, this.LuminanceLevels, pixelRow.Length); + } + + for (int y = yStart; y < yEnd; y++) + { + if (this.ClipHistogramEnabled) + { + // Clipping the histogram, but doing it on a copy to keep the original un-clipped values for the next iteration. + histogram.CopyTo(histogramCopy); + this.ClipHistogram(histogramCopy, this.ClipLimitPercentage, swInfos.PixeInTile); + } + + // Calculate the cumulative distribution function, which will map each input pixel in the current tile to a new value. + int cdfMin = this.ClipHistogramEnabled + ? this.CalculateCdf(ref cdfBase, ref histogramCopyBase, histogram.Length - 1) + : this.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); + + float numberOfPixelsMinusCdfMin = swInfos.PixeInTile - cdfMin; + + // Map the current pixel to the new equalized value. + int luminance = GetLuminance(source[x, y], this.LuminanceLevels); + float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / numberOfPixelsMinusCdfMin; + targetPixels[x, y].FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, source[x, y].ToVector4().W)); + + // Remove top most row from the histogram, mirroring rows which exceeds the borders. + if (useFastPath) + { + this.CopyPixelRowFast(source, pixelRow, x - swInfos.HalfTileWidth, y - swInfos.HalfTileWidth, swInfos.TileWidth, configuration); + } + else + { + this.CopyPixelRow(source, pixelRow, x - swInfos.HalfTileWidth, y - swInfos.HalfTileWidth, swInfos.TileWidth, configuration); + } + + this.RemovePixelsFromHistogram(ref pixelRowBase, ref histogramBase, this.LuminanceLevels, pixelRow.Length); + + // Add new bottom row to the histogram, mirroring rows which exceeds the borders. + if (useFastPath) + { + this.CopyPixelRowFast(source, pixelRow, x - swInfos.HalfTileWidth, y + swInfos.HalfTileWidth, swInfos.TileWidth, configuration); + } + else + { + this.CopyPixelRow(source, pixelRow, x - swInfos.HalfTileWidth, y + swInfos.HalfTileWidth, swInfos.TileWidth, configuration); + } + + this.AddPixelsToHistogram(ref pixelRowBase, ref histogramBase, this.LuminanceLevels, pixelRow.Length); + } + } + }; + } + + /// + /// Get the a pixel row at a given position with a length of the tile width. Mirrors pixels which exceeds the edges. + /// + /// The source image. + /// Pre-allocated pixel row span of the size of a the tile width. + /// The x position. + /// The y position. + /// The width in pixels of a tile. + /// The configuration. + private void CopyPixelRow( + ImageFrame source, + Span rowPixels, + int x, + int y, + int tileWidth, + Configuration configuration) + { + if (y < 0) + { + y = ImageMaths.FastAbs(y); + } + else if (y >= source.Height) + { + int diff = y - source.Height; + y = source.Height - diff - 1; + } + + // Special cases for the left and the right border where GetPixelRowSpan can not be used. + if (x < 0) + { + rowPixels.Clear(); + int idx = 0; + for (int dx = x; dx < x + tileWidth; dx++) + { + rowPixels[idx] = source[ImageMaths.FastAbs(dx), y].ToVector4(); + idx++; + } + + return; + } + else if (x + tileWidth > source.Width) + { + rowPixels.Clear(); + int idx = 0; + for (int dx = x; dx < x + tileWidth; dx++) + { + if (dx >= source.Width) + { + int diff = dx - source.Width; + rowPixels[idx] = source[dx - diff - 1, y].ToVector4(); + } + else + { + rowPixels[idx] = source[dx, y].ToVector4(); + } + + idx++; + } + + return; + } + + this.CopyPixelRowFast(source, rowPixels, x, y, tileWidth, configuration); + } + + /// + /// Get the a pixel row at a given position with a length of the tile width. + /// + /// The source image. + /// Pre-allocated pixel row span of the size of a the tile width. + /// The x position. + /// The y position. + /// The width in pixels of a tile. + /// The configuration. + [MethodImpl(InliningOptions.ShortMethod)] + private void CopyPixelRowFast( + ImageFrame source, + Span rowPixels, + int x, + int y, + int tileWidth, + Configuration configuration) + => PixelOperations.Instance.ToVector4(configuration, source.GetPixelRowSpan(y).Slice(start: x, length: tileWidth), rowPixels); + + /// + /// Adds a column of grey values to the histogram. + /// + /// The reference to the span of grey values to add. + /// The reference to the histogram span. + /// The number of different luminance levels. + /// The grey values span length. + [MethodImpl(InliningOptions.ShortMethod)] + private void AddPixelsToHistogram(ref Vector4 greyValuesBase, ref int histogramBase, int luminanceLevels, int length) + { + for (int idx = 0; idx < length; idx++) + { + int luminance = GetLuminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels); + Unsafe.Add(ref histogramBase, luminance)++; + } + } + + /// + /// Removes a column of grey values from the histogram. + /// + /// The reference to the span of grey values to remove. + /// The reference to the histogram span. + /// The number of different luminance levels. + /// The grey values span length. + [MethodImpl(InliningOptions.ShortMethod)] + private void RemovePixelsFromHistogram(ref Vector4 greyValuesBase, ref int histogramBase, int luminanceLevels, int length) + { + for (int idx = 0; idx < length; idx++) + { + int luminance = GetLuminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels); + Unsafe.Add(ref histogramBase, luminance)--; + } + } + + private class SlidingWindowInfos + { + public SlidingWindowInfos(int tileWidth, int tileHeight, int halfTileWidth, int halfTileHeight, int pixeInTile) + { + this.TileWidth = tileWidth; + this.TileHeight = tileHeight; + this.HalfTileWidth = halfTileWidth; + this.HalfTileHeight = halfTileHeight; + this.PixeInTile = pixeInTile; + } + + public int TileWidth { get; private set; } + + public int TileHeight { get; private set; } + + public int PixeInTile { get; private set; } + + public int HalfTileWidth { get; private set; } + + public int HalfTileHeight { get; private set; } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs index aadde2424..62e018595 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs @@ -1,106 +1,25 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; -using SixLabors.Primitives; - namespace SixLabors.ImageSharp.Processing.Processors.Normalization { /// - /// Applies a global histogram equalization to the image. + /// Defines a global histogram equalization applicable to an . /// - /// The pixel format. - internal class GlobalHistogramEqualizationProcessor : HistogramEqualizationProcessor - where TPixel : struct, IPixel + internal class GlobalHistogramEqualizationProcessor : HistogramEqualizationProcessor { - /// - /// Initializes a new instance of the class. - /// - /// - /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images - /// or 65536 for 16-bit grayscale images. - /// - /// Indicating whether to clip the histogram bins at a specific value. - /// Histogram clip limit in percent of the total pixels. Histogram bins which exceed this limit, will be capped at this value. public GlobalHistogramEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage) : base(luminanceLevels, clipHistogram, clipLimitPercentage) { } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + public override IImageProcessor CreatePixelSpecificProcessor() { - MemoryAllocator memoryAllocator = configuration.MemoryAllocator; - int numberOfPixels = source.Width * source.Height; - Span pixels = source.GetPixelSpan(); - var workingRect = new Rectangle(0, 0, source.Width, source.Height); - - using (IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) - using (IMemoryOwner cdfBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) - { - // Build the histogram of the grayscale levels. - ParallelHelper.IterateRows( - workingRect, - configuration, - rows => - { - ref int histogramBase = ref MemoryMarshal.GetReference(histogramBuffer.GetSpan()); - for (int y = rows.Min; y < rows.Max; y++) - { - ref TPixel pixelBase = ref MemoryMarshal.GetReference(source.GetPixelRowSpan(y)); - - for (int x = 0; x < workingRect.Width; x++) - { - int luminance = GetLuminance(Unsafe.Add(ref pixelBase, x), this.LuminanceLevels); - Unsafe.Add(ref histogramBase, luminance)++; - } - } - }); - - Span histogram = histogramBuffer.GetSpan(); - if (this.ClipHistogramEnabled) - { - this.ClipHistogram(histogram, this.ClipLimitPercentage, numberOfPixels); - } - - // Calculate the cumulative distribution function, which will map each input pixel to a new value. - int cdfMin = this.CalculateCdf( - ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()), - ref MemoryMarshal.GetReference(histogram), - histogram.Length - 1); - - float numberOfPixelsMinusCdfMin = numberOfPixels - cdfMin; - - // Apply the cdf to each pixel of the image - ParallelHelper.IterateRows( - workingRect, - configuration, - rows => - { - ref int cdfBase = ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()); - for (int y = rows.Min; y < rows.Max; y++) - { - ref TPixel pixelBase = ref MemoryMarshal.GetReference(source.GetPixelRowSpan(y)); - - for (int x = 0; x < workingRect.Width; x++) - { - ref TPixel pixel = ref Unsafe.Add(ref pixelBase, x); - int luminance = GetLuminance(pixel, this.LuminanceLevels); - float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / numberOfPixelsMinusCdfMin; - pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); - } - } - }); - } + return new GlobalHistogramEqualizationProcessor( + this.LuminanceLevels, + this.ClipHistogram, + this.ClipLimitPercentage); } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs new file mode 100644 index 000000000..b3a1603e6 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs @@ -0,0 +1,107 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Normalization +{ + /// + /// Applies a global histogram equalization to the image. + /// + /// The pixel format. + internal class GlobalHistogramEqualizationProcessor : HistogramEqualizationProcessor + where TPixel : struct, IPixel + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// + /// Indicating whether to clip the histogram bins at a specific value. + /// Histogram clip limit in percent of the total pixels. Histogram bins which exceed this limit, will be capped at this value. + public GlobalHistogramEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage) + : base(luminanceLevels, clipHistogram, clipLimitPercentage) + { + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + MemoryAllocator memoryAllocator = configuration.MemoryAllocator; + int numberOfPixels = source.Width * source.Height; + Span pixels = source.GetPixelSpan(); + var workingRect = new Rectangle(0, 0, source.Width, source.Height); + + using (IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + using (IMemoryOwner cdfBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) + { + // Build the histogram of the grayscale levels. + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + ref int histogramBase = ref MemoryMarshal.GetReference(histogramBuffer.GetSpan()); + for (int y = rows.Min; y < rows.Max; y++) + { + ref TPixel pixelBase = ref MemoryMarshal.GetReference(source.GetPixelRowSpan(y)); + + for (int x = 0; x < workingRect.Width; x++) + { + int luminance = GetLuminance(Unsafe.Add(ref pixelBase, x), this.LuminanceLevels); + Unsafe.Add(ref histogramBase, luminance)++; + } + } + }); + + Span histogram = histogramBuffer.GetSpan(); + if (this.ClipHistogramEnabled) + { + this.ClipHistogram(histogram, this.ClipLimitPercentage, numberOfPixels); + } + + // Calculate the cumulative distribution function, which will map each input pixel to a new value. + int cdfMin = this.CalculateCdf( + ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()), + ref MemoryMarshal.GetReference(histogram), + histogram.Length - 1); + + float numberOfPixelsMinusCdfMin = numberOfPixels - cdfMin; + + // Apply the cdf to each pixel of the image + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + ref int cdfBase = ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()); + for (int y = rows.Min; y < rows.Max; y++) + { + ref TPixel pixelBase = ref MemoryMarshal.GetReference(source.GetPixelRowSpan(y)); + + for (int x = 0; x < workingRect.Width; x++) + { + ref TPixel pixel = ref Unsafe.Add(ref pixelBase, x); + int luminance = GetLuminance(pixel, this.LuminanceLevels); + float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / numberOfPixelsMinusCdfMin; + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + } + } + }); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs index 0d1a37836..1d9d5c986 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationOptions.cs @@ -38,6 +38,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// /// Gets or sets the number of tiles the image is split into (horizontal and vertically) for the adaptive histogram equalization. Defaults to 10. /// - public int Tiles { get; set; } = 10; + public int NumberOfTiles { get; set; } = 10; } } diff --git a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs index fd1b6b978..4aad1f564 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs @@ -1,10 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Normalization @@ -12,14 +8,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// /// Defines a processor that normalizes the histogram of an image. /// - /// The pixel format. - internal abstract class HistogramEqualizationProcessor : ImageProcessor - where TPixel : struct, IPixel + internal abstract class HistogramEqualizationProcessor : IImageProcessor { - private readonly float luminanceLevelsFloat; - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images /// or 65536 for 16-bit grayscale images. @@ -27,12 +19,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. protected HistogramEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage) { - Guard.MustBeGreaterThan(luminanceLevels, 0, nameof(luminanceLevels)); - Guard.MustBeGreaterThan(clipLimitPercentage, 0F, nameof(clipLimitPercentage)); - this.LuminanceLevels = luminanceLevels; - this.luminanceLevelsFloat = luminanceLevels; - this.ClipHistogramEnabled = clipHistogram; + this.ClipHistogram = clipHistogram; this.ClipLimitPercentage = clipLimitPercentage; } @@ -44,95 +32,61 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// /// Gets a value indicating whether to clip the histogram bins at a specific value. /// - public bool ClipHistogramEnabled { get; } + public bool ClipHistogram { get; } /// /// Gets the histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. /// public float ClipLimitPercentage { get; } - /// - /// Calculates the cumulative distribution function. - /// - /// The reference to the array holding the cdf. - /// The reference to the histogram of the input image. - /// Index of the maximum of the histogram. - /// The first none zero value of the cdf. - public int CalculateCdf(ref int cdfBase, ref int histogramBase, int maxIdx) - { - int histSum = 0; - int cdfMin = 0; - bool cdfMinFound = false; - - for (int i = 0; i <= maxIdx; i++) - { - histSum += Unsafe.Add(ref histogramBase, i); - if (!cdfMinFound && histSum != 0) - { - cdfMin = histSum; - cdfMinFound = true; - } - - // Creating the lookup table: subtracting cdf min, so we do not need to do that inside the for loop. - Unsafe.Add(ref cdfBase, i) = Math.Max(0, histSum - cdfMin); - } - - return cdfMin; - } + /// + public abstract IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel; /// - /// AHE tends to over amplify the contrast in near-constant regions of the image, since the histogram in such regions is highly concentrated. - /// Clipping the histogram is meant to reduce this effect, by cutting of histogram bin's which exceed a certain amount and redistribute - /// the values over the clip limit to all other bins equally. + /// Creates the that implements the algorithm + /// defined by the given . /// - /// The histogram to apply the clipping. - /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. - /// The numbers of pixels inside the tile. - public void ClipHistogram(Span histogram, float clipLimitPercentage, int pixelCount) + /// The . + /// The . + public static HistogramEqualizationProcessor FromOptions(HistogramEqualizationOptions options) { - int clipLimit = (int)MathF.Round(pixelCount * clipLimitPercentage); - int sumOverClip = 0; - ref int histogramBase = ref MemoryMarshal.GetReference(histogram); + HistogramEqualizationProcessor processor; - for (int i = 0; i < histogram.Length; i++) + switch (options.Method) { - ref int histogramLevel = ref Unsafe.Add(ref histogramBase, i); - if (histogramLevel > clipLimit) - { - sumOverClip += histogramLevel - clipLimit; - histogramLevel = clipLimit; - } + case HistogramEqualizationMethod.Global: + processor = new GlobalHistogramEqualizationProcessor( + options.LuminanceLevels, + options.ClipHistogram, + options.ClipLimitPercentage); + break; + + case HistogramEqualizationMethod.AdaptiveTileInterpolation: + processor = new AdaptiveHistEqualizationProcessor( + options.LuminanceLevels, + options.ClipHistogram, + options.ClipLimitPercentage, + options.NumberOfTiles); + break; + + case HistogramEqualizationMethod.AdaptiveSlidingWindow: + processor = new AdaptiveHistEqualizationSWProcessor( + options.LuminanceLevels, + options.ClipHistogram, + options.ClipLimitPercentage, + options.NumberOfTiles); + break; + + default: + processor = new GlobalHistogramEqualizationProcessor( + options.LuminanceLevels, + options.ClipHistogram, + options.ClipLimitPercentage); + break; } - int addToEachBin = sumOverClip > 0 ? (int)MathF.Floor(sumOverClip / this.luminanceLevelsFloat) : 0; - if (addToEachBin > 0) - { - for (int i = 0; i < histogram.Length; i++) - { - Unsafe.Add(ref histogramBase, i) += addToEachBin; - } - } + return processor; } - - /// - /// Convert the pixel values to grayscale using ITU-R Recommendation BT.709. - /// - /// The pixel to get the luminance from - /// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images) - [MethodImpl(InliningOptions.ShortMethod)] - public static int GetLuminance(TPixel sourcePixel, int luminanceLevels) - { - var vector = sourcePixel.ToVector4(); - return GetLuminance(ref vector, luminanceLevels); - } - - /// - /// Convert the pixel values to grayscale using ITU-R Recommendation BT.709. - /// - /// The vector to get the luminance from - /// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images) - [MethodImpl(InliningOptions.ShortMethod)] - public static int GetLuminance(ref Vector4 vector, int luminanceLevels) - => (int)MathF.Round(((.2126F * vector.X) + (.7152F * vector.Y) + (.0722F * vector.Y)) * (luminanceLevels - 1)); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs new file mode 100644 index 000000000..8dbc903f2 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs @@ -0,0 +1,139 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing.Processors.Normalization +{ + /// + /// Defines a processor that normalizes the histogram of an image. + /// + /// The pixel format. + internal abstract class HistogramEqualizationProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly float luminanceLevelsFloat; + + /// + /// Initializes a new instance of the class. + /// + /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images + /// or 65536 for 16-bit grayscale images. + /// Indicates, if histogram bins should be clipped. + /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. + protected HistogramEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage) + { + Guard.MustBeGreaterThan(luminanceLevels, 0, nameof(luminanceLevels)); + Guard.MustBeGreaterThan(clipLimitPercentage, 0F, nameof(clipLimitPercentage)); + + this.LuminanceLevels = luminanceLevels; + this.luminanceLevelsFloat = luminanceLevels; + this.ClipHistogramEnabled = clipHistogram; + this.ClipLimitPercentage = clipLimitPercentage; + } + + /// + /// Gets the number of luminance levels. + /// + public int LuminanceLevels { get; } + + /// + /// Gets a value indicating whether to clip the histogram bins at a specific value. + /// + public bool ClipHistogramEnabled { get; } + + /// + /// Gets the histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. + /// + public float ClipLimitPercentage { get; } + + /// + /// Calculates the cumulative distribution function. + /// + /// The reference to the array holding the cdf. + /// The reference to the histogram of the input image. + /// Index of the maximum of the histogram. + /// The first none zero value of the cdf. + public int CalculateCdf(ref int cdfBase, ref int histogramBase, int maxIdx) + { + int histSum = 0; + int cdfMin = 0; + bool cdfMinFound = false; + + for (int i = 0; i <= maxIdx; i++) + { + histSum += Unsafe.Add(ref histogramBase, i); + if (!cdfMinFound && histSum != 0) + { + cdfMin = histSum; + cdfMinFound = true; + } + + // Creating the lookup table: subtracting cdf min, so we do not need to do that inside the for loop. + Unsafe.Add(ref cdfBase, i) = Math.Max(0, histSum - cdfMin); + } + + return cdfMin; + } + + /// + /// AHE tends to over amplify the contrast in near-constant regions of the image, since the histogram in such regions is highly concentrated. + /// Clipping the histogram is meant to reduce this effect, by cutting of histogram bin's which exceed a certain amount and redistribute + /// the values over the clip limit to all other bins equally. + /// + /// The histogram to apply the clipping. + /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. + /// The numbers of pixels inside the tile. + public void ClipHistogram(Span histogram, float clipLimitPercentage, int pixelCount) + { + int clipLimit = (int)MathF.Round(pixelCount * clipLimitPercentage); + int sumOverClip = 0; + ref int histogramBase = ref MemoryMarshal.GetReference(histogram); + + for (int i = 0; i < histogram.Length; i++) + { + ref int histogramLevel = ref Unsafe.Add(ref histogramBase, i); + if (histogramLevel > clipLimit) + { + sumOverClip += histogramLevel - clipLimit; + histogramLevel = clipLimit; + } + } + + int addToEachBin = sumOverClip > 0 ? (int)MathF.Floor(sumOverClip / this.luminanceLevelsFloat) : 0; + if (addToEachBin > 0) + { + for (int i = 0; i < histogram.Length; i++) + { + Unsafe.Add(ref histogramBase, i) += addToEachBin; + } + } + } + + /// + /// Convert the pixel values to grayscale using ITU-R Recommendation BT.709. + /// + /// The pixel to get the luminance from + /// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images) + [MethodImpl(InliningOptions.ShortMethod)] + public static int GetLuminance(TPixel sourcePixel, int luminanceLevels) + { + var vector = sourcePixel.ToVector4(); + return GetLuminance(ref vector, luminanceLevels); + } + + /// + /// Convert the pixel values to grayscale using ITU-R Recommendation BT.709. + /// + /// The vector to get the luminance from + /// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images) + [MethodImpl(InliningOptions.ShortMethod)] + public static int GetLuminance(ref Vector4 vector, int luminanceLevels) + => (int)MathF.Round(((.2126F * vector.X) + (.7152F * vector.Y) + (.0722F * vector.Y)) * (luminanceLevels - 1)); + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs b/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs index 84d592bd9..fc9a583dd 100644 --- a/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs +++ b/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Normalization Method = HistogramEqualizationMethod.AdaptiveSlidingWindow, LuminanceLevels = 256, ClipHistogram = true, - Tiles = 15 + NumberOfTiles = 15 }; image.Mutate(x => x.HistogramEqualization(options)); image.DebugSave(provider); @@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Normalization Method = HistogramEqualizationMethod.AdaptiveTileInterpolation, LuminanceLevels = 256, ClipHistogram = true, - Tiles = 10 + NumberOfTiles = 10 }; image.Mutate(x => x.HistogramEqualization(options)); image.DebugSave(provider); diff --git a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs index cb901c2a8..91422faaa 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs @@ -50,8 +50,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization /// The output is visually correct old 32bit runtime, /// but it is very different because of floating point inaccuracies. /// - private static readonly bool SkipAllDitherTests = - !TestEnvironment.Is64BitProcess && string.IsNullOrEmpty(TestEnvironment.NetCoreVersion); + private static readonly bool SkipAllDitherTests = false; [Theory] [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] From cf3d4b50f5241509756176653229bc5a4151f0a2 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 17:43:06 +0200 Subject: [PATCH 133/223] cache Image dimensions into a field + re-enable all target frameworks --- .../ImageSharp.Drawing.csproj | 4 +- src/ImageSharp/Image.cs | 39 +++++++++++++--- src/ImageSharp/ImageSharp.csproj | 3 +- src/ImageSharp/Image{TPixel}.cs | 45 +++++++++++++------ 4 files changed, 68 insertions(+), 23 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 1734c48de..ac5d7fdea 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -10,8 +10,8 @@ $(packageversion) 0.0.1 - - netcoreapp2.1 + netcoreapp2.1;netstandard1.3;netstandard2.0 + netstandard2.0 7.3 true diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index d0a1c4319..1566fd0ee 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -7,6 +7,7 @@ using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; namespace SixLabors.ImageSharp { @@ -17,19 +18,36 @@ namespace SixLabors.ImageSharp /// public abstract partial class Image : IImage, IConfigurable { + private Size size; + /// /// Initializes a new instance of the class. /// /// The . /// The . /// The . - protected Image(Configuration configuration, PixelTypeInfo pixelType, ImageMetadata metadata) + /// The . + protected Image(Configuration configuration, PixelTypeInfo pixelType, ImageMetadata metadata, Size size) { this.Configuration = configuration ?? Configuration.Default; this.PixelType = pixelType; + this.size = size; this.Metadata = metadata ?? new ImageMetadata(); } + /// + /// Initializes a new instance of the class. + /// + internal Image( + Configuration configuration, + PixelTypeInfo pixelType, + ImageMetadata metadata, + int width, + int height) + : this(configuration, pixelType, metadata, new Size(width, height)) + { + } + /// /// Gets the . /// @@ -39,10 +57,10 @@ namespace SixLabors.ImageSharp public PixelTypeInfo PixelType { get; } /// - public abstract int Width { get; } + public int Width => this.size.Width; /// - public abstract int Height { get; } + public int Height => this.size.Height; /// public ImageMetadata Metadata { get; } @@ -55,8 +73,6 @@ namespace SixLabors.ImageSharp /// public abstract void Dispose(); - internal abstract void AcceptVisitor(IImageVisitor visitor); - /// /// Saves the image to the given stream using the given image encoder. /// @@ -72,6 +88,19 @@ namespace SixLabors.ImageSharp this.AcceptVisitor(visitor); } + /// + /// Accept a . + /// Implemented by invoking + /// with the pixel type of the image. + /// + internal abstract void AcceptVisitor(IImageVisitor visitor); + + /// + /// Update the size of the image after mutation. + /// + /// The . + protected void UpdateSize(Size size) => this.size = size; + private class EncodeVisitor : IImageVisitor { private readonly IImageEncoder encoder; diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index f780ca666..e763b8ef1 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -11,8 +11,7 @@ $(packageversion) 0.0.1 - - netcoreapp2.1 + netcoreapp2.1;netstandard1.3;netstandard2.0;net472 true true diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 243e2912b..27e2bc593 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -3,14 +3,13 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; namespace SixLabors.ImageSharp { @@ -67,14 +66,14 @@ namespace SixLabors.ImageSharp /// The height of the image in pixels. /// The images metadata. internal Image(Configuration configuration, int width, int height, ImageMetadata metadata) - : base(configuration, PixelTypeInfo.Create(), metadata) + : base(configuration, PixelTypeInfo.Create(), metadata, width, height) { this.Frames = new ImageFrameCollection(this, width, height, default(TPixel)); } /// /// Initializes a new instance of the class - /// wrapping an external + /// wrapping an external . /// /// The configuration providing initialization code which allows extending the library. /// The memory source. @@ -82,7 +81,7 @@ namespace SixLabors.ImageSharp /// The height of the image in pixels. /// The images metadata. internal Image(Configuration configuration, MemorySource memorySource, int width, int height, ImageMetadata metadata) - : base(configuration, PixelTypeInfo.Create(), metadata) + : base(configuration, PixelTypeInfo.Create(), metadata, width, height) { this.Frames = new ImageFrameCollection(this, width, height, memorySource); } @@ -97,7 +96,7 @@ namespace SixLabors.ImageSharp /// The color to initialize the pixels with. /// The images metadata. internal Image(Configuration configuration, int width, int height, TPixel backgroundColor, ImageMetadata metadata) - : base(configuration, PixelTypeInfo.Create(), metadata) + : base(configuration, PixelTypeInfo.Create(), metadata, width, height) { this.Frames = new ImageFrameCollection(this, width, height, backgroundColor); } @@ -110,17 +109,11 @@ namespace SixLabors.ImageSharp /// The images metadata. /// The frames that will be owned by this image instance. internal Image(Configuration configuration, ImageMetadata metadata, IEnumerable> frames) - : base(configuration, PixelTypeInfo.Create(), metadata) + : base(configuration, PixelTypeInfo.Create(), metadata, ValidateFramesAndGetSize(frames)) { this.Frames = new ImageFrameCollection(this, frames); } - /// - public override int Width => this.Frames.RootFrame.Width; - - /// - public override int Height => this.Frames.RootFrame.Height; - /// /// Gets the frames. /// @@ -173,7 +166,7 @@ namespace SixLabors.ImageSharp /// /// The pixel format. /// The configuration providing initialization code which allows extending the library. - /// The + /// The . public Image CloneAs(Configuration configuration) where TPixel2 : struct, IPixel { @@ -184,6 +177,7 @@ namespace SixLabors.ImageSharp /// public override void Dispose() => this.Frames.Dispose(); + /// internal override void AcceptVisitor(IImageVisitor visitor) { visitor.Visit(this); @@ -204,6 +198,29 @@ namespace SixLabors.ImageSharp { this.Frames[i].SwapOrCopyPixelsBufferFrom(pixelSource.Frames[i]); } + + this.UpdateSize(pixelSource.Size()); + } + + private static Size ValidateFramesAndGetSize(IEnumerable> frames) + { + Guard.NotNull(frames, nameof(frames)); + + ImageFrame rootFrame = frames.FirstOrDefault(); + + if (rootFrame == null) + { + throw new ArgumentException("Must not be empty.", nameof(frames)); + } + + Size rootSize = rootFrame.Size(); + + if (frames.Any(f => f.Size() != rootSize)) + { + throw new ArgumentException("The provided frames must be of the same size.", nameof(frames)); + } + + return rootSize; } } } \ No newline at end of file From 52c4a3d41746af6212da395c79bdf675cd19b5db Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 19:33:34 +0200 Subject: [PATCH 134/223] fix Image.FromStream() + add tests --- src/ImageSharp/Formats/Bmp/ImageExtensions.cs | 19 +- src/ImageSharp/Formats/Gif/ImageExtensions.cs | 19 +- .../Formats/Jpeg/ImageExtensions.cs | 19 +- src/ImageSharp/Formats/Png/ImageExtensions.cs | 18 +- src/ImageSharp/Image.FromBytes.cs | 207 +++++++++++++----- src/ImageSharp/Image.FromFile.cs | 16 +- src/ImageSharp/Image.FromStream.cs | 50 +++-- .../Drawing/RecolorImageTest.cs | 4 +- .../Drawing/SolidPolygonTests.cs | 2 +- .../Formats/Bmp/BmpEncoderTests.cs | 4 +- .../Formats/GeneralFormatTests.cs | 6 +- .../Formats/Gif/GifDecoderTests.cs | 6 +- .../Formats/Gif/GifEncoderTests.cs | 6 +- .../Formats/Jpg/JpegDecoderTests.MetaData.cs | 2 +- .../Formats/Jpg/JpegEncoderTests.cs | 8 +- .../Formats/Png/PngDecoderTests.cs | 6 +- .../Formats/Png/PngEncoderTests.cs | 6 +- .../Image/ImageTests.ImageLoadTestBase.cs | 25 ++- .../Image/ImageTests.Load_FileSystemPath.cs | 2 +- .../Image/ImageTests.Load_FromBytes.cs | 120 ---------- ...s.Load_FromBytes_PassLocalConfiguration.cs | 119 ++++++++++ ...s.Load_FromBytes_UseGlobalConfiguration.cs | 101 +++++++++ .../Image/ImageTests.Load_FromStream.cs | 102 --------- ....Load_FromStream_PassLocalConfiguration.cs | 93 ++++++++ ...Load_FromStream_UseDefaultConfiguration.cs | 95 ++++++++ .../Profiles/Exif/ExifProfileTests.cs | 12 +- .../MetaData/Profiles/Exif/ExifValueTests.cs | 2 +- .../PorterDuffCompositorTests.cs | 2 +- tests/ImageSharp.Tests/TestFile.cs | 6 +- tests/ImageSharp.Tests/TestFileSystem.cs | 31 +-- tests/ImageSharp.Tests/TestFormat.cs | 63 +++++- .../Tests/ReferenceDecoderBenchmarks.cs | 2 +- 32 files changed, 761 insertions(+), 412 deletions(-) delete mode 100644 tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes.cs create mode 100644 tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs create mode 100644 tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs delete mode 100644 tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream.cs create mode 100644 tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_PassLocalConfiguration.cs create mode 100644 tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs diff --git a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs index aa1c353db..0c37907c2 100644 --- a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs @@ -2,38 +2,35 @@ // Licensed under the Apache License, Version 2.0. using System.IO; + using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats.Bmp; -using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { /// - /// Extension methods for the type. + /// Extension methods for the type. /// public static partial class ImageExtensions { /// /// Saves the image to the given stream with the bmp format. /// - /// The pixel format. /// The image this method extends. /// The stream to save the image to. /// Thrown if the stream is null. - public static void SaveAsBmp(this Image source, Stream stream) - where TPixel : struct, IPixel - => source.SaveAsBmp(stream, null); + public static void SaveAsBmp(this Image source, Stream stream) => source.SaveAsBmp(stream, null); /// /// Saves the image to the given stream with the bmp format. /// - /// The pixel format. /// The image this method extends. /// The stream to save the image to. /// The encoder to save the image with. /// Thrown if the stream is null. - public static void SaveAsBmp(this Image source, Stream stream, BmpEncoder encoder) - where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance)); + public static void SaveAsBmp(this Image source, Stream stream, BmpEncoder encoder) => + source.Save( + stream, + encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(BmpFormat.Instance)); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Gif/ImageExtensions.cs b/src/ImageSharp/Formats/Gif/ImageExtensions.cs index 8ddd4247e..c7ac001ff 100644 --- a/src/ImageSharp/Formats/Gif/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Gif/ImageExtensions.cs @@ -2,38 +2,35 @@ // Licensed under the Apache License, Version 2.0. using System.IO; + using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats.Gif; -using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { /// - /// Extension methods for the type. + /// Extension methods for the type. /// public static partial class ImageExtensions { /// /// Saves the image to the given stream in the gif format. /// - /// The pixel format. /// The image this method extends. /// The stream to save the image to. /// Thrown if the stream is null. - public static void SaveAsGif(this Image source, Stream stream) - where TPixel : struct, IPixel - => source.SaveAsGif(stream, null); + public static void SaveAsGif(this Image source, Stream stream) => source.SaveAsGif(stream, null); /// /// Saves the image to the given stream in the gif format. /// - /// The pixel format. /// The image this method extends. /// The stream to save the image to. /// The options for the encoder. /// Thrown if the stream is null. - public static void SaveAsGif(this Image source, Stream stream, GifEncoder encoder) - where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance)); + public static void SaveAsGif(this Image source, Stream stream, GifEncoder encoder) => + source.Save( + stream, + encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(GifFormat.Instance)); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs index cb7fc1944..7fec050b4 100644 --- a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs @@ -2,38 +2,35 @@ // Licensed under the Apache License, Version 2.0. using System.IO; + using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { /// - /// Extension methods for the type. + /// Extension methods for the type. /// public static partial class ImageExtensions { /// /// Saves the image to the given stream with the jpeg format. /// - /// The pixel format. /// The image this method extends. /// The stream to save the image to. /// Thrown if the stream is null. - public static void SaveAsJpeg(this Image source, Stream stream) - where TPixel : struct, IPixel - => SaveAsJpeg(source, stream, null); + public static void SaveAsJpeg(this Image source, Stream stream) => SaveAsJpeg(source, stream, null); /// /// Saves the image to the given stream with the jpeg format. /// - /// The pixel format. /// The image this method extends. /// The stream to save the image to. /// The options for the encoder. /// Thrown if the stream is null. - public static void SaveAsJpeg(this Image source, Stream stream, JpegEncoder encoder) - where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance)); + public static void SaveAsJpeg(this Image source, Stream stream, JpegEncoder encoder) => + source.Save( + stream, + encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance)); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Png/ImageExtensions.cs b/src/ImageSharp/Formats/Png/ImageExtensions.cs index c73ec6f57..af56830f4 100644 --- a/src/ImageSharp/Formats/Png/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Png/ImageExtensions.cs @@ -2,39 +2,35 @@ // Licensed under the Apache License, Version 2.0. using System.IO; + using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { /// - /// Extension methods for the type. + /// Extension methods for the type. /// public static partial class ImageExtensions { /// /// Saves the image to the given stream with the png format. /// - /// The pixel format. /// The image this method extends. /// The stream to save the image to. /// Thrown if the stream is null. - public static void SaveAsPng(this Image source, Stream stream) - where TPixel : struct, IPixel - => SaveAsPng(source, stream, null); + public static void SaveAsPng(this Image source, Stream stream) => SaveAsPng(source, stream, null); /// /// Saves the image to the given stream with the png format. /// - /// The pixel format. /// The image this method extends. /// The stream to save the image to. /// The options for the encoder. /// Thrown if the stream is null. - public static void SaveAsPng(this Image source, Stream stream, PngEncoder encoder) - where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance)); + public static void SaveAsPng(this Image source, Stream stream, PngEncoder encoder) => + source.Save( + stream, + encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance)); } } \ No newline at end of file diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs index 24a169f6e..25dc5a1e0 100644 --- a/src/ImageSharp/Image.FromBytes.cs +++ b/src/ImageSharp/Image.FromBytes.cs @@ -44,48 +44,6 @@ namespace SixLabors.ImageSharp /// A new . public static Image Load(byte[] data) => Load(Configuration.Default, data); - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The byte array containing encoded image data. - /// The mime type of the decoded image. - /// A new . - public static Image Load(byte[] data, out IImageFormat format) => Load(Configuration.Default, data, out format); - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The config for the decoder. - /// The byte array containing encoded image data. - /// A new . - public static Image Load(Configuration config, byte[] data) => Load(config, data); - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The config for the decoder. - /// The byte array containing image data. - /// The mime type of the decoded image. - /// A new . - public static Image Load(Configuration config, byte[] data, out IImageFormat format) => Load(config, data, out format); - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The byte array containing encoded image data. - /// The decoder. - /// A new . - public static Image Load(byte[] data, IImageDecoder decoder) => Load(data, decoder); - - /// - /// Load a new instance of from the given encoded byte array. - /// - /// The config for the decoder. - /// The byte array containing image data. - /// The decoder. - /// A new . - public static Image Load(Configuration config, byte[] data, IImageDecoder decoder) => Load(config, data, decoder); - /// /// Load a new instance of from the given encoded byte array. /// @@ -117,9 +75,9 @@ namespace SixLabors.ImageSharp public static Image Load(Configuration config, byte[] data) where TPixel : struct, IPixel { - using (var steram = new MemoryStream(data)) + using (var stream = new MemoryStream(data)) { - return Load(config, steram); + return Load(config, stream); } } @@ -211,29 +169,36 @@ namespace SixLabors.ImageSharp } /// - /// Load a new instance of from the given encoded byte span. + /// Load a new instance of from the given encoded byte span. /// - /// The byte span containing image data. - /// A new . - public static Image Load(ReadOnlySpan data) => Load(Configuration.Default, data); + /// The byte span containing encoded image data. + /// The pixel format. + /// A new . + public static Image Load(ReadOnlySpan data) + where TPixel : struct, IPixel + => Load(Configuration.Default, data); /// - /// Load a new instance of from the given encoded byte span. + /// Load a new instance of from the given encoded byte array. /// - /// The config for the decoder. - /// The byte span containing encoded image data. - /// A new . - public static Image Load(Configuration config, ReadOnlySpan data) => Load(config, data); + /// The byte span containing image data. + /// The mime type of the decoded image. + /// The pixel format. + /// A new . + public static Image Load(ReadOnlySpan data, out IImageFormat format) + where TPixel : struct, IPixel + => Load(Configuration.Default, data, out format); /// - /// Load a new instance of from the given encoded byte span. + /// Load a new instance of from the given encoded byte array. /// /// The byte span containing encoded image data. + /// The decoder. /// The pixel format. /// A new . - public static Image Load(ReadOnlySpan data) + public static Image Load(ReadOnlySpan data, IImageDecoder decoder) where TPixel : struct, IPixel - => Load(Configuration.Default, data); + => Load(Configuration.Default, data, decoder); /// /// Load a new instance of from the given encoded byte span. @@ -299,5 +264,135 @@ namespace SixLabors.ImageSharp } } } + + /// + /// Load a new instance of from the given encoded byte array. + /// + /// The byte array containing image data. + /// The detected format. + /// A new . + public static Image Load(byte[] data, out IImageFormat format) => + Load(Configuration.Default, data, out format); + + /// + /// Load a new instance of from the given encoded byte array. + /// + /// The byte array containing encoded image data. + /// The decoder. + /// A new . + public static Image Load(byte[] data, IImageDecoder decoder) => Load(Configuration.Default, data, decoder); + + /// + /// Load a new instance of from the given encoded byte array. + /// + /// The config for the decoder. + /// The byte array containing encoded image data. + /// A new . + public static Image Load(Configuration config, byte[] data) => Load(config, data, out _); + + /// + /// Load a new instance of from the given encoded byte array. + /// + /// The config for the decoder. + /// The byte array containing image data. + /// The decoder. + /// A new . + public static Image Load(Configuration config, byte[] data, IImageDecoder decoder) + { + using (var stream = new MemoryStream(data)) + { + return Load(config, stream, decoder); + } + } + + /// + /// Load a new instance of from the given encoded byte array. + /// + /// The config for the decoder. + /// The byte array containing image data. + /// The mime type of the decoded image. + /// A new . + public static Image Load(Configuration config, byte[] data, out IImageFormat format) + { + using (var stream = new MemoryStream(data)) + { + return Load(config, stream, out format); + } + } + + /// + /// Load a new instance of from the given encoded byte span. + /// + /// The byte span containing image data. + /// A new . + public static Image Load(ReadOnlySpan data) => Load(Configuration.Default, data); + + /// + /// Load a new instance of from the given encoded byte span. + /// + /// The byte span containing image data. + /// The decoder. + /// A new . + public static Image Load(ReadOnlySpan data, IImageDecoder decoder) => + Load(Configuration.Default, data, decoder); + + /// + /// Load a new instance of from the given encoded byte array. + /// + /// The byte span containing image data. + /// The detected format. + /// A new . + public static Image Load(ReadOnlySpan data, out IImageFormat format) => + Load(Configuration.Default, data, out format); + + /// + /// Decodes a new instance of from the given encoded byte span. + /// + /// The configuration options. + /// The byte span containing image data. + /// A new . + public static unsafe Image Load(Configuration config, ReadOnlySpan data) => Load(config, data, out _); + + /// + /// Load a new instance of from the given encoded byte span. + /// + /// The Configuration. + /// The byte span containing image data. + /// The decoder. + /// A new . + public static unsafe Image Load( + Configuration config, + ReadOnlySpan data, + IImageDecoder decoder) + { + fixed (byte* ptr = &data.GetPinnableReference()) + { + using (var stream = new UnmanagedMemoryStream(ptr, data.Length)) + { + return Load(config, stream, decoder); + } + } + } + + /// + /// Load a new instance of from the given encoded byte span. + /// + /// The configuration options. + /// The byte span containing image data. + /// The of the decoded image.> + /// A new . + public static unsafe Image Load( + Configuration config, + ReadOnlySpan data, + out IImageFormat format) + { + fixed (byte* ptr = &data.GetPinnableReference()) + { + using (var stream = new UnmanagedMemoryStream(ptr, data.Length)) + { + return Load(config, stream, out format); + } + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/Image.FromFile.cs b/src/ImageSharp/Image.FromFile.cs index 61500e20d..08ed381c5 100644 --- a/src/ImageSharp/Image.FromFile.cs +++ b/src/ImageSharp/Image.FromFile.cs @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(string path) => Load(path); + public static Image Load(string path) => Load(Configuration.Default, path); /// /// Create a new instance of the class from the given file. @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(string path, out IImageFormat format) => Load(path, out format); + public static Image Load(string path, out IImageFormat format) => Load(Configuration.Default, path, out format); /// /// Create a new instance of the class from the given file. @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(Configuration config, string path) => Load(config, path); + public static Image Load(Configuration config, string path) => Load(config, path, out _); /// /// Create a new instance of the class from the given file. @@ -80,7 +80,13 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(Configuration config, string path, IImageDecoder decoder) => Load(config, path, decoder); + public static Image Load(Configuration config, string path, IImageDecoder decoder) + { + using (Stream stream = config.FileSystem.OpenRead(path)) + { + return Load(config, stream, decoder); + } + } /// /// Create a new instance of the class from the given file. @@ -91,7 +97,7 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(string path, IImageDecoder decoder) => Load(path, decoder); + public static Image Load(string path, IImageDecoder decoder) => Load(Configuration.Default, path, decoder); /// /// Create a new instance of the class from the given file. diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index a4a9eeec7..74b99dfb3 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -56,39 +56,54 @@ namespace SixLabors.ImageSharp => WithSeekableStream(config, stream, s => InternalIdentity(s, config ?? Configuration.Default)); /// - /// Create a new instance of the class from the given stream. + /// Decode a new instance of the class from the given stream. + /// The pixel format is selected by the decoder. /// /// The stream containing image information. /// the mime type of the decoded image. /// Thrown if the stream is not readable. - /// A new .> - public static Image Load(Stream stream, out IImageFormat format) => Load(stream, out format); + /// A new .> + public static Image Load(Stream stream, out IImageFormat format) => Load(Configuration.Default, stream, out format); /// - /// Create a new instance of the class from the given stream. + /// Decode a new instance of the class from the given stream. + /// The pixel format is selected by the decoder. /// /// The stream containing image information. /// Thrown if the stream is not readable. - /// A new .> - public static Image Load(Stream stream) => Load(stream); + /// A new .> + public static Image Load(Stream stream) => Load(Configuration.Default, stream); /// - /// Create a new instance of the class from the given stream. + /// Decode a new instance of the class from the given stream. + /// The pixel format is selected by the decoder. /// /// The stream containing image information. /// The decoder. /// Thrown if the stream is not readable. - /// A new .> - public static Image Load(Stream stream, IImageDecoder decoder) => Load(stream, decoder); + /// A new .> + public static Image Load(Stream stream, IImageDecoder decoder) => Load(Configuration.Default, stream, decoder); /// - /// Create a new instance of the class from the given stream. + /// Decode a new instance of the class from the given stream. + /// The pixel format is selected by the decoder. + /// + /// The config for the decoder. + /// The stream containing image information. + /// The decoder. + /// Thrown if the stream is not readable. + /// A new .> + public static Image Load(Configuration config, Stream stream, IImageDecoder decoder) => + WithSeekableStream(config, stream, s => decoder.Decode(config, s)); + + /// + /// Decode a new instance of the class from the given stream. /// /// The config for the decoder. /// The stream containing image information. /// Thrown if the stream is not readable. - /// A new .> - public static Image Load(Configuration config, Stream stream) => Load(config, stream); + /// A new .> + public static Image Load(Configuration config, Stream stream) => Load(config, stream, out _); /// /// Create a new instance of the class from the given stream. @@ -183,7 +198,16 @@ namespace SixLabors.ImageSharp throw new NotSupportedException(sb.ToString()); } - private static Image Load(Configuration config, Stream stream, out IImageFormat format) + /// + /// Decode a new instance of the class from the given stream. + /// The pixel format is selected by the decoder. + /// + /// The configuration options. + /// The stream containing image information. + /// the mime type of the decoded image. + /// Thrown if the stream is not readable. + /// A new . + public static Image Load(Configuration config, Stream stream, out IImageFormat format) { config = config ?? Configuration.Default; (Image img, IImageFormat format) data = WithSeekableStream(config, stream, s => Decode(s, config)); diff --git a/tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs b/tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs index 2dcd8b3d3..b064d9c96 100644 --- a/tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs +++ b/tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Tests foreach (TestFile file in Files) { - using (Image image = file.CreateImage()) + using (Image image = file.CreateRgba32Image()) { image.Mutate(x => x.Fill(brush)); image.Save($"{path}/{file.FileName}"); @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Tests foreach (TestFile file in Files) { - using (Image image = file.CreateImage()) + using (Image image = file.CreateRgba32Image()) { int imageHeight = image.Height; image.Mutate(x => x.Fill(brush, new Rectangle(0, imageHeight / 2 - imageHeight / 4, image.Width, imageHeight / 2))); diff --git a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs index d7fb0a3d3..5660518eb 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs @@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing new Vector2(50, 300) }; - using (Image brushImage = TestFile.Create(TestImages.Bmp.Car).CreateImage()) + using (Image brushImage = TestFile.Create(TestImages.Bmp.Car).CreateRgba32Image()) using (var image = new Image(500, 500)) { var brush = new ImageBrush(brushImage); diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index 7e054734e..df3029a7f 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp var options = new BmpEncoder(); var testFile = TestFile.Create(imagePath); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) { using (var memStream = new MemoryStream()) { @@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp var options = new BmpEncoder(); var testFile = TestFile.Create(imagePath); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) { using (var memStream = new MemoryStream()) { diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs index e8fdbd892..b2f9788ae 100644 --- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs +++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests foreach (TestFile file in Files) { - using (Image image = file.CreateImage()) + using (Image image = file.CreateRgba32Image()) { string filename = path + "/" + file.FileNameWithoutExtension + ".txt"; File.WriteAllText(filename, image.ToBase64String(PngFormat.Instance)); @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Tests foreach (TestFile file in Files) { - using (Image image = file.CreateImage()) + using (Image image = file.CreateRgba32Image()) { image.Save($"{path}/{file.FileName}"); } @@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.Tests foreach (TestFile file in Files) { - using (Image image = file.CreateImage()) + using (Image image = file.CreateRgba32Image()) { using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.bmp")) { diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index b13362aa3..784f7ce70 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -165,7 +165,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var testFile = TestFile.Create(TestImages.Gif.Rings); - using (Image image = testFile.CreateImage(options)) + using (Image image = testFile.CreateRgba32Image(options)) { Assert.Equal(1, image.Metadata.Properties.Count); Assert.Equal("Comments", image.Metadata.Properties[0].Name); @@ -183,7 +183,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var testFile = TestFile.Create(TestImages.Gif.Rings); - using (Image image = testFile.CreateImage(options)) + using (Image image = testFile.CreateRgba32Image(options)) { Assert.Equal(0, image.Metadata.Properties.Count); } @@ -199,7 +199,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var testFile = TestFile.Create(TestImages.Gif.Rings); - using (Image image = testFile.CreateImage(options)) + using (Image image = testFile.CreateRgba32Image(options)) { Assert.Equal(1, image.Metadata.Properties.Count); Assert.Equal("浉条卥慨灲", image.Metadata.Properties[0].Value); diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index 5da1c3bb7..eab30944e 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var options = new GifEncoder(); var testFile = TestFile.Create(imagePath); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) { using (var memStream = new MemoryStream()) { @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var testFile = TestFile.Create(TestImages.Gif.Rings); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) { using (var memStream = new MemoryStream()) { @@ -107,7 +107,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif var testFile = TestFile.Create(TestImages.Gif.Rings); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) { input.Metadata.Properties.Clear(); using (var memStream = new MemoryStream()) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs index 48acc9ea4..308cf28b3 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.MetaData.cs @@ -216,7 +216,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg // Snake.jpg has both Exif and ICC profiles defined: var testFile = TestFile.Create(TestImages.Jpeg.Baseline.Snake); - using (Image image = testFile.CreateImage(decoder)) + using (Image image = testFile.CreateRgba32Image(decoder)) { if (ignoreMetaData) { diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs index 618947130..d9013b507 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var options = new JpegEncoder(); var testFile = TestFile.Create(imagePath); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) { using (var memStream = new MemoryStream()) { @@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var testFile = TestFile.Create(TestImages.Jpeg.Baseline.Calliphora); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) using (var memStream0 = new MemoryStream()) using (var memStream1 = new MemoryStream()) { @@ -160,7 +160,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var testFile = TestFile.Create(TestImages.Jpeg.Baseline.Calliphora); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) using (var memStream0 = new MemoryStream()) using (var memStream1 = new MemoryStream()) { @@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var options = new JpegEncoder(); var testFile = TestFile.Create(imagePath); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) { using (var memStream = new MemoryStream()) { diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 0dbccd250..70d191d74 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -202,7 +202,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var testFile = TestFile.Create(TestImages.Png.Blur); - using (Image image = testFile.CreateImage(options)) + using (Image image = testFile.CreateRgba32Image(options)) { Assert.Equal(1, image.Metadata.Properties.Count); Assert.Equal("Software", image.Metadata.Properties[0].Name); @@ -220,7 +220,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var testFile = TestFile.Create(TestImages.Png.Blur); - using (Image image = testFile.CreateImage(options)) + using (Image image = testFile.CreateRgba32Image(options)) { Assert.Equal(0, image.Metadata.Properties.Count); } @@ -236,7 +236,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var testFile = TestFile.Create(TestImages.Png.Blur); - using (Image image = testFile.CreateImage(options)) + using (Image image = testFile.CreateRgba32Image(options)) { Assert.Equal(1, image.Metadata.Properties.Count); Assert.Equal("潓瑦慷敲", image.Metadata.Properties[0].Name); diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index 5aa69dd6a..b8178fd4f 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var options = new PngEncoder(); var testFile = TestFile.Create(imagePath); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) { using (var memStream = new MemoryStream()) { @@ -244,7 +244,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var options = new PngEncoder(); var testFile = TestFile.Create(imagePath); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) { using (var memStream = new MemoryStream()) { @@ -268,7 +268,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png var options = new PngEncoder(); var testFile = TestFile.Create(imagePath); - using (Image input = testFile.CreateImage()) + using (Image input = testFile.CreateRgba32Image()) { PngMetadata inMeta = input.Metadata.GetFormatMetadata(PngFormat.Instance); Assert.True(inMeta.HasTrans); diff --git a/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs b/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs index aabc3f50e..ec6705d0e 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.ImageLoadTestBase.cs @@ -16,7 +16,9 @@ namespace SixLabors.ImageSharp.Tests { public abstract class ImageLoadTestBase : IDisposable { - protected Image returnImage; + protected Image localStreamReturnImageRgba32; + + protected Image localStreamReturnImageAgnostic; protected Mock localDecoder; @@ -48,12 +50,14 @@ namespace SixLabors.ImageSharp.Tests protected ImageLoadTestBase() { - this.returnImage = new Image(1, 1); + this.localStreamReturnImageRgba32 = new Image(1, 1); + this.localStreamReturnImageAgnostic = new Image(1, 1); this.localImageFormatMock = new Mock(); this.localDecoder = new Mock(); this.localMimeTypeDetector = new MockImageFormatDetector(this.localImageFormatMock.Object); + this.localDecoder.Setup(x => x.Decode(It.IsAny(), It.IsAny())) .Callback((c, s) => { @@ -63,7 +67,19 @@ namespace SixLabors.ImageSharp.Tests this.DecodedData = ms.ToArray(); } }) - .Returns(this.returnImage); + .Returns(this.localStreamReturnImageRgba32); + + this.localDecoder.Setup(x => x.Decode(It.IsAny(), It.IsAny())) + .Callback((c, s) => + { + using (var ms = new MemoryStream()) + { + s.CopyTo(ms); + this.DecodedData = ms.ToArray(); + } + }) + .Returns(this.localStreamReturnImageAgnostic); + this.LocalConfiguration = new Configuration { @@ -85,7 +101,8 @@ namespace SixLabors.ImageSharp.Tests public void Dispose() { // clean up the global object; - this.returnImage?.Dispose(); + this.localStreamReturnImageRgba32?.Dispose(); + this.localStreamReturnImageAgnostic?.Dispose(); } } } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath.cs index 1a21d3d10..d6fe43897 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Tests Assert.NotNull(img); - this.TestFormat.VerifyDecodeCall(this.Marker, this.TopLevelConfiguration); + this.TestFormat.VerifySpecificDecodeCall(this.Marker, this.TopLevelConfiguration); } [Fact] diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes.cs deleted file mode 100644 index eed1a2825..000000000 --- a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes.cs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.IO; - -using Moq; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -using Xunit; - -// ReSharper disable InconsistentNaming -namespace SixLabors.ImageSharp.Tests -{ - public partial class ImageTests - { - public class Load_FromBytes : ImageLoadTestBase - { - private byte[] ByteArray => this.DataStream.ToArray(); - - private ReadOnlySpan ByteSpan => this.ByteArray.AsSpan(); - - private byte[] ActualImageBytes => TestFile.Create(TestImages.Bmp.F).Bytes; - - private ReadOnlySpan ActualImageSpan => this.ActualImageBytes.AsSpan(); - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void BasicCase(bool useSpan) - { - Image img = useSpan - ? Image.Load(this.TopLevelConfiguration, this.ByteSpan) - : Image.Load(this.TopLevelConfiguration, this.ByteArray); - - Assert.NotNull(img); - Assert.Equal(this.TestFormat.Sample(), img); - - this.TestFormat.VerifyDecodeCall(this.Marker, this.TopLevelConfiguration); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void NonDefaultPixelType(bool useSpan) - { - Image img = useSpan - ? Image.Load(this.TopLevelConfiguration, this.ByteSpan) - : Image.Load(this.TopLevelConfiguration, this.ByteArray); - - Assert.NotNull(img); - Assert.Equal(this.TestFormat.Sample(), img); - - this.TestFormat.VerifyDecodeCall(this.Marker, this.TopLevelConfiguration); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void UseLocalConfiguration(bool useSpan) - { - Image img = useSpan - ? Image.Load(this.LocalConfiguration, this.ByteSpan) - : Image.Load(this.LocalConfiguration, this.ByteArray); - - Assert.NotNull(img); - - this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, It.IsAny())); - - Assert.Equal(this.DataStream.ToArray(), this.DecodedData); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void UseCustomDecoder(bool useSpan) - { - Image img = useSpan - ? Image.Load( - this.TopLevelConfiguration, - this.ByteSpan, - this.localDecoder.Object) - : Image.Load( - this.TopLevelConfiguration, - this.ByteArray, - this.localDecoder.Object); - Assert.NotNull(img); - this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, It.IsAny())); - Assert.Equal(this.DataStream.ToArray(), this.DecodedData); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void UseGlobalConfiguration(bool useSpan) - { - using (Image img = - useSpan ? Image.Load(this.ActualImageSpan) : Image.Load(this.ActualImageBytes)) - { - Assert.Equal(new Size(108, 202), img.Size()); - } - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void UseGlobalConfiguration_NonDefaultPixelType(bool useSpan) - { - using (Image img = useSpan - ? Image.Load(this.ActualImageSpan) - : Image.Load(this.ActualImageBytes)) - { - Assert.Equal(new Size(108, 202), img.Size()); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs new file mode 100644 index 000000000..5fe87fedc --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_PassLocalConfiguration.cs @@ -0,0 +1,119 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ImageTests + { + public class Load_FromBytes_PassLocalConfiguration : ImageLoadTestBase + { + private byte[] ByteArray => this.DataStream.ToArray(); + + private ReadOnlySpan ByteSpan => this.ByteArray.AsSpan(); + + private byte[] ActualImageBytes => TestFile.Create(TestImages.Bmp.F).Bytes; + + private ReadOnlySpan ActualImageSpan => this.ActualImageBytes.AsSpan(); + + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Configuration_Bytes_Specific(bool useSpan) + { + var img = useSpan + ? Image.Load(this.TopLevelConfiguration, this.ByteSpan) + : Image.Load(this.TopLevelConfiguration, this.ByteArray); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat.Sample(), img); + + this.TestFormat.VerifySpecificDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Configuration_Bytes_Agnostic(bool useSpan) + { + var img = useSpan + ? Image.Load(this.TopLevelConfiguration, this.ByteSpan) + : Image.Load(this.TopLevelConfiguration, this.ByteArray); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat.SampleAgnostic(), img); + + this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Configuration_Bytes_Decoder_Specific(bool useSpan) + { + TestFormat localFormat = new TestFormat(); + + var img = useSpan ? + Image.Load(this.TopLevelConfiguration, this.ByteSpan, localFormat.Decoder) : + Image.Load(this.TopLevelConfiguration, this.ByteArray, localFormat.Decoder); + + Assert.NotNull(img); + localFormat.VerifySpecificDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Configuration_Bytes_Decoder_Agnostic(bool useSpan) + { + TestFormat localFormat = new TestFormat(); + + var img = useSpan ? + Image.Load(this.TopLevelConfiguration, this.ByteSpan, localFormat.Decoder) : + Image.Load(this.TopLevelConfiguration, this.ByteArray, localFormat.Decoder); + + Assert.NotNull(img); + localFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Configuration_Bytes_OutFormat_Specific(bool useSpan) + { + IImageFormat format; + var img = useSpan ? + Image.Load(this.TopLevelConfiguration, this.ByteSpan, out format) : + Image.Load(this.TopLevelConfiguration, this.ByteArray, out format); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat, format); + + this.TestFormat.VerifySpecificDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Configuration_Bytes_OutFormat_Agnostic(bool useSpan) + { + IImageFormat format; + var img = useSpan ? + Image.Load(this.TopLevelConfiguration, this.ByteSpan, out format) : + Image.Load(this.TopLevelConfiguration, this.ByteArray, out format); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat, format); + + this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs new file mode 100644 index 000000000..23c25d9db --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs @@ -0,0 +1,101 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.IO; + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ImageTests + { + public class Load_FromBytes_UseGlobalConfiguration + { + private static byte[] ByteArray { get; } = TestFile.Create(TestImages.Bmp.F).Bytes; + + private static Span ByteSpan => new Span(ByteArray); + + private static void VerifyDecodedImage(Image img) + { + Assert.Equal(new Size(108, 202), img.Size()); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Bytes_Specific(bool useSpan) + { + using (var img = useSpan ? Image.Load(ByteSpan) : Image.Load(ByteArray)) + { + VerifyDecodedImage(img); + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Bytes_Agnostic(bool useSpan) + { + using (var img = useSpan ? Image.Load(ByteSpan) : Image.Load(ByteArray)) + { + VerifyDecodedImage(img); + } + } + + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Bytes_Decoder_Specific(bool useSpan) + { + using (var img = useSpan ? Image.Load(ByteSpan, new BmpDecoder()) : Image.Load(ByteArray, new BmpDecoder())) + { + VerifyDecodedImage(img); + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Bytes_Decoder_Agnostic(bool useSpan) + { + using (var img = useSpan ? Image.Load(ByteSpan, new BmpDecoder()) : Image.Load(ByteArray, new BmpDecoder())) + { + VerifyDecodedImage(img); + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Bytes_OutFormat_Specific(bool useSpan) + { + IImageFormat format; + using (var img = useSpan ? Image.Load(ByteSpan, out format) : Image.Load(ByteArray, out format)) + { + VerifyDecodedImage(img); + Assert.IsType(format); + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Bytes_OutFormat_Agnostic(bool useSpan) + { + IImageFormat format; + using (var img = useSpan ? Image.Load(ByteSpan, out format) : Image.Load(ByteArray, out format)) + { + VerifyDecodedImage(img); + Assert.IsType(format); + } + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream.cs deleted file mode 100644 index 6b6acb1b8..000000000 --- a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream.cs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.IO; - -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -// ReSharper disable InconsistentNaming - -namespace SixLabors.ImageSharp.Tests -{ - using SixLabors.Primitives; - - public partial class ImageTests - { - /// - /// Tests the class. - /// - public class Load_FromStream : ImageLoadTestBase - { - [Fact] - public void BasicCase() - { - var img = Image.Load(this.TopLevelConfiguration, this.DataStream); - - Assert.NotNull(img); - Assert.Equal(this.TestFormat.Sample(), img); - - this.TestFormat.VerifyDecodeCall(this.Marker, this.TopLevelConfiguration); - } - - [Fact] - public void UseGlobalConfiguration() - { - byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; - - using (var stream = new MemoryStream(data)) - using (var img = Image.Load(stream)) - { - Assert.Equal(new Size(108, 202), img.Size()); - } - } - - [Fact] - public void NonDefaultPixelTypeImage() - { - var img = Image.Load(this.TopLevelConfiguration, this.DataStream); - - Assert.NotNull(img); - Assert.Equal(this.TestFormat.Sample(), img); - - this.TestFormat.VerifyDecodeCall(this.Marker, this.TopLevelConfiguration); - } - - [Fact] - public void NonSeekableStream() - { - var stream = new NoneSeekableStream(this.DataStream); - var img = Image.Load(this.TopLevelConfiguration, stream); - - Assert.NotNull(img); - - this.TestFormat.VerifyDecodeCall(this.Marker, this.TopLevelConfiguration); - } - - [Fact] - public void UseLocalConfiguration() - { - Stream stream = new MemoryStream(); - var img = Image.Load(this.LocalConfiguration, stream); - - Assert.NotNull(img); - - this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, stream)); - } - - [Fact] - public void UseCustomDecoder() - { - Stream stream = new MemoryStream(); - var img = Image.Load(this.TopLevelConfiguration, stream, this.localDecoder.Object); - - Assert.NotNull(img); - this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, stream)); - } - - // TODO: This should be a png decoder test! - [Fact] - public void LoadsImageWithoutThrowingCrcException() - { - var image1Provider = TestImageProvider.File(TestImages.Png.VersioningImage1); - - using (Image img = image1Provider.GetImage()) - { - Assert.Equal(166036, img.Frames.RootFrame.GetPixelSpan().Length); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_PassLocalConfiguration.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_PassLocalConfiguration.cs new file mode 100644 index 000000000..5ca86c3ce --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_PassLocalConfiguration.cs @@ -0,0 +1,93 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.IO; + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ImageTests + { + public class Load_FromStream_PassLocalConfiguration : ImageLoadTestBase + { + [Fact] + public void Configuration_Stream_Specific() + { + var img = Image.Load(this.TopLevelConfiguration, this.DataStream); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat.Sample(), img); + + this.TestFormat.VerifySpecificDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Fact] + public void Configuration_Stream_Agnostic() + { + var img = Image.Load(this.TopLevelConfiguration, this.DataStream); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat.SampleAgnostic(), img); + + this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Fact] + public void NonSeekableStream() + { + var stream = new NoneSeekableStream(this.DataStream); + var img = Image.Load(this.TopLevelConfiguration, stream); + + Assert.NotNull(img); + + this.TestFormat.VerifySpecificDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Fact] + public void Configuration_Stream_Decoder_Specific() + { + Stream stream = new MemoryStream(); + var img = Image.Load(this.TopLevelConfiguration, stream, this.localDecoder.Object); + + Assert.NotNull(img); + this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, stream)); + } + + [Fact] + public void Configuration_Stream_Decoder_Agnostic() + { + Stream stream = new MemoryStream(); + var img = Image.Load(this.TopLevelConfiguration, stream, this.localDecoder.Object); + + Assert.NotNull(img); + this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, stream)); + } + + [Fact] + public void Configuration_Stream_OutFormat_Specific() + { + var img = Image.Load(this.TopLevelConfiguration, this.DataStream, out IImageFormat format); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat, format); + + this.TestFormat.VerifySpecificDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Fact] + public void Configuration_Stream_OutFormat_Agnostic() + { + var img = Image.Load(this.TopLevelConfiguration, this.DataStream, out IImageFormat format); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat, format); + + this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs new file mode 100644 index 000000000..27aba42ea --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs @@ -0,0 +1,95 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.IO; + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ImageTests + { + public class Load_FromStream_UseDefaultConfiguration + { + [Fact] + public void Stream_Specific() + { + byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; + + using (var stream = new MemoryStream(data)) + using (var img = Image.Load(stream)) + { + Assert.Equal(new Size(108, 202), img.Size()); + } + } + + [Fact] + public void Stream_Agnostic() + { + byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; + + using (var stream = new MemoryStream(data)) + using (var img = Image.Load(stream)) + { + Assert.Equal(new Size(108, 202), img.Size()); + } + } + + [Fact] + public void Stream_OutFormat_Specific() + { + byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; + + + using (var stream = new MemoryStream(data)) + using (var img = Image.Load(stream, out IImageFormat format)) + { + Assert.Equal(new Size(108, 202), img.Size()); + Assert.IsType(format); + } + } + + [Fact] + public void Stream_Decoder_Specific() + { + byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; + + using (var stream = new MemoryStream(data)) + using (var img = Image.Load(stream, new BmpDecoder())) + { + Assert.Equal(new Size(108, 202), img.Size()); + } + } + + [Fact] + public void Stream_Decoder_Agnostic() + { + byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; + + using (var stream = new MemoryStream(data)) + using (var img = Image.Load(stream, new BmpDecoder())) + { + Assert.Equal(new Size(108, 202), img.Size()); + } + } + + [Fact] + public void Stream_OutFormat_Agnostic() + { + byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; + + using (var stream = new MemoryStream(data)) + using (var img = Image.Load(stream, out IImageFormat format)) + { + Assert.Equal(new Size(108, 202), img.Size()); + Assert.IsType(format); + } + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs index 9d145f380..668e699c5 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Tests [InlineData(TestImageWriteFormat.Png)] public void Constructor(TestImageWriteFormat imageFormat) { - Image image = TestFile.Create(TestImages.Jpeg.Baseline.Calliphora).CreateImage(); + Image image = TestFile.Create(TestImages.Jpeg.Baseline.Calliphora).CreateRgba32Image(); Assert.Null(image.Metadata.ExifProfile); @@ -126,7 +126,7 @@ namespace SixLabors.ImageSharp.Tests [InlineData(TestImageWriteFormat.Png)] public void ReadWriteInfinity(TestImageWriteFormat imageFormat) { - Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage(); + Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateRgba32Image(); image.Metadata.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.PositiveInfinity)); image = WriteAndReadJpeg(image); @@ -156,7 +156,7 @@ namespace SixLabors.ImageSharp.Tests { var latitude = new Rational[] { new Rational(12.3), new Rational(4.56), new Rational(789.0) }; - Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage(); + Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateRgba32Image(); image.Metadata.ExifProfile.SetValue(ExifTag.Software, "ImageSharp"); ExifValue value = image.Metadata.ExifProfile.GetValue(ExifTag.Software); @@ -314,7 +314,7 @@ namespace SixLabors.ImageSharp.Tests // This image contains an 802 byte EXIF profile // It has a tag with an index offset of 18,481,152 bytes (overrunning the data) - Image image = TestFile.Create(TestImages.Jpeg.Progressive.Bad.ExifUndefType).CreateImage(); + Image image = TestFile.Create(TestImages.Jpeg.Progressive.Bad.ExifUndefType).CreateRgba32Image(); Assert.NotNull(image); ExifProfile profile = image.Metadata.ExifProfile; @@ -333,7 +333,7 @@ namespace SixLabors.ImageSharp.Tests public void TestArrayValueWithUnspecifiedSize() { // This images contains array in the exif profile that has zero components. - Image image = TestFile.Create(TestImages.Jpeg.Issues.InvalidCast520).CreateImage(); + Image image = TestFile.Create(TestImages.Jpeg.Issues.InvalidCast520).CreateRgba32Image(); ExifProfile profile = image.Metadata.ExifProfile; Assert.NotNull(profile); @@ -408,7 +408,7 @@ namespace SixLabors.ImageSharp.Tests internal static ExifProfile GetExifProfile() { - Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage(); + Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateRgba32Image(); ExifProfile profile = image.Metadata.ExifProfile; Assert.NotNull(profile); diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs index 4327cae33..8d786811c 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Tests private static ExifValue GetExifValue() { ExifProfile profile; - using (Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage()) + using (Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateRgba32Image()) { profile = image.Metadata.ExifProfile; } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs index 9c3ea90d5..0c7a76081 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffCompositorTests.cs @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelBlenders public void PorterDuffOutputIsCorrect(TestImageProvider provider, PixelAlphaCompositionMode mode) { var srcFile = TestFile.Create(TestImages.Png.PDSrc); - using (Image src = srcFile.CreateImage()) + using (Image src = srcFile.CreateRgba32Image()) using (Image dest = provider.GetImage()) { GraphicsOptions options = new GraphicsOptions diff --git a/tests/ImageSharp.Tests/TestFile.cs b/tests/ImageSharp.Tests/TestFile.cs index 089249e21..6ca86ced6 100644 --- a/tests/ImageSharp.Tests/TestFile.cs +++ b/tests/ImageSharp.Tests/TestFile.cs @@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.Tests /// /// The . /// - public Image CreateImage() + public Image CreateRgba32Image() { return this.Image.Clone(); } @@ -145,9 +145,9 @@ namespace SixLabors.ImageSharp.Tests /// /// The . /// - public Image CreateImage(IImageDecoder decoder) + public Image CreateRgba32Image(IImageDecoder decoder) { - return ImageSharp.Image.Load(this.Image.GetConfiguration(), this.Bytes, decoder); + return ImageSharp.Image.Load(this.Image.GetConfiguration(), this.Bytes, decoder); } } } diff --git a/tests/ImageSharp.Tests/TestFileSystem.cs b/tests/ImageSharp.Tests/TestFileSystem.cs index 21ad4d2c1..9211e70f7 100644 --- a/tests/ImageSharp.Tests/TestFileSystem.cs +++ b/tests/ImageSharp.Tests/TestFileSystem.cs @@ -12,29 +12,24 @@ namespace SixLabors.ImageSharp.Tests /// public class TestFileSystem : ImageSharp.IO.IFileSystem { - - public static TestFileSystem Global { get; } = new TestFileSystem(); - - public static void RegisterGlobalTestFormat() - { - Configuration.Default.FileSystem = Global; - } - - Dictionary fileSystem = new Dictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary fileSystem = new Dictionary(StringComparer.OrdinalIgnoreCase); public void AddFile(string path, Stream data) { - fileSystem.Add(path, data); + lock (this.fileSystem) + { + this.fileSystem.Add(path, data); + } } public Stream Create(string path) { // if we have injected a fake file use it instead - lock (fileSystem) + lock (this.fileSystem) { - if (fileSystem.ContainsKey(path)) + if (this.fileSystem.ContainsKey(path)) { - Stream stream = fileSystem[path]; + Stream stream = this.fileSystem[path]; stream.Position = 0; return stream; } @@ -43,15 +38,14 @@ namespace SixLabors.ImageSharp.Tests return File.Create(path); } - public Stream OpenRead(string path) { // if we have injected a fake file use it instead - lock (fileSystem) + lock (this.fileSystem) { - if (fileSystem.ContainsKey(path)) + if (this.fileSystem.ContainsKey(path)) { - Stream stream = fileSystem[path]; + Stream stream = this.fileSystem[path]; stream.Position = 0; return stream; } @@ -60,5 +54,4 @@ namespace SixLabors.ImageSharp.Tests return File.OpenRead(path); } } -} - +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestFormat.cs b/tests/ImageSharp.Tests/TestFormat.cs index 91e31b356..23bd0a54c 100644 --- a/tests/ImageSharp.Tests/TestFormat.cs +++ b/tests/ImageSharp.Tests/TestFormat.cs @@ -6,6 +6,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Numerics; using System.Reflection; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.PixelFormats; @@ -18,6 +19,8 @@ namespace SixLabors.ImageSharp.Tests /// public class TestFormat : IConfigurationModule, IImageFormat { + private readonly Dictionary sampleImages = new Dictionary(); + // We should not change Configuration.Default in individual tests! // Create new configuration instances with new Configuration(TestFormat.GlobalTestFormat) instead! public static TestFormat GlobalTestFormat { get; } = new TestFormat(); @@ -49,12 +52,23 @@ namespace SixLabors.ImageSharp.Tests return ms; } - Dictionary _sampleImages = new Dictionary(); + public void VerifySpecificDecodeCall(byte[] marker, Configuration config) + where TPixel : struct, IPixel + { + DecodeOperation[] discovered = this.DecodeCalls.Where(x => x.IsMatch(marker, config, typeof(TPixel))).ToArray(); - public void VerifyDecodeCall(byte[] marker, Configuration config) + Assert.True(discovered.Any(), "No calls to decode on this formate with the proveded options happend"); + + foreach (DecodeOperation d in discovered) + { + this.DecodeCalls.Remove(d); + } + } + + public void VerifyAgnosticDecodeCall(byte[] marker, Configuration config) { - DecodeOperation[] discovered = this.DecodeCalls.Where(x => x.IsMatch(marker, config)).ToArray(); + DecodeOperation[] discovered = this.DecodeCalls.Where(x => x.IsMatch(marker, config, typeof(TestPixelForAgnosticDecode))).ToArray(); Assert.True(discovered.Any(), "No calls to decode on this formate with the proveded options happend"); @@ -68,17 +82,19 @@ namespace SixLabors.ImageSharp.Tests public Image Sample() where TPixel : struct, IPixel { - lock (this._sampleImages) + lock (this.sampleImages) { - if (!this._sampleImages.ContainsKey(typeof(TPixel))) + if (!this.sampleImages.ContainsKey(typeof(TPixel))) { - this._sampleImages.Add(typeof(TPixel), new Image(1, 1)); + this.sampleImages.Add(typeof(TPixel), new Image(1, 1)); } - return (Image)this._sampleImages[typeof(TPixel)]; + return (Image)this.sampleImages[typeof(TPixel)]; } } + public Image SampleAgnostic() => this.Sample(); + public string MimeType => "img/test"; public string Extension => "test_ext"; @@ -123,10 +139,12 @@ namespace SixLabors.ImageSharp.Tests public byte[] marker; internal Configuration config; - public bool IsMatch(byte[] testMarker, Configuration config) + public Type pixelType; + + public bool IsMatch(byte[] testMarker, Configuration config, Type pixelType) { - if (this.config != config) + if (this.config != config || this.pixelType != pixelType) { return false; } @@ -191,7 +209,8 @@ namespace SixLabors.ImageSharp.Tests this.testFormat.DecodeCalls.Add(new DecodeOperation { marker = marker, - config = config + config = config, + pixelType = typeof(TPixel) }); // TODO record this happend so we can verify it. @@ -200,7 +219,7 @@ namespace SixLabors.ImageSharp.Tests public bool IsSupportedFileFormat(Span header) => testFormat.IsSupportedFileFormat(header); - public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); + public Image Decode(Configuration configuration, Stream stream) => this.Decode(configuration, stream); } public class TestEncoder : ImageSharp.Formats.IImageEncoder @@ -221,5 +240,27 @@ namespace SixLabors.ImageSharp.Tests // TODO record this happend so we can verify it. } } + + + struct TestPixelForAgnosticDecode : IPixel + { + public PixelOperations CreatePixelOperations() => new PixelOperations(); + public void FromScaledVector4(Vector4 vector) { } + public Vector4 ToScaledVector4() => default; + public void FromVector4(Vector4 vector) { } + public Vector4 ToVector4() => default; + public void FromArgb32(Argb32 source) { } + public void FromBgra5551(Bgra5551 source) { } + public void FromBgr24(Bgr24 source) { } + public void FromBgra32(Bgra32 source) { } + public void FromGray8(Gray8 source) { } + public void FromGray16(Gray16 source) { } + public void FromRgb24(Rgb24 source) { } + public void FromRgba32(Rgba32 source) { } + public void ToRgba32(ref Rgba32 dest) { } + public void FromRgb48(Rgb48 source) { } + public void FromRgba64(Rgba64 source) { } + public bool Equals(TestPixelForAgnosticDecode other) => false; + } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceDecoderBenchmarks.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceDecoderBenchmarks.cs index 033f0866a..15213d5d3 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceDecoderBenchmarks.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/ReferenceDecoderBenchmarks.cs @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests { foreach (string testFile in testFiles) { - Image image = TestFile.Create(testFile).CreateImage(decoder); + Image image = TestFile.Create(testFile).CreateRgba32Image(decoder); image.Dispose(); } }, From fcaaa6fa39b90faec08f5ef81852e732f7df7f54 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 21:19:35 +0200 Subject: [PATCH 135/223] full coverage for Image.Load (I hope) --- .../Image/ImageTests.Load_FileSystemPath.cs | 83 -------------- ...d_FileSystemPath_PassLocalConfiguration.cs | 100 +++++++++++++++++ ..._FileSystemPath_UseDefaultConfiguration.cs | 103 ++++++++++++++++++ ...s.Load_FromBytes_UseGlobalConfiguration.cs | 4 +- ...Load_FromStream_UseDefaultConfiguration.cs | 60 +++++----- .../ImageSharp.Tests/ImageSharp.Tests.csproj | 3 +- 6 files changed, 234 insertions(+), 119 deletions(-) delete mode 100644 tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath.cs create mode 100644 tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_PassLocalConfiguration.cs create mode 100644 tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_UseDefaultConfiguration.cs diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath.cs deleted file mode 100644 index d6fe43897..000000000 --- a/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.PixelFormats; -using Xunit; -// ReSharper disable InconsistentNaming - -namespace SixLabors.ImageSharp.Tests -{ - using Moq; - - using SixLabors.ImageSharp.IO; - - public partial class ImageTests - { - public class Load_FileSystemPath : ImageLoadTestBase - { - [Fact] - public void BasicCase() - { - var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath); - - Assert.NotNull(img); - - this.TestFormat.VerifySpecificDecodeCall(this.Marker, this.TopLevelConfiguration); - } - - [Fact] - public void UseLocalConfiguration() - { - var img = Image.Load(this.LocalConfiguration, this.MockFilePath); - - Assert.NotNull(img); - - this.localDecoder.Verify(x => x.Decode(this.LocalConfiguration, this.DataStream)); - } - - [Fact] - public void UseCustomDecoder() - { - var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath, this.localDecoder.Object); - - Assert.NotNull(img); - this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, this.DataStream)); - } - - - [Fact] - public void UseGlobalConfigration() - { - var file = TestFile.Create(TestImages.Bmp.Car); - using (var image = Image.Load(file.FullPath)) - { - Assert.Equal(600, image.Width); - Assert.Equal(450, image.Height); - } - } - - [Fact] - public void WhenFileNotFound_Throws() - { - System.IO.FileNotFoundException ex = Assert.Throws( - () => - { - Image.Load(Guid.NewGuid().ToString()); - }); - } - - [Fact] - public void WhenPathIsNull_Throws() - { - ArgumentNullException ex = Assert.Throws( - () => - { - Image.Load((string)null); - }); - } - } - - - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_PassLocalConfiguration.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_PassLocalConfiguration.cs new file mode 100644 index 000000000..92159f0c9 --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_PassLocalConfiguration.cs @@ -0,0 +1,100 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ImageTests + { + public class Load_FileSystemPath_PassLocalConfiguration : ImageLoadTestBase + { + [Fact] + public void Configuration_Path_Specific() + { + var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat.Sample(), img); + + this.TestFormat.VerifySpecificDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Fact] + public void Configuration_Path_Agnostic() + { + var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat.SampleAgnostic(), img); + + this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Fact] + public void Configuration_Path_Decoder_Specific() + { + var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath, this.localDecoder.Object); + + Assert.NotNull(img); + this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, this.DataStream)); + } + + [Fact] + public void Configuration_Path_Decoder_Agnostic() + { + var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath, this.localDecoder.Object); + + Assert.NotNull(img); + this.localDecoder.Verify(x => x.Decode(this.TopLevelConfiguration, this.DataStream)); + } + + [Fact] + public void Configuration_Path_OutFormat_Specific() + { + var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath, out IImageFormat format); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat, format); + + this.TestFormat.VerifySpecificDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Fact] + public void Configuration_Path_OutFormat_Agnostic() + { + var img = Image.Load(this.TopLevelConfiguration, this.MockFilePath, out IImageFormat format); + + Assert.NotNull(img); + Assert.Equal(this.TestFormat, format); + + this.TestFormat.VerifyAgnosticDecodeCall(this.Marker, this.TopLevelConfiguration); + } + + [Fact] + public void WhenFileNotFound_Throws() + { + System.IO.FileNotFoundException ex = Assert.Throws( + () => + { + Image.Load(this.TopLevelConfiguration, Guid.NewGuid().ToString()); + }); + } + + [Fact] + public void WhenPathIsNull_Throws() + { + ArgumentNullException ex = Assert.Throws( + () => + { + Image.Load(this.TopLevelConfiguration,(string)null); + }); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_UseDefaultConfiguration.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_UseDefaultConfiguration.cs new file mode 100644 index 000000000..19cf7ee64 --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FileSystemPath_UseDefaultConfiguration.cs @@ -0,0 +1,103 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ImageTests + { + public class Load_FileSystemPath_UseDefaultConfiguration + { + private string Path { get; } = TestFile.GetInputFileFullPath(TestImages.Bmp.Bit8); + + private static void VerifyDecodedImage(Image img) + { + Assert.Equal(new Size(127, 64), img.Size()); + } + + [Fact] + public void Path_Specific() + { + using (var img = Image.Load(this.Path)) + { + VerifyDecodedImage(img); + } + } + + [Fact] + public void Path_Agnostic() + { + using (var img = Image.Load(this.Path)) + { + VerifyDecodedImage(img); + } + } + + + [Fact] + public void Path_Decoder_Specific() + { + using (var img = Image.Load(this.Path, new BmpDecoder())) + { + VerifyDecodedImage(img); + } + } + + [Fact] + public void Path_Decoder_Agnostic() + { + using (var img = Image.Load(this.Path, new BmpDecoder())) + { + VerifyDecodedImage(img); + } + } + + [Fact] + public void Path_OutFormat_Specific() + { + using (var img = Image.Load(this.Path, out IImageFormat format)) + { + VerifyDecodedImage(img); + Assert.IsType(format); + } + } + + [Fact] + public void Path_OutFormat_Agnostic() + { + using (var img = Image.Load(this.Path, out IImageFormat format)) + { + VerifyDecodedImage(img); + Assert.IsType(format); + } + } + [Fact] + public void WhenFileNotFound_Throws() + { + System.IO.FileNotFoundException ex = Assert.Throws( + () => + { + Image.Load(Guid.NewGuid().ToString()); + }); + } + + [Fact] + public void WhenPathIsNull_Throws() + { + ArgumentNullException ex = Assert.Throws( + () => + { + Image.Load((string)null); + }); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs index 23c25d9db..67b19a086 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromBytes_UseGlobalConfiguration.cs @@ -17,13 +17,13 @@ namespace SixLabors.ImageSharp.Tests { public class Load_FromBytes_UseGlobalConfiguration { - private static byte[] ByteArray { get; } = TestFile.Create(TestImages.Bmp.F).Bytes; + private static byte[] ByteArray { get; } = TestFile.Create(TestImages.Bmp.Bit8).Bytes; private static Span ByteSpan => new Span(ByteArray); private static void VerifyDecodedImage(Image img) { - Assert.Equal(new Size(108, 202), img.Size()); + Assert.Equal(new Size(127, 64), img.Size()); } [Theory] diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs index 27aba42ea..980ed17ce 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_UseDefaultConfiguration.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.IO; using SixLabors.ImageSharp.Formats; @@ -14,42 +15,41 @@ namespace SixLabors.ImageSharp.Tests { public partial class ImageTests { - public class Load_FromStream_UseDefaultConfiguration + public class Load_FromStream_UseDefaultConfiguration : IDisposable { + private static readonly byte[] Data = TestFile.Create(TestImages.Bmp.Bit8).Bytes; + + private MemoryStream Stream { get; } = new MemoryStream(Data); + + private static void VerifyDecodedImage(Image img) + { + Assert.Equal(new Size(127, 64), img.Size()); + } + [Fact] public void Stream_Specific() { - byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; - - using (var stream = new MemoryStream(data)) - using (var img = Image.Load(stream)) + using (var img = Image.Load(this.Stream)) { - Assert.Equal(new Size(108, 202), img.Size()); + VerifyDecodedImage(img); } } [Fact] public void Stream_Agnostic() { - byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; - - using (var stream = new MemoryStream(data)) - using (var img = Image.Load(stream)) + using (var img = Image.Load(this.Stream)) { - Assert.Equal(new Size(108, 202), img.Size()); + VerifyDecodedImage(img); } } [Fact] public void Stream_OutFormat_Specific() { - byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; - - - using (var stream = new MemoryStream(data)) - using (var img = Image.Load(stream, out IImageFormat format)) + using (var img = Image.Load(this.Stream, out IImageFormat format)) { - Assert.Equal(new Size(108, 202), img.Size()); + VerifyDecodedImage(img); Assert.IsType(format); } } @@ -57,39 +57,35 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void Stream_Decoder_Specific() { - byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; - - using (var stream = new MemoryStream(data)) - using (var img = Image.Load(stream, new BmpDecoder())) + using (var img = Image.Load(this.Stream, new BmpDecoder())) { - Assert.Equal(new Size(108, 202), img.Size()); + VerifyDecodedImage(img); } } [Fact] public void Stream_Decoder_Agnostic() { - byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; - - using (var stream = new MemoryStream(data)) - using (var img = Image.Load(stream, new BmpDecoder())) + using (var img = Image.Load(this.Stream, new BmpDecoder())) { - Assert.Equal(new Size(108, 202), img.Size()); + VerifyDecodedImage(img); } } [Fact] public void Stream_OutFormat_Agnostic() { - byte[] data = TestFile.Create(TestImages.Bmp.F).Bytes; - - using (var stream = new MemoryStream(data)) - using (var img = Image.Load(stream, out IImageFormat format)) + using (var img = Image.Load(this.Stream, out IImageFormat format)) { - Assert.Equal(new Size(108, 202), img.Size()); + VerifyDecodedImage(img); Assert.IsType(format); } } + + public void Dispose() + { + this.Stream?.Dispose(); + } } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index efdf89964..0b727f30c 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,7 +1,6 @@  - - netcoreapp2.1 + netcoreapp2.1;net462;net472 True latest full From 143946e37f48fd9e7a835d3c697c3ebccc184142 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 21:32:54 +0200 Subject: [PATCH 136/223] fix changes applied by mistake --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 2 +- src/ImageSharp/ImageSharp.csproj | 2 +- .../Processing/Processors/Dithering/DitherTests.cs | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index ac5d7fdea..915915f6c 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -10,8 +10,8 @@ $(packageversion) 0.0.1 + netcoreapp2.1;netstandard1.3;netstandard2.0 - netstandard2.0 7.3 true diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index e763b8ef1..d734648f4 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -10,7 +10,7 @@ $(packageversion) 0.0.1 - + netcoreapp2.1;netstandard1.3;netstandard2.0;net472 true diff --git a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs index 91422faaa..cb901c2a8 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs @@ -50,7 +50,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization /// The output is visually correct old 32bit runtime, /// but it is very different because of floating point inaccuracies. /// - private static readonly bool SkipAllDitherTests = false; + private static readonly bool SkipAllDitherTests = + !TestEnvironment.Is64BitProcess && string.IsNullOrEmpty(TestEnvironment.NetCoreVersion); [Theory] [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] From c21c8ba86224ffe42cfdfe99b779076a21d52fac Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 22:13:29 +0200 Subject: [PATCH 137/223] Fix docs for processing extensions --- .../Processing/AutoOrientExtensions.cs | 3 ++- .../Processing/BackgroundColorExtensions.cs | 3 ++- .../Processing/BinaryDiffuseExtensions.cs | 11 ++++---- .../Processing/BinaryDitherExtensions.cs | 11 ++++---- .../Processing/BinaryThresholdExtensions.cs | 11 ++++---- .../Processing/BlackWhiteExtensions.cs | 7 ++--- .../Processing/BoxBlurExtensions.cs | 9 ++++--- .../Processing/BrightnessExtensions.cs | 7 ++--- .../Processing/ColorBlindnessExtensions.cs | 8 +++--- .../Processing/ContrastExtensions.cs | 8 +++--- src/ImageSharp/Processing/CropExtensions.cs | 7 ++--- .../Processing/DetectEdgesExtensions.cs | 16 +++++------ .../Processing/DiffuseExtensions.cs | 15 ++++++----- src/ImageSharp/Processing/DitherExtensions.cs | 13 ++++----- .../Processing/EntropyCropExtensions.cs | 7 ++--- src/ImageSharp/Processing/FilterExtensions.cs | 7 ++--- src/ImageSharp/Processing/FlipExtensions.cs | 5 ++-- .../Processing/GaussianBlurExtensions.cs | 9 ++++--- .../Processing/GaussianSharpenExtensions.cs | 9 ++++--- src/ImageSharp/Processing/GlowExtensions.cs | 27 ++++++++++--------- .../Processing/GrayscaleExtensions.cs | 3 ++- .../HistogramEqualizationExtension.cs | 6 ++--- src/ImageSharp/Processing/HueExtensions.cs | 7 ++--- src/ImageSharp/Processing/InvertExtensions.cs | 7 ++--- .../Processing/KodachromeExtensions.cs | 7 ++--- .../Processing/LomographExtensions.cs | 7 ++--- .../Processing/OilPaintExtensions.cs | 11 ++++---- .../Processing/OpacityExtensions.cs | 7 ++--- src/ImageSharp/Processing/PadExtensions.cs | 5 ++-- .../Processing/PixelateExtensions.cs | 9 ++++--- .../Processing/PolaroidExtensions.cs | 7 ++--- .../Processing/QuantizeExtensions.cs | 7 ++--- src/ImageSharp/Processing/ResizeExtensions.cs | 23 ++++++++-------- src/ImageSharp/Processing/RotateExtensions.cs | 9 ++++--- .../Processing/RotateFlipExtensions.cs | 5 ++-- .../Processing/SaturateExtensions.cs | 7 ++--- src/ImageSharp/Processing/SepiaExtensions.cs | 11 ++++---- src/ImageSharp/Processing/SkewExtensions.cs | 7 ++--- .../Processing/TransformExtensions.cs | 17 ++++++------ .../Processing/VignetteExtensions.cs | 23 ++++++++-------- 40 files changed, 207 insertions(+), 171 deletions(-) diff --git a/src/ImageSharp/Processing/AutoOrientExtensions.cs b/src/ImageSharp/Processing/AutoOrientExtensions.cs index d11fc9623..d065d4583 100644 --- a/src/ImageSharp/Processing/AutoOrientExtensions.cs +++ b/src/ImageSharp/Processing/AutoOrientExtensions.cs @@ -7,7 +7,8 @@ using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of auto-orientation operations to the type. + /// Defines extensions that allow the application of auto-orientation operations to an + /// using Mutate/Clone. /// public static class AutoOrientExtensions { diff --git a/src/ImageSharp/Processing/BackgroundColorExtensions.cs b/src/ImageSharp/Processing/BackgroundColorExtensions.cs index 1ad2c9237..3b794e335 100644 --- a/src/ImageSharp/Processing/BackgroundColorExtensions.cs +++ b/src/ImageSharp/Processing/BackgroundColorExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of a background color to the type. + /// Defines extension methods to replace the background color of an + /// using Mutate/Clone. /// public static class BackgroundColorExtensions { diff --git a/src/ImageSharp/Processing/BinaryDiffuseExtensions.cs b/src/ImageSharp/Processing/BinaryDiffuseExtensions.cs index 788942dde..487b64e1c 100644 --- a/src/ImageSharp/Processing/BinaryDiffuseExtensions.cs +++ b/src/ImageSharp/Processing/BinaryDiffuseExtensions.cs @@ -9,7 +9,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds binary diffusion extensions to the type. + /// Defines extension methods to apply binary diffusion on an + /// using Mutate/Clone. /// public static class BinaryDiffuseExtensions { @@ -20,7 +21,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDiffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold)); @@ -35,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDiffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold), rectangle); @@ -49,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDiffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, TPixel upperColor, TPixel lowerColor) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold, upperColor, lowerColor)); @@ -66,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDiffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, TPixel upperColor, TPixel lowerColor, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold, upperColor, lowerColor), rectangle); diff --git a/src/ImageSharp/Processing/BinaryDitherExtensions.cs b/src/ImageSharp/Processing/BinaryDitherExtensions.cs index 617770196..d8843dafa 100644 --- a/src/ImageSharp/Processing/BinaryDitherExtensions.cs +++ b/src/ImageSharp/Processing/BinaryDitherExtensions.cs @@ -9,7 +9,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds binary dithering extensions to the type. + /// Defines extensions to apply binary dithering on an + /// using Mutate/Clone. /// public static class BinaryDitherExtensions { @@ -19,7 +20,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image this method extends. /// The ordered ditherer. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDither(this IImageProcessingContext source, IOrderedDither dither) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither)); @@ -32,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing /// The ordered ditherer. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDither(this IImageProcessingContext source, IOrderedDither dither, TPixel upperColor, TPixel lowerColor) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither, upperColor, lowerColor)); @@ -46,7 +47,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDither(this IImageProcessingContext source, IOrderedDither dither, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither), rectangle); @@ -62,7 +63,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDither(this IImageProcessingContext source, IOrderedDither dither, TPixel upperColor, TPixel lowerColor, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither, upperColor, lowerColor), rectangle); diff --git a/src/ImageSharp/Processing/BinaryThresholdExtensions.cs b/src/ImageSharp/Processing/BinaryThresholdExtensions.cs index 31f81ba4b..aecb78484 100644 --- a/src/ImageSharp/Processing/BinaryThresholdExtensions.cs +++ b/src/ImageSharp/Processing/BinaryThresholdExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds binary thresholding extensions to the type. + /// Defines extension methods to apply binary thresholding on an + /// using Mutate/Clone. /// public static class BinaryThresholdExtensions { @@ -18,7 +19,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryThresholdProcessor(threshold)); @@ -32,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryThresholdProcessor(threshold), rectangle); @@ -45,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold, TPixel upperColor, TPixel lowerColor) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor)); @@ -61,7 +62,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold, TPixel upperColor, TPixel lowerColor, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor), rectangle); diff --git a/src/ImageSharp/Processing/BlackWhiteExtensions.cs b/src/ImageSharp/Processing/BlackWhiteExtensions.cs index 5dc2341e5..ee34cd99e 100644 --- a/src/ImageSharp/Processing/BlackWhiteExtensions.cs +++ b/src/ImageSharp/Processing/BlackWhiteExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of black and white toning to the type. + /// Defines extension methods that allow the application of black and white toning to an + /// using Mutate/Clone. /// public static class BlackWhiteExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// Applies black and white toning to the image. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BlackWhite(this IImageProcessingContext source) => source.ApplyProcessor(new BlackWhiteProcessor()); @@ -27,7 +28,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BlackWhite(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new BlackWhiteProcessor(), rectangle); } diff --git a/src/ImageSharp/Processing/BoxBlurExtensions.cs b/src/ImageSharp/Processing/BoxBlurExtensions.cs index bc6e06dd6..f3400c24e 100644 --- a/src/ImageSharp/Processing/BoxBlurExtensions.cs +++ b/src/ImageSharp/Processing/BoxBlurExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds box blurring extensions to the type. + /// Defines extensions methods to apply box blurring to an + /// using Mutate/Clone. /// public static class BoxBlurExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// Applies a box blur to the image. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BoxBlur(this IImageProcessingContext source) => source.ApplyProcessor(new BoxBlurProcessor()); @@ -25,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The 'radius' value representing the size of the area to sample. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BoxBlur(this IImageProcessingContext source, int radius) => source.ApplyProcessor(new BoxBlurProcessor(radius)); @@ -37,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext BoxBlur(this IImageProcessingContext source, int radius, Rectangle rectangle) => source.ApplyProcessor(new BoxBlurProcessor(radius), rectangle); } diff --git a/src/ImageSharp/Processing/BrightnessExtensions.cs b/src/ImageSharp/Processing/BrightnessExtensions.cs index 4de4dc897..db8409176 100644 --- a/src/ImageSharp/Processing/BrightnessExtensions.cs +++ b/src/ImageSharp/Processing/BrightnessExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the alteration of the brightness component to the type. + /// Defines extensions that allow the alteration of the brightness component of an + /// using Mutate/Clone. /// public static class BrightnessExtensions { @@ -21,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The proportion of the conversion. Must be greater than or equal to 0. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Brightness(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new BrightnessProcessor(amount)); @@ -37,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Brightness(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new BrightnessProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/ColorBlindnessExtensions.cs b/src/ImageSharp/Processing/ColorBlindnessExtensions.cs index 000d47bd3..b8d503955 100644 --- a/src/ImageSharp/Processing/ColorBlindnessExtensions.cs +++ b/src/ImageSharp/Processing/ColorBlindnessExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; using SixLabors.ImageSharp.Processing.Processors.Filters; using SixLabors.Primitives; @@ -9,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that simulate the effects of various color blindness disorders to the type. + /// Defines extensions that simulate the effects of various color blindness disorders on an + /// using Mutate/Clone. /// public static class ColorBlindnessExtensions { @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The type of color blindness simulator to apply. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext ColorBlindness(this IImageProcessingContext source, ColorBlindnessMode colorBlindness) => source.ApplyProcessor(GetProcessor(colorBlindness)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext ColorBlindness(this IImageProcessingContext source, ColorBlindnessMode colorBlindnessMode, Rectangle rectangle) => source.ApplyProcessor(GetProcessor(colorBlindnessMode), rectangle); diff --git a/src/ImageSharp/Processing/ContrastExtensions.cs b/src/ImageSharp/Processing/ContrastExtensions.cs index b03844d93..bdfd7c98a 100644 --- a/src/ImageSharp/Processing/ContrastExtensions.cs +++ b/src/ImageSharp/Processing/ContrastExtensions.cs @@ -1,14 +1,14 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Filters; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the alteration of the contrast component to the type. + /// Defines extensions that allow the alteration of the contrast component of an + /// using Mutate/Clone. /// public static class ContrastExtensions { @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The proportion of the conversion. Must be greater than or equal to 0. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Contrast(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new ContrastProcessor(amount)); @@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Contrast(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new ContrastProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/CropExtensions.cs b/src/ImageSharp/Processing/CropExtensions.cs index 6aaff5656..7ec85169e 100644 --- a/src/ImageSharp/Processing/CropExtensions.cs +++ b/src/ImageSharp/Processing/CropExtensions.cs @@ -7,7 +7,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of cropping operations to the type. + /// Defines extensions that allow the application of cropping operations on an + /// using Mutate/Clone. /// public static class CropExtensions { @@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.Processing /// The image to resize. /// The target image width. /// The target image height. - /// The + /// The to allow chaining of operations. public static IImageProcessingContext Crop(this IImageProcessingContext source, int width, int height) => Crop(source, new Rectangle(0, 0, width, height)); @@ -28,7 +29,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to retain. /// - /// The + /// The to allow chaining of operations. public static IImageProcessingContext Crop(this IImageProcessingContext source, Rectangle cropRectangle) => source.ApplyProcessor(new CropProcessor(cropRectangle, source.GetCurrentSize())); } diff --git a/src/ImageSharp/Processing/DetectEdgesExtensions.cs b/src/ImageSharp/Processing/DetectEdgesExtensions.cs index 7527d601d..837b26910 100644 --- a/src/ImageSharp/Processing/DetectEdgesExtensions.cs +++ b/src/ImageSharp/Processing/DetectEdgesExtensions.cs @@ -8,7 +8,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds edge detection extensions to the type. + /// Defines edge detection extensions applicable on an using Mutate/Clone. /// public static class DetectEdgesExtensions { @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// operating in grayscale mode. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext DetectEdges(this IImageProcessingContext source) => DetectEdges(source, new SobelProcessor(true)); @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext DetectEdges(this IImageProcessingContext source, Rectangle rectangle) => DetectEdges(source, rectangle, new SobelProcessor(true)); @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The filter for detecting edges. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectionOperators filter) => @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The filter for detecting edges. /// Whether to convert the image to grayscale first. Defaults to true. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectionOperators filter, @@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// Whether to convert the image to grayscale first. Defaults to true. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectionOperators filter, @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The filter for detecting edges. - /// The . + /// The to allow chaining of operations. private static IImageProcessingContext DetectEdges(this IImageProcessingContext source, IImageProcessor filter) { return source.ApplyProcessor(filter); @@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The filter for detecting edges. - /// The . + /// The to allow chaining of operations. private static IImageProcessingContext DetectEdges( this IImageProcessingContext source, Rectangle rectangle, diff --git a/src/ImageSharp/Processing/DiffuseExtensions.cs b/src/ImageSharp/Processing/DiffuseExtensions.cs index 768d28116..4668363e9 100644 --- a/src/ImageSharp/Processing/DiffuseExtensions.cs +++ b/src/ImageSharp/Processing/DiffuseExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Dithering { /// - /// Adds diffusion extensions to the type. + /// Defines extension methods to apply diffusion to an + /// using Mutate/Clone. /// public static class DiffuseExtensions { @@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.Processing.Dithering /// /// The pixel format. /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Diffuse(this IImageProcessingContext source) where TPixel : struct, IPixel => Diffuse(source, KnownDiffusers.FloydSteinberg, .5F); @@ -28,7 +29,7 @@ namespace SixLabors.ImageSharp.Processing.Dithering /// The pixel format. /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Diffuse(this IImageProcessingContext source, float threshold) where TPixel : struct, IPixel => Diffuse(source, KnownDiffusers.FloydSteinberg, threshold); @@ -40,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Dithering /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Diffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold) where TPixel : struct, IPixel => source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold)); @@ -55,7 +56,7 @@ namespace SixLabors.ImageSharp.Processing.Dithering /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Diffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold), rectangle); @@ -68,7 +69,7 @@ namespace SixLabors.ImageSharp.Processing.Dithering /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The palette to select substitute colors from. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Diffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, TPixel[] palette) where TPixel : struct, IPixel => source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold, palette)); @@ -84,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Dithering /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Diffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, TPixel[] palette, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold, palette), rectangle); diff --git a/src/ImageSharp/Processing/DitherExtensions.cs b/src/ImageSharp/Processing/DitherExtensions.cs index 795561e70..aeb975d1c 100644 --- a/src/ImageSharp/Processing/DitherExtensions.cs +++ b/src/ImageSharp/Processing/DitherExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds dithering extensions to the type. + /// Defines dithering extensions to apply on an + /// using Mutate/Clone. /// public static class DitherExtensions { @@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The pixel format. /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Dither(this IImageProcessingContext source) where TPixel : struct, IPixel => Dither(source, KnownDitherers.BayerDither4x4); @@ -28,7 +29,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image this method extends. /// The ordered ditherer. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Dither(this IImageProcessingContext source, IOrderedDither dither) where TPixel : struct, IPixel => source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither)); @@ -40,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The ordered ditherer. /// The palette to select substitute colors from. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Dither(this IImageProcessingContext source, IOrderedDither dither, TPixel[] palette) where TPixel : struct, IPixel => source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither, palette)); @@ -54,7 +55,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Dither(this IImageProcessingContext source, IOrderedDither dither, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither), rectangle); @@ -69,7 +70,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Dither(this IImageProcessingContext source, IOrderedDither dither, TPixel[] palette, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither, palette), rectangle); diff --git a/src/ImageSharp/Processing/EntropyCropExtensions.cs b/src/ImageSharp/Processing/EntropyCropExtensions.cs index 34bc5daeb..de5296d83 100644 --- a/src/ImageSharp/Processing/EntropyCropExtensions.cs +++ b/src/ImageSharp/Processing/EntropyCropExtensions.cs @@ -6,7 +6,8 @@ using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of entropy cropping operations to the type. + /// Defines extensions that allow the application of entropy cropping operations on an + /// using Mutate/Clone. /// public static class EntropyCropExtensions { @@ -14,7 +15,7 @@ namespace SixLabors.ImageSharp.Processing /// Crops an image to the area of greatest entropy using a threshold for entropic density of .5F. /// /// The image to crop. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext EntropyCrop(this IImageProcessingContext source) => source.ApplyProcessor(new EntropyCropProcessor()); @@ -23,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image to crop. /// The threshold for entropic density. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext EntropyCrop(this IImageProcessingContext source, float threshold) => source.ApplyProcessor(new EntropyCropProcessor(threshold)); } diff --git a/src/ImageSharp/Processing/FilterExtensions.cs b/src/ImageSharp/Processing/FilterExtensions.cs index 2a1c6bc7f..5a66502ce 100644 --- a/src/ImageSharp/Processing/FilterExtensions.cs +++ b/src/ImageSharp/Processing/FilterExtensions.cs @@ -9,7 +9,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of composable filters to the type. + /// Defines extensions that allow the application of composable filters to an + /// using Mutate/Clone. /// public static class FilterExtensions { @@ -18,7 +19,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The filter color matrix - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Filter(this IImageProcessingContext source, ColorMatrix matrix) => source.ApplyProcessor(new FilterProcessor(matrix)); @@ -30,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Filter(this IImageProcessingContext source, ColorMatrix matrix, Rectangle rectangle) => source.ApplyProcessor(new FilterProcessor(matrix), rectangle); } diff --git a/src/ImageSharp/Processing/FlipExtensions.cs b/src/ImageSharp/Processing/FlipExtensions.cs index bc862972e..f6b3c0c37 100644 --- a/src/ImageSharp/Processing/FlipExtensions.cs +++ b/src/ImageSharp/Processing/FlipExtensions.cs @@ -6,7 +6,8 @@ using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of flipping operations to the type. + /// Defines extensions that allow the application of flipping operations on an + /// using Mutate/Clone. /// public static class FlipExtensions { @@ -15,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image to rotate, flip, or both. /// The to perform the flip. - /// The + /// The to allow chaining of operations. public static IImageProcessingContext Flip(this IImageProcessingContext source, FlipMode flipMode) => source.ApplyProcessor(new FlipProcessor(flipMode)); } diff --git a/src/ImageSharp/Processing/GaussianBlurExtensions.cs b/src/ImageSharp/Processing/GaussianBlurExtensions.cs index 1dab05457..e527a14b7 100644 --- a/src/ImageSharp/Processing/GaussianBlurExtensions.cs +++ b/src/ImageSharp/Processing/GaussianBlurExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds Gaussian blurring extensions to the type. + /// Defines Gaussian blurring extensions to apply on an + /// using Mutate/Clone. /// public static class GaussianBlurExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// Applies a Gaussian blur to the image. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source) => source.ApplyProcessor(new GaussianBlurProcessor()); @@ -25,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The 'sigma' value representing the weight of the blur. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source, float sigma) => source.ApplyProcessor(new GaussianBlurProcessor(sigma)); @@ -37,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source, float sigma, Rectangle rectangle) => source.ApplyProcessor(new GaussianBlurProcessor(sigma), rectangle); } diff --git a/src/ImageSharp/Processing/GaussianSharpenExtensions.cs b/src/ImageSharp/Processing/GaussianSharpenExtensions.cs index 64aa7b5db..79f4a0cc3 100644 --- a/src/ImageSharp/Processing/GaussianSharpenExtensions.cs +++ b/src/ImageSharp/Processing/GaussianSharpenExtensions.cs @@ -7,7 +7,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds Gaussian sharpening extensions to the type. + /// Defines Gaussian sharpening extensions to apply on an + /// using Mutate/Clone. /// public static class GaussianSharpenExtensions { @@ -15,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing /// Applies a Gaussian sharpening filter to the image. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source) => source.ApplyProcessor(new GaussianSharpenProcessor()); @@ -24,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The 'sigma' value representing the weight of the blur. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source, float sigma) => source.ApplyProcessor(new GaussianSharpenProcessor(sigma)); @@ -36,7 +37,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext GaussianSharpen( this IImageProcessingContext source, float sigma, diff --git a/src/ImageSharp/Processing/GlowExtensions.cs b/src/ImageSharp/Processing/GlowExtensions.cs index 8b6e8ffc2..759fdccbe 100644 --- a/src/ImageSharp/Processing/GlowExtensions.cs +++ b/src/ImageSharp/Processing/GlowExtensions.cs @@ -9,7 +9,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of a radial glow to the type. + /// Defines extensions that allow the application of a radial glow on an + /// using Mutate/Clone. /// public static class GlowExtensions { @@ -18,7 +19,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The pixel format. /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Glow(this IImageProcessingContext source) where TPixel : struct, IPixel => Glow(source, GraphicsOptions.Default); @@ -29,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image this method extends. /// The color to set as the glow. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Glow(this IImageProcessingContext source, TPixel color) where TPixel : struct, IPixel { @@ -42,7 +43,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image this method extends. /// The the radius. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Glow(this IImageProcessingContext source, float radius) where TPixel : struct, IPixel => Glow(source, GraphicsOptions.Default, radius); @@ -55,7 +56,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Glow(this IImageProcessingContext source, Rectangle rectangle) where TPixel : struct, IPixel => source.Glow(GraphicsOptions.Default, rectangle); @@ -70,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Glow(this IImageProcessingContext source, TPixel color, float radius, Rectangle rectangle) where TPixel : struct, IPixel => source.Glow(GraphicsOptions.Default, color, ValueSize.Absolute(radius), rectangle); @@ -81,7 +82,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image this method extends. /// The options effecting things like blending. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options) where TPixel : struct, IPixel => source.Glow(options, NamedColors.Black, ValueSize.PercentageOfWidth(0.5f)); @@ -93,7 +94,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The options effecting things like blending. /// The color to set as the glow. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, TPixel color) where TPixel : struct, IPixel => source.Glow(options, color, ValueSize.PercentageOfWidth(0.5f)); @@ -105,7 +106,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The options effecting things like blending. /// The the radius. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, float radius) where TPixel : struct, IPixel => source.Glow(options, NamedColors.Black, ValueSize.Absolute(radius)); @@ -119,7 +120,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, Rectangle rectangle) where TPixel : struct, IPixel => source.Glow(options, NamedColors.Black, ValueSize.PercentageOfWidth(0.5f), rectangle); @@ -135,7 +136,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float radius, Rectangle rectangle) where TPixel : struct, IPixel => source.Glow(options, color, ValueSize.Absolute(radius), rectangle); @@ -151,7 +152,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. private static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, TPixel color, ValueSize radius, Rectangle rectangle) where TPixel : struct, IPixel => source.ApplyProcessor(new GlowProcessor(color, radius, options), rectangle); @@ -164,7 +165,7 @@ namespace SixLabors.ImageSharp.Processing /// The options effecting things like blending. /// The color to set as the glow. /// The the radius. - /// The . + /// The to allow chaining of operations. private static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, TPixel color, ValueSize radius) where TPixel : struct, IPixel => source.ApplyProcessor(new GlowProcessor(color, radius, options)); diff --git a/src/ImageSharp/Processing/GrayscaleExtensions.cs b/src/ImageSharp/Processing/GrayscaleExtensions.cs index d68a385e4..a87341025 100644 --- a/src/ImageSharp/Processing/GrayscaleExtensions.cs +++ b/src/ImageSharp/Processing/GrayscaleExtensions.cs @@ -9,7 +9,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of grayscale toning to the type. + /// Defines extensions that allow the application of grayscale toning to an + /// using Mutate/Clone. /// public static class GrayscaleExtensions { diff --git a/src/ImageSharp/Processing/HistogramEqualizationExtension.cs b/src/ImageSharp/Processing/HistogramEqualizationExtension.cs index aae3e997f..01c14fc09 100644 --- a/src/ImageSharp/Processing/HistogramEqualizationExtension.cs +++ b/src/ImageSharp/Processing/HistogramEqualizationExtension.cs @@ -6,7 +6,7 @@ using SixLabors.ImageSharp.Processing.Processors.Normalization; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extension that allow the adjustment of the contrast of an image via its histogram. + /// Defines extension that allow the adjustment of the contrast of an image via its histogram. /// public static class HistogramEqualizationExtension { @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Processing /// Equalizes the histogram of an image to increases the contrast. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext HistogramEqualization(this IImageProcessingContext source) => HistogramEqualization(source, HistogramEqualizationOptions.Default); @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The histogram equalization options to use. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext HistogramEqualization( this IImageProcessingContext source, HistogramEqualizationOptions options) => diff --git a/src/ImageSharp/Processing/HueExtensions.cs b/src/ImageSharp/Processing/HueExtensions.cs index 17296e1db..3c1239da6 100644 --- a/src/ImageSharp/Processing/HueExtensions.cs +++ b/src/ImageSharp/Processing/HueExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the alteration of the hue component to the type. + /// Defines extensions that allow the alteration of the hue component of an + /// using Mutate/Clone. /// public static class HueExtensions { @@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The rotation angle in degrees to adjust the hue. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Hue(this IImageProcessingContext source, float degrees) => source.ApplyProcessor(new HueProcessor(degrees)); @@ -29,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Hue(this IImageProcessingContext source, float degrees, Rectangle rectangle) => source.ApplyProcessor(new HueProcessor(degrees), rectangle); } diff --git a/src/ImageSharp/Processing/InvertExtensions.cs b/src/ImageSharp/Processing/InvertExtensions.cs index 828aaa1bb..c45f24c2e 100644 --- a/src/ImageSharp/Processing/InvertExtensions.cs +++ b/src/ImageSharp/Processing/InvertExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the inversion of colors to the type. + /// Defines extensions that allow the inversion of colors of an + /// using Mutate/Clone. /// public static class InvertExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// Inverts the colors of the image. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Invert(this IImageProcessingContext source) => source.ApplyProcessor(new InvertProcessor(1F)); @@ -27,7 +28,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Invert(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new InvertProcessor(1F), rectangle); } diff --git a/src/ImageSharp/Processing/KodachromeExtensions.cs b/src/ImageSharp/Processing/KodachromeExtensions.cs index 24bd51e01..810094a18 100644 --- a/src/ImageSharp/Processing/KodachromeExtensions.cs +++ b/src/ImageSharp/Processing/KodachromeExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the recreation of an old Kodachrome camera effect to the type. + /// Defines extensions that allow the recreation of an old Kodachrome camera effect on an + /// using Mutate/Clone. /// public static class KodachromeExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// Alters the colors of the image recreating an old Kodachrome camera effect. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Kodachrome(this IImageProcessingContext source) => source.ApplyProcessor(new KodachromeProcessor()); @@ -27,7 +28,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Kodachrome(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new KodachromeProcessor(), rectangle); } diff --git a/src/ImageSharp/Processing/LomographExtensions.cs b/src/ImageSharp/Processing/LomographExtensions.cs index a3fd3d3b5..dd7ab21ec 100644 --- a/src/ImageSharp/Processing/LomographExtensions.cs +++ b/src/ImageSharp/Processing/LomographExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the recreation of an old Lomograph camera effect to the type. + /// Defines extensions that allow the recreation of an old Lomograph camera effect on an + /// using Mutate/Clone. /// public static class LomographExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// Alters the colors of the image recreating an old Lomograph camera effect. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Lomograph(this IImageProcessingContext source) => source.ApplyProcessor(new LomographProcessor()); @@ -27,7 +28,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Lomograph(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new LomographProcessor(), rectangle); } diff --git a/src/ImageSharp/Processing/OilPaintExtensions.cs b/src/ImageSharp/Processing/OilPaintExtensions.cs index ee51b31fa..1aa98c8c1 100644 --- a/src/ImageSharp/Processing/OilPaintExtensions.cs +++ b/src/ImageSharp/Processing/OilPaintExtensions.cs @@ -7,7 +7,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds oil painting effect extensions to the type. + /// Defines oil painting effect extensions applicable on an + /// using Mutate/Clone. /// public static class OilPaintExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// set to 10 and 15 respectively. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext OilPaint(this IImageProcessingContext source) => OilPaint(source, 10, 15); /// @@ -27,7 +28,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext OilPaint(this IImageProcessingContext source, Rectangle rectangle) => OilPaint(source, 10, 15, rectangle); @@ -37,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The number of intensity levels. Higher values result in a broader range of color intensities forming part of the result image. /// The number of neighboring pixels used in calculating each individual pixel value. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext OilPaint(this IImageProcessingContext source, int levels, int brushSize) => source.ApplyProcessor(new OilPaintingProcessor(levels, brushSize)); @@ -51,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext OilPaint( this IImageProcessingContext source, int levels, diff --git a/src/ImageSharp/Processing/OpacityExtensions.cs b/src/ImageSharp/Processing/OpacityExtensions.cs index 6d9198648..ecf6ce783 100644 --- a/src/ImageSharp/Processing/OpacityExtensions.cs +++ b/src/ImageSharp/Processing/OpacityExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the alteration of the opacity component to the type. + /// Defines extensions that allow the alteration of the opacity component of an + /// using Mutate/Clone. /// public static class OpacityExtensions { @@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The proportion of the conversion. Must be between 0 and 1. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Opacity(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new OpacityProcessor(amount)); @@ -29,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Opacity(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new OpacityProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/PadExtensions.cs b/src/ImageSharp/Processing/PadExtensions.cs index 0422f7c59..29f80b43f 100644 --- a/src/ImageSharp/Processing/PadExtensions.cs +++ b/src/ImageSharp/Processing/PadExtensions.cs @@ -7,7 +7,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of padding operations to the type. + /// Defines extensions that allow the application of padding operations on an + /// using Mutate/Clone. /// public static class PadExtensions { @@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.Processing /// The source image to pad. /// The new width. /// The new height. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Pad(this IImageProcessingContext source, int width, int height) { var options = new ResizeOptions diff --git a/src/ImageSharp/Processing/PixelateExtensions.cs b/src/ImageSharp/Processing/PixelateExtensions.cs index d9f7f9be5..bf40af91a 100644 --- a/src/ImageSharp/Processing/PixelateExtensions.cs +++ b/src/ImageSharp/Processing/PixelateExtensions.cs @@ -7,7 +7,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds pixelation effect extensions to the type. + /// Defines pixelation effect extensions applicable on an + /// using Mutate/Clone. /// public static class PixelateExtensions { @@ -15,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing /// Pixelates an image with the given pixel size. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Pixelate(this IImageProcessingContext source) => Pixelate(source, 4); /// @@ -23,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The size of the pixels. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Pixelate(this IImageProcessingContext source, int size) => source.ApplyProcessor(new PixelateProcessor(size)); @@ -35,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Pixelate( this IImageProcessingContext source, int size, diff --git a/src/ImageSharp/Processing/PolaroidExtensions.cs b/src/ImageSharp/Processing/PolaroidExtensions.cs index 4e7841168..eace46357 100644 --- a/src/ImageSharp/Processing/PolaroidExtensions.cs +++ b/src/ImageSharp/Processing/PolaroidExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the recreation of an old Polaroid camera effect to the type. + /// Defines extensions that allow the recreation of an old Polaroid camera effect on an + /// using Mutate/Clone. /// public static class PolaroidExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// Alters the colors of the image recreating an old Polaroid camera effect. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Polaroid(this IImageProcessingContext source) => source.ApplyProcessor(new PolaroidProcessor()); @@ -27,7 +28,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Polaroid(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new PolaroidProcessor(), rectangle); } diff --git a/src/ImageSharp/Processing/QuantizeExtensions.cs b/src/ImageSharp/Processing/QuantizeExtensions.cs index 5bd2f49bd..ad351afa9 100644 --- a/src/ImageSharp/Processing/QuantizeExtensions.cs +++ b/src/ImageSharp/Processing/QuantizeExtensions.cs @@ -7,7 +7,8 @@ using SixLabors.ImageSharp.Processing.Processors.Quantization; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of quantizing algorithms to the type. + /// Defines extensions that allow the application of quantizing algorithms on an + /// using Mutate/Clone. /// public static class QuantizeExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The pixel format. /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Quantize(this IImageProcessingContext source) where TPixel : struct, IPixel => Quantize(source, KnownQuantizers.Octree); @@ -27,7 +28,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image this method extends. /// The quantizer to apply to perform the operation. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Quantize(this IImageProcessingContext source, IQuantizer quantizer) where TPixel : struct, IPixel => source.ApplyProcessor(new QuantizeProcessor(quantizer)); diff --git a/src/ImageSharp/Processing/ResizeExtensions.cs b/src/ImageSharp/Processing/ResizeExtensions.cs index 57dbcb1d1..4578b4353 100644 --- a/src/ImageSharp/Processing/ResizeExtensions.cs +++ b/src/ImageSharp/Processing/ResizeExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of resize operations to the type. + /// Defines extensions that allow the application of resize operations on an + /// using Mutate/Clone. /// public static class ResizeExtensions { @@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image to resize. /// The resize options. - /// The + /// The to allow chaining of operations. /// Passing zero for one of height or width within the resize options will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, ResizeOptions options) => source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize())); @@ -27,7 +28,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image to resize. /// The target image size. - /// The + /// The to allow chaining of operations. /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size) => Resize(source, size.Width, size.Height, KnownResamplers.Bicubic, false); @@ -38,7 +39,7 @@ namespace SixLabors.ImageSharp.Processing /// The image to resize. /// The target image size. /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The + /// The to allow chaining of operations. /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size, bool compand) => Resize(source, size.Width, size.Height, KnownResamplers.Bicubic, compand); @@ -49,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing /// The image to resize. /// The target image width. /// The target image height. - /// The + /// The to allow chaining of operations. /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height) => Resize(source, width, height, KnownResamplers.Bicubic, false); @@ -61,7 +62,7 @@ namespace SixLabors.ImageSharp.Processing /// The target image width. /// The target image height. /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The + /// The to allow chaining of operations. /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, bool compand) => Resize(source, width, height, KnownResamplers.Bicubic, compand); @@ -73,7 +74,7 @@ namespace SixLabors.ImageSharp.Processing /// The target image width. /// The target image height. /// The to perform the resampling. - /// The + /// The to allow chaining of operations. /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, IResampler sampler) => Resize(source, width, height, sampler, false); @@ -85,7 +86,7 @@ namespace SixLabors.ImageSharp.Processing /// The target image size. /// The to perform the resampling. /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The + /// The to allow chaining of operations. /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size, IResampler sampler, bool compand) => Resize(source, size.Width, size.Height, sampler, new Rectangle(0, 0, size.Width, size.Height), compand); @@ -98,7 +99,7 @@ namespace SixLabors.ImageSharp.Processing /// The target image height. /// The to perform the resampling. /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The + /// The to allow chaining of operations. /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, IResampler sampler, bool compand) => Resize(source, width, height, sampler, new Rectangle(0, 0, width, height), compand); @@ -118,7 +119,7 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the target image object to draw to. /// /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The + /// The to allow chaining of operations. /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize( this IImageProcessingContext source, @@ -141,7 +142,7 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the target image object to draw to. /// /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The + /// The to allow chaining of operations. /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize( this IImageProcessingContext source, diff --git a/src/ImageSharp/Processing/RotateExtensions.cs b/src/ImageSharp/Processing/RotateExtensions.cs index cb637a1b8..395462ae3 100644 --- a/src/ImageSharp/Processing/RotateExtensions.cs +++ b/src/ImageSharp/Processing/RotateExtensions.cs @@ -6,7 +6,8 @@ using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of rotate operations to the type. + /// Defines extensions that allow the application of rotate operations on an + /// using Mutate/Clone. /// public static class RotateExtensions { @@ -15,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image to rotate. /// The to perform the rotation. - /// The + /// The to allow chaining of operations. public static IImageProcessingContext Rotate(this IImageProcessingContext source, RotateMode rotateMode) => Rotate(source, (float)rotateMode); @@ -24,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image to rotate. /// The angle in degrees to perform the rotation. - /// The + /// The to allow chaining of operations. public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees) => Rotate(source, degrees, KnownResamplers.Bicubic); @@ -34,7 +35,7 @@ namespace SixLabors.ImageSharp.Processing /// The image to rotate. /// The angle in degrees to perform the rotation. /// The to perform the resampling. - /// The + /// The to allow chaining of operations. public static IImageProcessingContext Rotate( this IImageProcessingContext source, float degrees, diff --git a/src/ImageSharp/Processing/RotateFlipExtensions.cs b/src/ImageSharp/Processing/RotateFlipExtensions.cs index 5030c942e..4d5d90c30 100644 --- a/src/ImageSharp/Processing/RotateFlipExtensions.cs +++ b/src/ImageSharp/Processing/RotateFlipExtensions.cs @@ -6,7 +6,8 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of rotate-flip operations to the type. + /// Defines extensions that allow the application of rotate-flip operations on an + /// using Mutate/Clone. /// public static class RotateFlipExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// The image to rotate, flip, or both. /// The to perform the rotation. /// The to perform the flip. - /// The + /// The to allow chaining of operations. public static IImageProcessingContext RotateFlip(this IImageProcessingContext source, RotateMode rotateMode, FlipMode flipMode) => source.Rotate(rotateMode).Flip(flipMode); } diff --git a/src/ImageSharp/Processing/SaturateExtensions.cs b/src/ImageSharp/Processing/SaturateExtensions.cs index fe2cf5f34..e9ba820b6 100644 --- a/src/ImageSharp/Processing/SaturateExtensions.cs +++ b/src/ImageSharp/Processing/SaturateExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the alteration of the saturation component to the type. + /// Defines extensions that allow the alteration of the saturation component of an + /// using Mutate/Clone. /// public static class SaturateExtensions { @@ -21,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The proportion of the conversion. Must be greater than or equal to 0. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Saturate(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new SaturateProcessor(amount)); @@ -37,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Saturate(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new SaturateProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/SepiaExtensions.cs b/src/ImageSharp/Processing/SepiaExtensions.cs index 5b23ec11a..5ee5151fa 100644 --- a/src/ImageSharp/Processing/SepiaExtensions.cs +++ b/src/ImageSharp/Processing/SepiaExtensions.cs @@ -8,7 +8,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of sepia toning to the type. + /// Defines extensions that allow the application of sepia toning on an + /// using Mutate/Clone. /// public static class SepiaExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// Applies sepia toning to the image. /// /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Sepia(this IImageProcessingContext source) => Sepia(source, 1F); @@ -25,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The proportion of the conversion. Must be between 0 and 1. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Sepia(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new SepiaProcessor(amount)); @@ -36,7 +37,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Sepia(this IImageProcessingContext source, Rectangle rectangle) => Sepia(source, 1F, rectangle); @@ -48,7 +49,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Sepia(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new SepiaProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/SkewExtensions.cs b/src/ImageSharp/Processing/SkewExtensions.cs index 7f378d248..77a46af0d 100644 --- a/src/ImageSharp/Processing/SkewExtensions.cs +++ b/src/ImageSharp/Processing/SkewExtensions.cs @@ -6,7 +6,8 @@ using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of skew operations to the type. + /// Defines extensions that allow the application of skew operations on an + /// using Mutate/Clone. /// public static class SkewExtensions { @@ -16,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// The image to skew. /// The angle in degrees to perform the skew along the x-axis. /// The angle in degrees to perform the skew along the y-axis. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Skew(this IImageProcessingContext source, float degreesX, float degreesY) => Skew(source, degreesX, degreesY, KnownResamplers.Bicubic); @@ -28,7 +29,7 @@ namespace SixLabors.ImageSharp.Processing /// The angle in degrees to perform the skew along the x-axis. /// The angle in degrees to perform the skew along the y-axis. /// The to perform the resampling. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Skew( this IImageProcessingContext source, float degreesX, diff --git a/src/ImageSharp/Processing/TransformExtensions.cs b/src/ImageSharp/Processing/TransformExtensions.cs index 35f374d01..7fffb71d2 100644 --- a/src/ImageSharp/Processing/TransformExtensions.cs +++ b/src/ImageSharp/Processing/TransformExtensions.cs @@ -9,7 +9,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of composable transform operations to the type. + /// Defines extensions that allow the application of composable transform operations on an + /// using Mutate/Clone. /// public static class TransformExtensions { @@ -30,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing /// The . /// The affine transform builder. /// The to perform the resampling. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Transform( this IImageProcessingContext ctx, AffineTransformBuilder builder, @@ -44,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing /// The source rectangle /// The affine transform builder. /// The to perform the resampling. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Transform( this IImageProcessingContext ctx, Rectangle sourceRectangle, @@ -64,7 +65,7 @@ namespace SixLabors.ImageSharp.Processing /// The transformation matrix. /// The size of the result image. /// The to perform the resampling. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Transform( this IImageProcessingContext ctx, Rectangle sourceRectangle, @@ -82,7 +83,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image to transform. /// The affine transform builder. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Transform( this IImageProcessingContext source, ProjectiveTransformBuilder builder) => @@ -94,7 +95,7 @@ namespace SixLabors.ImageSharp.Processing /// The . /// The projective transform builder. /// The to perform the resampling. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Transform( this IImageProcessingContext ctx, ProjectiveTransformBuilder builder, @@ -108,7 +109,7 @@ namespace SixLabors.ImageSharp.Processing /// The source rectangle /// The projective transform builder. /// The to perform the resampling. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Transform( this IImageProcessingContext ctx, Rectangle sourceRectangle, @@ -128,7 +129,7 @@ namespace SixLabors.ImageSharp.Processing /// The transformation matrix. /// The size of the result image. /// The to perform the resampling. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Transform( this IImageProcessingContext ctx, Rectangle sourceRectangle, diff --git a/src/ImageSharp/Processing/VignetteExtensions.cs b/src/ImageSharp/Processing/VignetteExtensions.cs index 18dd8064c..63cdee3f8 100644 --- a/src/ImageSharp/Processing/VignetteExtensions.cs +++ b/src/ImageSharp/Processing/VignetteExtensions.cs @@ -9,7 +9,8 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Adds extensions that allow the application of a radial glow to the type. + /// Defines extensions that allow the application of a radial glow to an + /// using Mutate/Clone. /// public static class VignetteExtensions { @@ -18,7 +19,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The pixel format. /// The image this method extends. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Vignette(this IImageProcessingContext source) where TPixel : struct, IPixel => Vignette(source, GraphicsOptions.Default); @@ -29,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image this method extends. /// The color to set as the vignette. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Vignette(this IImageProcessingContext source, TPixel color) where TPixel : struct, IPixel => Vignette(source, GraphicsOptions.Default, color); @@ -41,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The the x-radius. /// The the y-radius. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Vignette(this IImageProcessingContext source, float radiusX, float radiusY) where TPixel : struct, IPixel => Vignette(source, GraphicsOptions.Default, radiusX, radiusY); @@ -54,7 +55,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Vignette(this IImageProcessingContext source, Rectangle rectangle) where TPixel : struct, IPixel => Vignette(source, GraphicsOptions.Default, rectangle); @@ -70,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Vignette(this IImageProcessingContext source, TPixel color, float radiusX, float radiusY, Rectangle rectangle) where TPixel : struct, IPixel => source.Vignette(GraphicsOptions.Default, color, radiusX, radiusY, rectangle); @@ -81,7 +82,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image this method extends. /// The options effecting pixel blending. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options) where TPixel : struct, IPixel => source.VignetteInternal(options, NamedColors.Black, ValueSize.PercentageOfWidth(.5f), ValueSize.PercentageOfHeight(.5f)); @@ -93,7 +94,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The options effecting pixel blending. /// The color to set as the vignette. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options, TPixel color) where TPixel : struct, IPixel => source.VignetteInternal(options, color, ValueSize.PercentageOfWidth(.5f), ValueSize.PercentageOfHeight(.5f)); @@ -106,7 +107,7 @@ namespace SixLabors.ImageSharp.Processing /// The options effecting pixel blending. /// The the x-radius. /// The the y-radius. - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options, float radiusX, float radiusY) where TPixel : struct, IPixel => source.VignetteInternal(options, NamedColors.Black, radiusX, radiusY); @@ -120,7 +121,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options, Rectangle rectangle) where TPixel : struct, IPixel => source.VignetteInternal(options, NamedColors.Black, ValueSize.PercentageOfWidth(.5f), ValueSize.PercentageOfHeight(.5f), rectangle); @@ -137,7 +138,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The . + /// The to allow chaining of operations. public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float radiusX, float radiusY, Rectangle rectangle) where TPixel : struct, IPixel => source.VignetteInternal(options, color, radiusX, radiusY, rectangle); From 7f2b4b02446ce8c8013f803c5aba8ac960413e05 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 22:31:06 +0200 Subject: [PATCH 138/223] publish non-generic QuantizeProcessor --- ImageSharp.sln.DotSettings | 1 + .../Quantization/QuantizeProcessor.cs | 41 +++---------- .../Quantization/QuantizeProcessor{TPixel}.cs | 57 +++++++++++++++++++ .../Processing/QuantizeExtensions.cs | 13 ++--- 4 files changed, 70 insertions(+), 42 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs diff --git a/ImageSharp.sln.DotSettings b/ImageSharp.sln.DotSettings index 8e7b5dd48..526817242 100644 --- a/ImageSharp.sln.DotSettings +++ b/ImageSharp.sln.DotSettings @@ -388,4 +388,5 @@ True True True + True \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs index e99f504b4..0aee0b483 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor.cs @@ -1,59 +1,34 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Quantization { /// - /// Enables the quantization of images to reduce the number of colors used in the image palette. + /// Defines quantization processing for images to reduce the number of colors used in the image palette. /// - /// The pixel format. - internal class QuantizeProcessor : ImageProcessor - where TPixel : struct, IPixel + public class QuantizeProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The quantizer used to reduce the color palette + /// The quantizer used to reduce the color palette. public QuantizeProcessor(IQuantizer quantizer) { - Guard.NotNull(quantizer, nameof(quantizer)); this.Quantizer = quantizer; } /// - /// Gets the quantizer + /// Gets the quantizer. /// public IQuantizer Quantizer { get; } /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - using (IFrameQuantizer executor = this.Quantizer.CreateFrameQuantizer(configuration)) - using (QuantizedFrame quantized = executor.QuantizeFrame(source)) - { - int paletteCount = quantized.Palette.Length - 1; - - // Not parallel to remove "quantized" closure allocation. - // We can operate directly on the source here as we've already read it to get the - // quantized result - for (int y = 0; y < source.Height; y++) - { - Span row = source.GetPixelRowSpan(y); - ReadOnlySpan quantizedPixelSpan = quantized.GetPixelSpan(); - int yy = y * source.Width; - - for (int x = 0; x < source.Width; x++) - { - int i = x + yy; - row[x] = quantized.Palette[Math.Min(paletteCount, quantizedPixelSpan[i])]; - } - } - } + return new QuantizeProcessor(this.Quantizer); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs new file mode 100644 index 000000000..b52343a2a --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs @@ -0,0 +1,57 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Quantization +{ + /// + /// Enables the quantization of images to reduce the number of colors used in the image palette. + /// + /// The pixel format. + internal class QuantizeProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly IQuantizer quantizer; + + /// + /// Initializes a new instance of the class. + /// + /// The quantizer used to reduce the color palette. + public QuantizeProcessor(IQuantizer quantizer) + { + Guard.NotNull(quantizer, nameof(quantizer)); + this.quantizer = quantizer; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + using (IFrameQuantizer executor = this.quantizer.CreateFrameQuantizer(configuration)) + using (QuantizedFrame quantized = executor.QuantizeFrame(source)) + { + int paletteCount = quantized.Palette.Length - 1; + + // Not parallel to remove "quantized" closure allocation. + // We can operate directly on the source here as we've already read it to get the + // quantized result + for (int y = 0; y < source.Height; y++) + { + Span row = source.GetPixelRowSpan(y); + ReadOnlySpan quantizedPixelSpan = quantized.GetPixelSpan(); + int yy = y * source.Width; + + for (int x = 0; x < source.Width; x++) + { + int i = x + yy; + row[x] = quantized.Palette[Math.Min(paletteCount, quantizedPixelSpan[i])]; + } + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/QuantizeExtensions.cs b/src/ImageSharp/Processing/QuantizeExtensions.cs index ad351afa9..3410ee6be 100644 --- a/src/ImageSharp/Processing/QuantizeExtensions.cs +++ b/src/ImageSharp/Processing/QuantizeExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; namespace SixLabors.ImageSharp.Processing @@ -15,22 +14,18 @@ namespace SixLabors.ImageSharp.Processing /// /// Applies quantization to the image using the . /// - /// The pixel format. /// The image this method extends. /// The to allow chaining of operations. - public static IImageProcessingContext Quantize(this IImageProcessingContext source) - where TPixel : struct, IPixel - => Quantize(source, KnownQuantizers.Octree); + public static IImageProcessingContext Quantize(this IImageProcessingContext source) => + Quantize(source, KnownQuantizers.Octree); /// /// Applies quantization to the image. /// - /// The pixel format. /// The image this method extends. /// The quantizer to apply to perform the operation. /// The to allow chaining of operations. - public static IImageProcessingContext Quantize(this IImageProcessingContext source, IQuantizer quantizer) - where TPixel : struct, IPixel - => source.ApplyProcessor(new QuantizeProcessor(quantizer)); + public static IImageProcessingContext Quantize(this IImageProcessingContext source, IQuantizer quantizer) => + source.ApplyProcessor(new QuantizeProcessor(quantizer)); } } \ No newline at end of file From aeaeab84f1dacbd8c492b32edc1b10524dd0790c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 23:14:41 +0200 Subject: [PATCH 139/223] temporarily disable multitargeting --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 3 ++- src/ImageSharp/ImageSharp.csproj | 3 ++- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 915915f6c..fdeb27a77 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -11,7 +11,8 @@ $(packageversion) 0.0.1 - netcoreapp2.1;netstandard1.3;netstandard2.0 + + netstandard2.0 7.3 true diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index d734648f4..4abe2f57a 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -11,7 +11,8 @@ $(packageversion) 0.0.1 - netcoreapp2.1;netstandard1.3;netstandard2.0;net472 + + netstandard2.0 true true diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 0b727f30c..efdf89964 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,6 +1,7 @@  - netcoreapp2.1;net462;net472 + + netcoreapp2.1 True latest full From 1d67089bd71811f8f810249bec2531bc499ee879 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 23:30:32 +0200 Subject: [PATCH 140/223] add skeleton for Color type --- src/ImageSharp/Color.cs | 42 +++++++++++++++++++ .../PixelImplementations/Rgba64.cs | 15 +++++++ .../Codecs/GetSetPixel.cs | 4 +- .../Drawing/DrawBeziers.cs | 2 +- .../Drawing/DrawLines.cs | 2 +- .../Drawing/DrawPolygon.cs | 2 +- .../Drawing/DrawTextOutline.cs | 2 +- .../Drawing/FillWithPattern.cs | 2 +- tests/ImageSharp.Tests/ColorTests.cs | 10 +++++ 9 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 src/ImageSharp/Color.cs create mode 100644 tests/ImageSharp.Tests/ColorTests.cs diff --git a/src/ImageSharp/Color.cs b/src/ImageSharp/Color.cs new file mode 100644 index 000000000..5b3de2eee --- /dev/null +++ b/src/ImageSharp/Color.cs @@ -0,0 +1,42 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Numerics; + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + public struct Color + { + private Rgba64 data; + + public Color(Rgba64 pixel) + { + this.data = pixel; + } + + public Color(Rgba32 pixel) + { + this.data = default; + this.data.FromRgba32(pixel); + } + + public Color(Vector4 vector) + { + this.data = default; + this.data.FromVector4(vector); + } + + public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(new Rgba32(r, g, b, a)); + public static Color FromRgba(ushort r, ushort g, ushort b, ushort a) => new Color(new Rgba64(r, g, b, a)); + + public TPixel ToPixel() + where TPixel : struct, IPixel + { + TPixel pixel = default; + pixel.FromRgba64(this.data); + return pixel; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs index 87d1b235b..6d838a54d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs @@ -54,6 +54,21 @@ namespace SixLabors.ImageSharp.PixelFormats this.A = a; } + /// + /// Initializes a new instance of the struct. + /// + /// The red component. + /// The green component. + /// The blue component. + /// The alpha component. + public Rgba64(byte r, byte g, byte b, byte a) + { + this.R = r; + this.G = g; + this.B = b; + this.A = a; + } + /// /// Gets or sets the RGB components of this struct as /// diff --git a/tests/ImageSharp.Benchmarks/Codecs/GetSetPixel.cs b/tests/ImageSharp.Benchmarks/Codecs/GetSetPixel.cs index a51ce8ebc..f0d7a54d0 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/GetSetPixel.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/GetSetPixel.cs @@ -10,11 +10,11 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs public class GetSetPixel : BenchmarkBase { [Benchmark(Baseline = true, Description = "System.Drawing GetSet pixel")] - public Color ResizeSystemDrawing() + public System.Drawing.Color ResizeSystemDrawing() { using (var source = new Bitmap(400, 400)) { - source.SetPixel(200, 200, Color.White); + source.SetPixel(200, 200, System.Drawing.Color.White); return source.GetPixel(200, 200); } } diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs index bc9c1c96d..0a343864d 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Benchmarks graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(Color.HotPink, 10)) + using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) { graphics.DrawBeziers(pen, new[] { new PointF(10, 500), diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs index 4265525e5..00942cc36 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Benchmarks graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(Color.HotPink, 10)) + using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) { graphics.DrawLines(pen, new[] { new PointF(10, 10), diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs index 4172b3c38..dcaf4bae6 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(Color.HotPink, 10)) + using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) { graphics.DrawPolygon(pen, new[] { new PointF(10, 10), diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs index b99c47960..ee17adbb5 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(Color.HotPink, 10)) + using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) using (var font = new Font("Arial", 12, GraphicsUnit.Point)) using (var gp = new GraphicsPath()) { diff --git a/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs b/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs index 3c9cfd7e3..411f8210a 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/FillWithPattern.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var brush = new HatchBrush(HatchStyle.BackwardDiagonal, Color.HotPink)) + using (var brush = new HatchBrush(HatchStyle.BackwardDiagonal, System.Drawing.Color.HotPink)) { graphics.FillRectangle(brush, new Rectangle(0, 0, 800, 800)); // can't find a way to flood fill with a brush } diff --git a/tests/ImageSharp.Tests/ColorTests.cs b/tests/ImageSharp.Tests/ColorTests.cs new file mode 100644 index 000000000..4142066bc --- /dev/null +++ b/tests/ImageSharp.Tests/ColorTests.cs @@ -0,0 +1,10 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Tests +{ + public class ColorTests + { + + } +} \ No newline at end of file From b8d47cbd3264deb589ac36abeb38170b9867c3b3 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 5 May 2019 23:52:39 +0200 Subject: [PATCH 141/223] add more Rgba64 constructor overloads --- src/ImageSharp/Color.cs | 6 +- .../PixelImplementations/Rgba64.cs | 146 +++++++++++- .../PixelFormats/Rgba64Tests.cs | 215 ++++++++++++++++-- 3 files changed, 336 insertions(+), 31 deletions(-) diff --git a/src/ImageSharp/Color.cs b/src/ImageSharp/Color.cs index 5b3de2eee..4f6cab97b 100644 --- a/src/ImageSharp/Color.cs +++ b/src/ImageSharp/Color.cs @@ -18,8 +18,7 @@ namespace SixLabors.ImageSharp public Color(Rgba32 pixel) { - this.data = default; - this.data.FromRgba32(pixel); + this.data = new Rgba64(pixel); } public Color(Vector4 vector) @@ -29,8 +28,7 @@ namespace SixLabors.ImageSharp } public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(new Rgba32(r, g, b, a)); - public static Color FromRgba(ushort r, ushort g, ushort b, ushort a) => new Color(new Rgba64(r, g, b, a)); - + public TPixel ToPixel() where TPixel : struct, IPixel { diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs index 6d838a54d..cf9d4a552 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs @@ -57,20 +57,78 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Initializes a new instance of the struct. /// - /// The red component. - /// The green component. - /// The blue component. - /// The alpha component. - public Rgba64(byte r, byte g, byte b, byte a) + /// A structure of 4 bytes in RGBA byte order. + public Rgba64(Rgba32 source) { - this.R = r; - this.G = g; - this.B = b; - this.A = a; + this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); + this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); + this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); } /// - /// Gets or sets the RGB components of this struct as + /// Initializes a new instance of the struct. + /// + /// A structure of 4 bytes in BGRA byte order. + public Rgba64(Bgra32 source) + { + this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); + this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); + this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + } + + /// + /// Initializes a new instance of the struct. + /// + /// A structure of 4 bytes in ARGB byte order. + public Rgba64(Argb32 source) + { + this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); + this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); + this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + } + + /// + /// Initializes a new instance of the struct. + /// + /// A structure of 3 bytes in RGB byte order. + public Rgba64(Rgb24 source) + { + this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); + this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); + this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.A = ushort.MaxValue; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A structure of 3 bytes in BGR byte order. + public Rgba64(Bgr24 source) + { + this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); + this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); + this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.A = ushort.MaxValue; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The . + public Rgba64(Vector4 vector) + { + vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max; + this.R = (ushort)MathF.Round(vector.X); + this.G = (ushort)MathF.Round(vector.Y); + this.B = (ushort)MathF.Round(vector.Z); + this.A = (ushort)MathF.Round(vector.W); + } + + /// + /// Gets or sets the RGB components of this struct as . /// public Rgb48 Rgb { @@ -236,6 +294,74 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba64(Rgba64 source) => this = source; + /// + /// Convert to . + /// + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public Rgba32 ToRgba32() + { + byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); + byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); + byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); + byte a = ImageMaths.DownScaleFrom16BitTo8Bit(this.A); + return new Rgba32(r, g, b, a); + } + + /// + /// Convert to . + /// + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public Bgra32 ToBgra32() + { + byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); + byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); + byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); + byte a = ImageMaths.DownScaleFrom16BitTo8Bit(this.A); + return new Bgra32(r, g, b, a); + } + + /// + /// Convert to . + /// + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public Argb32 ToArgb32() + { + byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); + byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); + byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); + byte a = ImageMaths.DownScaleFrom16BitTo8Bit(this.A); + return new Argb32(r, g, b, a); + } + + /// + /// Convert to . + /// + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public Rgb24 ToRgb24() + { + byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); + byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); + byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); + return new Rgb24(r, g, b); + } + + /// + /// Convert to . + /// + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public Bgr24 ToBgr24() + { + byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); + byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); + byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); + return new Bgr24(r, g, b); + } + /// public override bool Equals(object obj) => obj is Rgba64 rgba64 && this.Equals(rgba64); diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs index 51f80e0e1..55a2dda7a 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs @@ -33,37 +33,50 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(Vector4.One, new Rgba64(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue).ToVector4()); } - [Fact] - public void Rgba64_ToScaledVector4() + [Theory] + [InlineData(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)] + [InlineData(0, 0, 0, 0)] + [InlineData(ushort.MaxValue/2, 100, 2222, 33333)] + public void Rgba64_ToScaledVector4(ushort r, ushort g, ushort b, ushort a) { // arrange - var short2 = new Rgba64(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue); + var short2 = new Rgba64(r, g, b, a); + + float max = ushort.MaxValue; + float rr = r / max; + float gg = g / max; + float bb = b / max; + float aa = a / max; // act Vector4 actual = short2.ToScaledVector4(); // assert - Assert.Equal(1, actual.X); - Assert.Equal(1, actual.Y); - Assert.Equal(1, actual.Z); - Assert.Equal(1, actual.W); + Assert.Equal(rr, actual.X); + Assert.Equal(gg, actual.Y); + Assert.Equal(bb, actual.Z); + Assert.Equal(aa, actual.W); } - [Fact] - public void Rgba64_FromScaledVector4() + [Theory] + [InlineData(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue)] + [InlineData(0, 0, 0, 0)] + [InlineData(ushort.MaxValue/2, 100, 2222, 33333)] + public void Rgba64_FromScaledVector4(ushort r, ushort g, ushort b, ushort a) { // arrange - var pixel = default(Rgba64); - var short4 = new Rgba64(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, ushort.MaxValue); - const ulong expected = 0xFFFFFFFFFFFFFFFF; - + + var source = new Rgba64(r, g, b, a); + // act - Vector4 scaled = short4.ToScaledVector4(); - pixel.FromScaledVector4(scaled); - ulong actual = pixel.PackedValue; + Vector4 scaled = source.ToScaledVector4(); + + Rgba64 actual = default; + actual.FromScaledVector4(scaled); + // assert - Assert.Equal(expected, actual); + Assert.Equal(source, actual); } [Fact] @@ -91,6 +104,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // assert Assert.Equal(expected, actual); } + [Fact] public void Rgba64_FromBgra5551() @@ -108,5 +122,172 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expected, rgba.B); Assert.Equal(expected, rgba.A); } + + [Fact] + public void Equality_WhenTrue() + { + Rgba64 c1 = new Rgba64(100, 2000, 3000, 40000); + Rgba64 c2 = new Rgba64(100, 2000, 3000, 40000); + + Assert.True(c1.Equals(c2)); + Assert.True(c1.GetHashCode() == c2.GetHashCode()); + } + + [Fact] + public void Equality_WhenFalse() + { + Rgba64 c1 = new Rgba64(100, 2000, 3000, 40000); + Rgba64 c2 = new Rgba64(101, 2000, 3000, 40000); + Rgba64 c3 = new Rgba64(100, 2000, 3000, 40001); + + Assert.False(c1.Equals(c2)); + Assert.False(c2.Equals(c3)); + Assert.False(c3.Equals(c1)); + } + + [Fact] + public void Rgba64_FromRgba32() + { + var source = new Rgba32(20, 38, 76, 115); + var expected = new Rgba64(5140, 9766, 19532, 29555); + + Rgba64 actual = default; + actual.FromRgba32(source); + + Assert.Equal(expected, actual); + } + + [Fact] + public void ConstructFrom_Rgba32() + { + var expected = new Rgba64(5140, 9766, 19532, 29555); + var source = new Rgba32(20, 38, 76, 115); + Rgba64 actual = new Rgba64(source); + + Assert.Equal(expected, actual); + } + + [Fact] + public void ConstructFrom_Bgra32() + { + var expected = new Rgba64(5140, 9766, 19532, 29555); + var source = new Bgra32(20, 38, 76, 115); + Rgba64 actual = new Rgba64(source); + + Assert.Equal(expected, actual); + } + + [Fact] + public void ConstructFrom_Argb32() + { + var expected = new Rgba64(5140, 9766, 19532, 29555); + var source = new Argb32(20, 38, 76, 115); + Rgba64 actual = new Rgba64(source); + + Assert.Equal(expected, actual); + } + + [Fact] + public void ConstructFrom_Rgb24() + { + var expected = new Rgba64(5140, 9766, 19532, ushort.MaxValue); + var source = new Rgb24(20, 38, 76); + Rgba64 actual = new Rgba64(source); + + Assert.Equal(expected, actual); + } + + [Fact] + public void ConstructFrom_Bgr24() + { + var expected = new Rgba64(5140, 9766, 19532, ushort.MaxValue); + var source = new Bgr24(20, 38, 76); + Rgba64 actual = new Rgba64(source); + + Assert.Equal(expected, actual); + } + + [Fact] + public void ConstructFrom_Vector4() + { + Vector4 source = new Vector4(0f, 0.2f, 0.5f, 1f); + Rgba64 expected = default; + expected.FromScaledVector4(source); + + Rgba64 actual = new Rgba64(source); + + Assert.Equal(expected, actual); + } + + + [Fact] + public void ToRgba32_Retval() + { + // arrange + var source = new Rgba64(5140, 9766, 19532, 29555); + var expected = new Rgba32(20, 38, 76, 115); + + // act + var actual = source.ToRgba32(); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void ToBgra32_Retval() + { + // arrange + var source = new Rgba64(5140, 9766, 19532, 29555); + var expected = new Bgra32(20, 38, 76, 115); + + // act + var actual = source.ToBgra32(); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void ToArgb32_Retval() + { + // arrange + var source = new Rgba64(5140, 9766, 19532, 29555); + var expected = new Argb32(20, 38, 76, 115); + + // act + var actual = source.ToArgb32(); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void ToRgb24_Retval() + { + // arrange + var source = new Rgba64(5140, 9766, 19532, 29555); + var expected = new Rgb24(20, 38, 76); + + // act + var actual = source.ToRgb24(); + + // assert + Assert.Equal(expected, actual); + } + + [Fact] + public void ToBgr24_Retval() + { + // arrange + var source = new Rgba64(5140, 9766, 19532, 29555); + var expected = new Bgr24(20, 38, 76); + + // act + var actual = source.ToBgr24(); + + // assert + Assert.Equal(expected, actual); + } } } From a2ca7da03d4eaf36a513bc6aab7b9121ac7ed1dd Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 6 May 2019 00:41:19 +0200 Subject: [PATCH 142/223] basic Color methods --- src/ImageSharp/Color.cs | 51 +++++- tests/ImageSharp.Tests/ColorTests.cs | 245 +++++++++++++++++++++++++++ 2 files changed, 292 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Color.cs b/src/ImageSharp/Color.cs index 4f6cab97b..70c721060 100644 --- a/src/ImageSharp/Color.cs +++ b/src/ImageSharp/Color.cs @@ -7,9 +7,9 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { - public struct Color + public readonly struct Color { - private Rgba64 data; + private readonly Rgba64 data; public Color(Rgba64 pixel) { @@ -21,12 +21,55 @@ namespace SixLabors.ImageSharp this.data = new Rgba64(pixel); } + public Color(Argb32 pixel) + { + this.data = new Rgba64(pixel); + } + + public Color(Bgra32 pixel) + { + this.data = new Rgba64(pixel); + } + + public Color(Rgb24 pixel) + { + this.data = new Rgba64(pixel); + } + + public Color(Bgr24 pixel) + { + this.data = new Rgba64(pixel); + } + public Color(Vector4 vector) { - this.data = default; - this.data.FromVector4(vector); + this.data = new Rgba64(vector); } + public static implicit operator Color(Rgba64 source) => new Color(source); + + public static implicit operator Color(Rgba32 source) => new Color(source); + + public static implicit operator Color(Bgra32 source) => new Color(source); + + public static implicit operator Color(Argb32 source) => new Color(source); + + public static implicit operator Color(Rgb24 source) => new Color(source); + + public static implicit operator Color(Bgr24 source) => new Color(source); + + public static implicit operator Rgba64(Color color) => color.data; + + public static implicit operator Rgba32(Color color) => color.data.ToRgba32(); + + public static implicit operator Bgra32(Color color) => color.data.ToBgra32(); + + public static implicit operator Argb32(Color color) => color.data.ToArgb32(); + + public static implicit operator Rgb24(Color color) => color.data.ToRgb24(); + + public static implicit operator Bgr24(Color color) => color.data.ToBgr24(); + public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(new Rgba32(r, g, b, a)); public TPixel ToPixel() diff --git a/tests/ImageSharp.Tests/ColorTests.cs b/tests/ImageSharp.Tests/ColorTests.cs index 4142066bc..a1eaf9fae 100644 --- a/tests/ImageSharp.Tests/ColorTests.cs +++ b/tests/ImageSharp.Tests/ColorTests.cs @@ -1,10 +1,255 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + namespace SixLabors.ImageSharp.Tests { public class ColorTests { + public class ConstructFrom + { + [Fact] + public void Rgba64() + { + Rgba64 source = new Rgba64(100, 2222, 3333, 4444); + + // Act: + Color color = new Color(source); + + // Assert: + Rgba64 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Rgba32() + { + Rgba32 source = new Rgba32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Rgba32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Argb32() + { + Argb32 source = new Argb32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Argb32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Bgra32() + { + Bgra32 source = new Bgra32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Bgra32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Rgb24() + { + Rgb24 source = new Rgb24(1, 22, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Rgb24 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Bgr24() + { + Bgr24 source = new Bgr24(1, 22, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Bgr24 data = color.ToPixel(); + Assert.Equal(source, data); + } + } + public class Cast + { + [Fact] + public void Rgba64() + { + Rgba64 source = new Rgba64(100, 2222, 3333, 4444); + + // Act: + Color color = source; + + // Assert: + Rgba64 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Rgba32() + { + Rgba32 source = new Rgba32(1, 22, 33, 231); + + // Act: + Color color = source; + + // Assert: + Rgba32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Argb32() + { + Argb32 source = new Argb32(1, 22, 33, 231); + + // Act: + Color color = source; + + // Assert: + Argb32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Bgra32() + { + Bgra32 source = new Bgra32(1, 22, 33, 231); + + // Act: + Color color = source; + + // Assert: + Bgra32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Rgb24() + { + Rgb24 source = new Rgb24(1, 22, 231); + + // Act: + Color color = source; + + // Assert: + Rgb24 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Bgr24() + { + Bgr24 source = new Bgr24(1, 22, 231); + + // Act: + Color color = source; + + // Assert: + Bgr24 data = color.ToPixel(); + Assert.Equal(source, data); + } + } + + public class CastTo + { + [Fact] + public void Rgba64() + { + Rgba64 source = new Rgba64(100, 2222, 3333, 4444); + + // Act: + Color color = new Color(source); + + // Assert: + Rgba64 data = color; + Assert.Equal(source, data); + } + + [Fact] + public void Rgba32() + { + Rgba32 source = new Rgba32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Rgba32 data = color; + Assert.Equal(source, data); + } + + [Fact] + public void Argb32() + { + Argb32 source = new Argb32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Argb32 data = color; + Assert.Equal(source, data); + } + + [Fact] + public void Bgra32() + { + Bgra32 source = new Bgra32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Bgra32 data = color; + Assert.Equal(source, data); + } + + [Fact] + public void Rgb24() + { + Rgb24 source = new Rgb24(1, 22, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Rgb24 data = color; + Assert.Equal(source, data); + } + + [Fact] + public void Bgr24() + { + Bgr24 source = new Bgr24(1, 22, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Bgr24 data = color; + Assert.Equal(source, data); + } + } } } \ No newline at end of file From e22c5b5c3f047c648bf654dbc38f036cd31c7490 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 6 May 2019 01:12:41 +0200 Subject: [PATCH 143/223] Pixel-agnostic Binarization processors --- src/ImageSharp/Color.cs | 2 +- .../Processing/BinaryDiffuseExtensions.cs | 47 +- .../Processing/BinaryDitherExtensions.cs | 40 +- .../Processing/BinaryThresholdExtensions.cs | 49 +- .../BinaryErrorDiffusionProcessor.cs | 68 +- .../BinaryErrorDiffusionProcessor{TPixel}.cs | 77 ++ .../BinaryOrderedDitherProcessor.cs | 67 +- .../BinaryOrderedDitherProcessor{TPixel}.cs | 75 ++ .../Binarization/BinaryThresholdProcessor.cs | 63 +- .../BinaryThresholdProcessor{TPixel}.cs | 70 ++ .../EdgeDetector2DProcessor{TPixel}.cs | 2 +- .../EdgeDetectorCompassProcessor{TPixel}.cs | 2 +- .../EdgeDetectorProcessor{TPixel}.cs | 2 +- .../Processors/Convolution/SobelProcessor.cs | 8 - .../Filters/GrayscaleBt709Processor.cs | 8 - .../Processors/ImageProcessorExtensions.cs | 15 + .../EntropyCropProcessor{TPixel}.cs | 4 +- .../Source/ImageSharp/Color.NamedColors.cs | 717 ++++++++++++++++++ .../Binarization/BinaryDitherTest.cs | 54 +- .../Binarization/BinaryThresholdTest.cs | 28 +- 20 files changed, 1114 insertions(+), 284 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Source/ImageSharp/Color.NamedColors.cs diff --git a/src/ImageSharp/Color.cs b/src/ImageSharp/Color.cs index 70c721060..6dae76c34 100644 --- a/src/ImageSharp/Color.cs +++ b/src/ImageSharp/Color.cs @@ -7,7 +7,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { - public readonly struct Color + public readonly partial struct Color { private readonly Rgba64 data; diff --git a/src/ImageSharp/Processing/BinaryDiffuseExtensions.cs b/src/ImageSharp/Processing/BinaryDiffuseExtensions.cs index 487b64e1c..7976daf25 100644 --- a/src/ImageSharp/Processing/BinaryDiffuseExtensions.cs +++ b/src/ImageSharp/Processing/BinaryDiffuseExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Binarization; using SixLabors.ImageSharp.Processing.Processors.Dithering; using SixLabors.Primitives; @@ -9,7 +8,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Defines extension methods to apply binary diffusion on an + /// Defines extension methods to apply binary diffusion on an /// using Mutate/Clone. /// public static class BinaryDiffuseExtensions @@ -17,19 +16,19 @@ namespace SixLabors.ImageSharp.Processing /// /// Dithers the image reducing it to two colors using error diffusion. /// - /// The pixel format. /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The to allow chaining of operations. - public static IImageProcessingContext BinaryDiffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold)); + public static IImageProcessingContext BinaryDiffuse( + this IImageProcessingContext source, + IErrorDiffuser diffuser, + float threshold) => + source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold)); /// /// Dithers the image reducing it to two colors using error diffusion. /// - /// The pixel format. /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. @@ -37,28 +36,33 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext BinaryDiffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold), rectangle); + public static IImageProcessingContext BinaryDiffuse( + this IImageProcessingContext source, + IErrorDiffuser diffuser, + float threshold, + Rectangle rectangle) => + source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold), rectangle); /// /// Dithers the image reducing it to two colors using error diffusion. /// - /// The pixel format. /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold /// The to allow chaining of operations. - public static IImageProcessingContext BinaryDiffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, TPixel upperColor, TPixel lowerColor) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold, upperColor, lowerColor)); + public static IImageProcessingContext BinaryDiffuse( + this IImageProcessingContext source, + IErrorDiffuser diffuser, + float threshold, + Color upperColor, + Color lowerColor) => + source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold, upperColor, lowerColor)); /// /// Dithers the image reducing it to two colors using error diffusion. /// - /// The pixel format. /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. @@ -68,8 +72,15 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext BinaryDiffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, TPixel upperColor, TPixel lowerColor, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryErrorDiffusionProcessor(diffuser, threshold, upperColor, lowerColor), rectangle); + public static IImageProcessingContext BinaryDiffuse( + this IImageProcessingContext source, + IErrorDiffuser diffuser, + float threshold, + Color upperColor, + Color lowerColor, + Rectangle rectangle) => + source.ApplyProcessor( + new BinaryErrorDiffusionProcessor(diffuser, threshold, upperColor, lowerColor), + rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/BinaryDitherExtensions.cs b/src/ImageSharp/Processing/BinaryDitherExtensions.cs index d8843dafa..b1e3d562e 100644 --- a/src/ImageSharp/Processing/BinaryDitherExtensions.cs +++ b/src/ImageSharp/Processing/BinaryDitherExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Binarization; using SixLabors.ImageSharp.Processing.Processors.Dithering; using SixLabors.Primitives; @@ -9,7 +8,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Defines extensions to apply binary dithering on an + /// Defines extensions to apply binary dithering on an /// using Mutate/Clone. /// public static class BinaryDitherExtensions @@ -17,45 +16,46 @@ namespace SixLabors.ImageSharp.Processing /// /// Dithers the image reducing it to two colors using ordered dithering. /// - /// The pixel format. /// The image this method extends. /// The ordered ditherer. /// The to allow chaining of operations. - public static IImageProcessingContext BinaryDither(this IImageProcessingContext source, IOrderedDither dither) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither)); + public static IImageProcessingContext + BinaryDither(this IImageProcessingContext source, IOrderedDither dither) => + source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither)); /// /// Dithers the image reducing it to two colors using ordered dithering. /// - /// The pixel format. /// The image this method extends. /// The ordered ditherer. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold /// The to allow chaining of operations. - public static IImageProcessingContext BinaryDither(this IImageProcessingContext source, IOrderedDither dither, TPixel upperColor, TPixel lowerColor) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither, upperColor, lowerColor)); + public static IImageProcessingContext BinaryDither( + this IImageProcessingContext source, + IOrderedDither dither, + Color upperColor, + Color lowerColor) => + source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither, upperColor, lowerColor)); /// /// Dithers the image reducing it to two colors using ordered dithering. /// - /// The pixel format. /// The image this method extends. /// The ordered ditherer. /// /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext BinaryDither(this IImageProcessingContext source, IOrderedDither dither, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither), rectangle); + public static IImageProcessingContext BinaryDither( + this IImageProcessingContext source, + IOrderedDither dither, + Rectangle rectangle) => + source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither), rectangle); /// /// Dithers the image reducing it to two colors using ordered dithering. /// - /// The pixel format. /// The image this method extends. /// The ordered ditherer. /// The color to use for pixels that are above the threshold. @@ -64,8 +64,12 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext BinaryDither(this IImageProcessingContext source, IOrderedDither dither, TPixel upperColor, TPixel lowerColor, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither, upperColor, lowerColor), rectangle); + public static IImageProcessingContext BinaryDither( + this IImageProcessingContext source, + IOrderedDither dither, + Color upperColor, + Color lowerColor, + Rectangle rectangle) => + source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither, upperColor, lowerColor), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/BinaryThresholdExtensions.cs b/src/ImageSharp/Processing/BinaryThresholdExtensions.cs index aecb78484..35aa681e3 100644 --- a/src/ImageSharp/Processing/BinaryThresholdExtensions.cs +++ b/src/ImageSharp/Processing/BinaryThresholdExtensions.cs @@ -1,14 +1,13 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Binarization; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Defines extension methods to apply binary thresholding on an + /// Defines extension methods to apply binary thresholding on an /// using Mutate/Clone. /// public static class BinaryThresholdExtensions @@ -16,45 +15,45 @@ namespace SixLabors.ImageSharp.Processing /// /// Applies binarization to the image splitting the pixels at the given threshold. /// - /// The pixel format. /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The to allow chaining of operations. - public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryThresholdProcessor(threshold)); + /// The to allow chaining of operations. + public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold) => + source.ApplyProcessor(new BinaryThresholdProcessor(threshold)); /// /// Applies binarization to the image splitting the pixels at the given threshold. /// - /// The pixel format. /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. - public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryThresholdProcessor(threshold), rectangle); + /// The to allow chaining of operations. + public static IImageProcessingContext BinaryThreshold( + this IImageProcessingContext source, + float threshold, + Rectangle rectangle) => + source.ApplyProcessor(new BinaryThresholdProcessor(threshold), rectangle); /// /// Applies binarization to the image splitting the pixels at the given threshold. /// - /// The pixel format. /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold - /// The to allow chaining of operations. - public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold, TPixel upperColor, TPixel lowerColor) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor)); + /// The to allow chaining of operations. + public static IImageProcessingContext BinaryThreshold( + this IImageProcessingContext source, + float threshold, + Color upperColor, + Color lowerColor) => + source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor)); /// /// Applies binarization to the image splitting the pixels at the given threshold. /// - /// The pixel format. /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. @@ -62,9 +61,13 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. - public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold, TPixel upperColor, TPixel lowerColor, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor), rectangle); + /// The to allow chaining of operations. + public static IImageProcessingContext BinaryThreshold( + this IImageProcessingContext source, + float threshold, + Color upperColor, + Color lowerColor, + Rectangle rectangle) => + source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor), rectangle); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor.cs index 32cc2f434..812983664 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor.cs @@ -2,22 +2,19 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.Advanced; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Dithering; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Binarization { /// /// Performs binary threshold filtering against an image using error diffusion. /// - /// The pixel format. - internal class BinaryErrorDiffusionProcessor : ImageProcessor - where TPixel : struct, IPixel + public class BinaryErrorDiffusionProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The error diffuser public BinaryErrorDiffusionProcessor(IErrorDiffuser diffuser) @@ -26,23 +23,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The error diffuser /// The threshold to split the image. Must be between 0 and 1. public BinaryErrorDiffusionProcessor(IErrorDiffuser diffuser, float threshold) - : this(diffuser, threshold, NamedColors.White, NamedColors.Black) + : this(diffuser, threshold, Color.White, Color.Black) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The error diffuser /// The threshold to split the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold. - public BinaryErrorDiffusionProcessor(IErrorDiffuser diffuser, float threshold, TPixel upperColor, TPixel lowerColor) + public BinaryErrorDiffusionProcessor(IErrorDiffuser diffuser, float threshold, Color upperColor, Color lowerColor) { Guard.NotNull(diffuser, nameof(diffuser)); Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold)); @@ -66,57 +63,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// /// Gets the color to use for pixels that are above the threshold. /// - public TPixel UpperColor { get; } + public Color UpperColor { get; } /// /// Gets the color to use for pixels that fall below the threshold. /// - public TPixel LowerColor { get; } + public Color LowerColor { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - byte threshold = (byte)MathF.Round(this.Threshold * 255F); - bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); - - var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); - int startY = interest.Y; - int endY = interest.Bottom; - int startX = interest.X; - int endX = interest.Right; - - // Collect the values before looping so we can reduce our calculation count for identical sibling pixels - TPixel sourcePixel = source[startX, startY]; - TPixel previousPixel = sourcePixel; - Rgba32 rgba = default; - sourcePixel.ToRgba32(ref rgba); - - // Convert to grayscale using ITU-R Recommendation BT.709 if required - byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); - - for (int y = startY; y < endY; y++) - { - Span row = source.GetPixelRowSpan(y); - - for (int x = startX; x < endX; x++) - { - sourcePixel = row[x]; - - // Check if this is the same as the last pixel. If so use that value - // rather than calculating it again. This is an inexpensive optimization. - if (!previousPixel.Equals(sourcePixel)) - { - sourcePixel.ToRgba32(ref rgba); - luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); - - // Setup the previous pointer - previousPixel = sourcePixel; - } - - TPixel transformedPixel = luminance >= threshold ? this.UpperColor : this.LowerColor; - this.Diffuser.Dither(source, sourcePixel, transformedPixel, x, y, startX, startY, endX, endY); - } - } + return new BinaryErrorDiffusionProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor{TPixel}.cs new file mode 100644 index 000000000..e3828aeb6 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor{TPixel}.cs @@ -0,0 +1,77 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Dithering; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Binarization +{ + /// + /// Performs binary threshold filtering against an image using error diffusion. + /// + /// The pixel format. + internal class BinaryErrorDiffusionProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly BinaryErrorDiffusionProcessor definition; + + public BinaryErrorDiffusionProcessor(BinaryErrorDiffusionProcessor definition) + { + this.definition = definition; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + TPixel upperColor = this.definition.UpperColor.ToPixel(); + TPixel lowerColor = this.definition.LowerColor.ToPixel(); + IErrorDiffuser diffuser = this.definition.Diffuser; + + byte threshold = (byte)MathF.Round(this.definition.Threshold * 255F); + bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); + + var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); + int startY = interest.Y; + int endY = interest.Bottom; + int startX = interest.X; + int endX = interest.Right; + + // Collect the values before looping so we can reduce our calculation count for identical sibling pixels + TPixel sourcePixel = source[startX, startY]; + TPixel previousPixel = sourcePixel; + Rgba32 rgba = default; + sourcePixel.ToRgba32(ref rgba); + + // Convert to grayscale using ITU-R Recommendation BT.709 if required + byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + + for (int y = startY; y < endY; y++) + { + Span row = source.GetPixelRowSpan(y); + + for (int x = startX; x < endX; x++) + { + sourcePixel = row[x]; + + // Check if this is the same as the last pixel. If so use that value + // rather than calculating it again. This is an inexpensive optimization. + if (!previousPixel.Equals(sourcePixel)) + { + sourcePixel.ToRgba32(ref rgba); + luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + + // Setup the previous pointer + previousPixel = sourcePixel; + } + + TPixel transformedPixel = luminance >= threshold ? upperColor : lowerColor; + diffuser.Dither(source, sourcePixel, transformedPixel, x, y, startX, startY, endX, endY); + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs index cfdaf107c..99c57171c 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs @@ -2,36 +2,30 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.Advanced; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Dithering; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Binarization { - /// - /// Performs binary threshold filtering against an image using ordered dithering. - /// - /// The pixel format. - internal class BinaryOrderedDitherProcessor : ImageProcessor - where TPixel : struct, IPixel + public class BinaryOrderedDitherProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The ordered ditherer. public BinaryOrderedDitherProcessor(IOrderedDither dither) - : this(dither, NamedColors.White, NamedColors.Black) + : this(dither, Color.White, Color.Black) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The ordered ditherer. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold. - public BinaryOrderedDitherProcessor(IOrderedDither dither, TPixel upperColor, TPixel lowerColor) + public BinaryOrderedDitherProcessor(IOrderedDither dither, Color upperColor, Color lowerColor) { this.Dither = dither ?? throw new ArgumentNullException(nameof(dither)); this.UpperColor = upperColor; @@ -46,55 +40,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// /// Gets the color to use for pixels that are above the threshold. /// - public TPixel UpperColor { get; } + public Color UpperColor { get; } /// /// Gets the color to use for pixels that fall below the threshold. /// - public TPixel LowerColor { get; } + public Color LowerColor { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); - - var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); - int startY = interest.Y; - int endY = interest.Bottom; - int startX = interest.X; - int endX = interest.Right; - - // Collect the values before looping so we can reduce our calculation count for identical sibling pixels - TPixel sourcePixel = source[startX, startY]; - TPixel previousPixel = sourcePixel; - Rgba32 rgba = default; - sourcePixel.ToRgba32(ref rgba); - - // Convert to grayscale using ITU-R Recommendation BT.709 if required - byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); - - for (int y = startY; y < endY; y++) - { - Span row = source.GetPixelRowSpan(y); - - for (int x = startX; x < endX; x++) - { - sourcePixel = row[x]; - - // Check if this is the same as the last pixel. If so use that value - // rather than calculating it again. This is an inexpensive optimization. - if (!previousPixel.Equals(sourcePixel)) - { - sourcePixel.ToRgba32(ref rgba); - luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); - - // Setup the previous pointer - previousPixel = sourcePixel; - } - - this.Dither.Dither(source, sourcePixel, this.UpperColor, this.LowerColor, luminance, x, y); - } - } + return new BinaryOrderedDitherProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor{TPixel}.cs new file mode 100644 index 000000000..b3d174dfb --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor{TPixel}.cs @@ -0,0 +1,75 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Dithering; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Binarization +{ + /// + /// Performs binary threshold filtering against an image using ordered dithering. + /// + /// The pixel format. + internal class BinaryOrderedDitherProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly BinaryOrderedDitherProcessor definition; + + public BinaryOrderedDitherProcessor(BinaryOrderedDitherProcessor definition) + { + this.definition = definition; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + IOrderedDither dither = this.definition.Dither; + TPixel upperColor = this.definition.UpperColor.ToPixel(); + TPixel lowerColor = this.definition.LowerColor.ToPixel(); + + bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); + + var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); + int startY = interest.Y; + int endY = interest.Bottom; + int startX = interest.X; + int endX = interest.Right; + + // Collect the values before looping so we can reduce our calculation count for identical sibling pixels + TPixel sourcePixel = source[startX, startY]; + TPixel previousPixel = sourcePixel; + Rgba32 rgba = default; + sourcePixel.ToRgba32(ref rgba); + + // Convert to grayscale using ITU-R Recommendation BT.709 if required + byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + + for (int y = startY; y < endY; y++) + { + Span row = source.GetPixelRowSpan(y); + + for (int x = startX; x < endX; x++) + { + sourcePixel = row[x]; + + // Check if this is the same as the last pixel. If so use that value + // rather than calculating it again. This is an inexpensive optimization. + if (!previousPixel.Equals(sourcePixel)) + { + sourcePixel.ToRgba32(ref rgba); + luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + + // Setup the previous pointer + previousPixel = sourcePixel; + } + + dither.Dither(source, sourcePixel, upperColor, lowerColor, luminance, x, y); + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs index 67dcfc7f1..50086936c 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs @@ -3,36 +3,31 @@ using System; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Binarization { /// /// Performs simple binary threshold filtering against an image. /// - /// The pixel format. - internal class BinaryThresholdProcessor : ImageProcessor - where TPixel : struct, IPixel + public class BinaryThresholdProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The threshold to split the image. Must be between 0 and 1. public BinaryThresholdProcessor(float threshold) - : this(threshold, NamedColors.White, NamedColors.Black) + : this(threshold, Color.White, Color.Black) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The threshold to split the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold. - public BinaryThresholdProcessor(float threshold, TPixel upperColor, TPixel lowerColor) + public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor) { Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold)); this.Threshold = threshold; @@ -48,54 +43,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// /// Gets or sets the color to use for pixels that are above the threshold. /// - public TPixel UpperColor { get; set; } + public Color UpperColor { get; } /// /// Gets or sets the color to use for pixels that fall below the threshold. /// - public TPixel LowerColor { get; set; } + public Color LowerColor { get; } - /// - protected override void OnFrameApply( - ImageFrame source, - Rectangle sourceRectangle, - Configuration configuration) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - byte threshold = (byte)MathF.Round(this.Threshold * 255F); - TPixel upper = this.UpperColor; - TPixel lower = this.LowerColor; - - var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); - int startY = interest.Y; - int endY = interest.Bottom; - int startX = interest.X; - int endX = interest.Right; - - bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); - - var workingRect = Rectangle.FromLTRB(startX, startY, endX, endY); - - ParallelHelper.IterateRows( - workingRect, - configuration, - rows => - { - Rgba32 rgba = default; - for (int y = rows.Min; y < rows.Max; y++) - { - Span row = source.GetPixelRowSpan(y); - - for (int x = startX; x < endX; x++) - { - ref TPixel color = ref row[x]; - color.ToRgba32(ref rgba); - - // Convert to grayscale using ITU-R Recommendation BT.709 if required - byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); - color = luminance >= threshold ? upper : lower; - } - } - }); + return new BinaryThresholdProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs new file mode 100644 index 000000000..0d90d3647 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs @@ -0,0 +1,70 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Binarization +{ + /// + /// Performs simple binary threshold filtering against an image. + /// + /// The pixel format. + internal class BinaryThresholdProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly BinaryThresholdProcessor definition; + + public BinaryThresholdProcessor(BinaryThresholdProcessor definition) + { + this.definition = definition; + } + + /// + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) + { + byte threshold = (byte)MathF.Round(this.definition.Threshold * 255F); + TPixel upper = this.definition.UpperColor.ToPixel(); + TPixel lower = this.definition.LowerColor.ToPixel(); + + var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); + int startY = interest.Y; + int endY = interest.Bottom; + int startX = interest.X; + int endX = interest.Right; + + bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); + + var workingRect = Rectangle.FromLTRB(startX, startY, endX, endY); + + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + Rgba32 rgba = default; + for (int y = rows.Min; y < rows.Max; y++) + { + Span row = source.GetPixelRowSpan(y); + + for (int x = startX; x < endX; x++) + { + ref TPixel color = ref row[x]; + color.ToRgba32(ref rgba); + + // Convert to grayscale using ITU-R Recommendation BT.709 if required + byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + color = luminance >= threshold ? upper : lower; + } + } + }); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs index 5daf14fc3..f6771288f 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { if (this.Grayscale) { - new GrayscaleBt709Processor(1F).ApplyToFrame(source, sourceRectangle, configuration); + new GrayscaleBt709Processor(1F).Apply(source, sourceRectangle, configuration); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs index 227003195..5995ac844 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { if (this.Grayscale) { - new GrayscaleBt709Processor(1F).ApplyToFrame(source, sourceRectangle, configuration); + new GrayscaleBt709Processor(1F).Apply(source, sourceRectangle, configuration); } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs index 026313cc1..041c54803 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { if (this.Grayscale) { - new GrayscaleBt709Processor(1F).ApplyToFrame(source, sourceRectangle, configuration); + new GrayscaleBt709Processor(1F).Apply(source, sourceRectangle, configuration); } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs index bc4339e05..3d5d1e7bf 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/SobelProcessor.cs @@ -26,13 +26,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { return new EdgeDetector2DProcessor(SobelKernels.SobelX, SobelKernels.SobelY, this.Grayscale); } - - // TODO: Move this to an appropriate extension method if possible. - internal void ApplyToFrame(ImageFrame frame, Rectangle sourceRectangle, Configuration configuration) - where TPixel : struct, IPixel - { - var processorImpl = new EdgeDetector2DProcessor(SobelKernels.SobelX, SobelKernels.SobelY, this.Grayscale); - processorImpl.Apply(frame, sourceRectangle, configuration); - } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs index 2d7d2a1ea..ae6d5f6f7 100644 --- a/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs +++ b/src/ImageSharp/Processing/Processors/Filters/GrayscaleBt709Processor.cs @@ -25,13 +25,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// Gets the proportion of the conversion. /// public float Amount { get; } - - // TODO: Move this to an appropriate extension method if possible. - internal void ApplyToFrame(ImageFrame frame, Rectangle sourceRectangle, Configuration configuration) - where TPixel : struct, IPixel - { - var processorImpl = new FilterProcessor(new GrayscaleBt709Processor(1F)); - processorImpl.Apply(frame, sourceRectangle, configuration); - } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs b/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs index 762d761c6..91b2b30d0 100644 --- a/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs +++ b/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs @@ -14,6 +14,21 @@ namespace SixLabors.ImageSharp.Processing.Processors source.AcceptVisitor(visitor); } + /// + /// Apply an to a frame. + /// Only works from processors implemented by an subclass. + /// + internal static void Apply( + this IImageProcessor processor, + ImageFrame frame, + Rectangle sourceRectangle, + Configuration configuration) + where TPixel : struct, IPixel + { + var processorImpl = (ImageProcessor)processor.CreatePixelSpecificProcessor(); + processorImpl.Apply(frame, sourceRectangle, configuration); + } + private class ApplyVisitor : IImageVisitor { private readonly IImageProcessor processor; diff --git a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs index eaeb6939e..4bfeb2519 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs @@ -38,10 +38,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Configuration configuration = source.GetConfiguration(); // Detect the edges. - new SobelProcessor(false).ApplyToFrame(temp, sourceRectangle, configuration); + new SobelProcessor(false).Apply(temp, sourceRectangle, configuration); // Apply threshold binarization filter. - new BinaryThresholdProcessor(this.definition.Threshold).Apply(temp, sourceRectangle, configuration); + new BinaryThresholdProcessor(this.definition.Threshold).Apply(temp, sourceRectangle, configuration); // Search for the first white pixels rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0); diff --git a/src/ImageSharp/Source/ImageSharp/Color.NamedColors.cs b/src/ImageSharp/Source/ImageSharp/Color.NamedColors.cs new file mode 100644 index 000000000..e00329d89 --- /dev/null +++ b/src/ImageSharp/Source/ImageSharp/Color.NamedColors.cs @@ -0,0 +1,717 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. +namespace SixLabors.ImageSharp +{ + public readonly partial struct Color + { + /// + /// Represents a matching the W3C definition that has an hex value of #F0F8FF. + /// + public static readonly Color AliceBlue = FromRgba(240, 248, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FAEBD7. + /// + public static readonly Color AntiqueWhite = FromRgba(250, 235, 215, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #00FFFF. + /// + public static readonly Color Aqua = FromRgba(0, 255, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #7FFFD4. + /// + public static readonly Color Aquamarine = FromRgba(127, 255, 212, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #F0FFFF. + /// + public static readonly Color Azure = FromRgba(240, 255, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #F5F5DC. + /// + public static readonly Color Beige = FromRgba(245, 245, 220, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFE4C4. + /// + public static readonly Color Bisque = FromRgba(255, 228, 196, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #000000. + /// + public static readonly Color Black = FromRgba(0, 0, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFEBCD. + /// + public static readonly Color BlanchedAlmond = FromRgba(255, 235, 205, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #0000FF. + /// + public static readonly Color Blue = FromRgba(0, 0, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #8A2BE2. + /// + public static readonly Color BlueViolet = FromRgba(138, 43, 226, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #A52A2A. + /// + public static readonly Color Brown = FromRgba(165, 42, 42, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #DEB887. + /// + public static readonly Color BurlyWood = FromRgba(222, 184, 135, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #5F9EA0. + /// + public static readonly Color CadetBlue = FromRgba(95, 158, 160, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #7FFF00. + /// + public static readonly Color Chartreuse = FromRgba(127, 255, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #D2691E. + /// + public static readonly Color Chocolate = FromRgba(210, 105, 30, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FF7F50. + /// + public static readonly Color Coral = FromRgba(255, 127, 80, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #6495ED. + /// + public static readonly Color CornflowerBlue = FromRgba(100, 149, 237, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFF8DC. + /// + public static readonly Color Cornsilk = FromRgba(255, 248, 220, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #DC143C. + /// + public static readonly Color Crimson = FromRgba(220, 20, 60, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #00FFFF. + /// + public static readonly Color Cyan = FromRgba(0, 255, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #00008B. + /// + public static readonly Color DarkBlue = FromRgba(0, 0, 139, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #008B8B. + /// + public static readonly Color DarkCyan = FromRgba(0, 139, 139, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #B8860B. + /// + public static readonly Color DarkGoldenrod = FromRgba(184, 134, 11, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #A9A9A9. + /// + public static readonly Color DarkGray = FromRgba(169, 169, 169, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #006400. + /// + public static readonly Color DarkGreen = FromRgba(0, 100, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #BDB76B. + /// + public static readonly Color DarkKhaki = FromRgba(189, 183, 107, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #8B008B. + /// + public static readonly Color DarkMagenta = FromRgba(139, 0, 139, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #556B2F. + /// + public static readonly Color DarkOliveGreen = FromRgba(85, 107, 47, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FF8C00. + /// + public static readonly Color DarkOrange = FromRgba(255, 140, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #9932CC. + /// + public static readonly Color DarkOrchid = FromRgba(153, 50, 204, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #8B0000. + /// + public static readonly Color DarkRed = FromRgba(139, 0, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #E9967A. + /// + public static readonly Color DarkSalmon = FromRgba(233, 150, 122, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #8FBC8B. + /// + public static readonly Color DarkSeaGreen = FromRgba(143, 188, 139, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #483D8B. + /// + public static readonly Color DarkSlateBlue = FromRgba(72, 61, 139, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #2F4F4F. + /// + public static readonly Color DarkSlateGray = FromRgba(47, 79, 79, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #00CED1. + /// + public static readonly Color DarkTurquoise = FromRgba(0, 206, 209, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #9400D3. + /// + public static readonly Color DarkViolet = FromRgba(148, 0, 211, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FF1493. + /// + public static readonly Color DeepPink = FromRgba(255, 20, 147, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #00BFFF. + /// + public static readonly Color DeepSkyBlue = FromRgba(0, 191, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #696969. + /// + public static readonly Color DimGray = FromRgba(105, 105, 105, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #1E90FF. + /// + public static readonly Color DodgerBlue = FromRgba(30, 144, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #B22222. + /// + public static readonly Color Firebrick = FromRgba(178, 34, 34, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFFAF0. + /// + public static readonly Color FloralWhite = FromRgba(255, 250, 240, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #228B22. + /// + public static readonly Color ForestGreen = FromRgba(34, 139, 34, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FF00FF. + /// + public static readonly Color Fuchsia = FromRgba(255, 0, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #DCDCDC. + /// + public static readonly Color Gainsboro = FromRgba(220, 220, 220, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #F8F8FF. + /// + public static readonly Color GhostWhite = FromRgba(248, 248, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFD700. + /// + public static readonly Color Gold = FromRgba(255, 215, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #DAA520. + /// + public static readonly Color Goldenrod = FromRgba(218, 165, 32, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #808080. + /// + public static readonly Color Gray = FromRgba(128, 128, 128, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #008000. + /// + public static readonly Color Green = FromRgba(0, 128, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #ADFF2F. + /// + public static readonly Color GreenYellow = FromRgba(173, 255, 47, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #F0FFF0. + /// + public static readonly Color Honeydew = FromRgba(240, 255, 240, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FF69B4. + /// + public static readonly Color HotPink = FromRgba(255, 105, 180, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #CD5C5C. + /// + public static readonly Color IndianRed = FromRgba(205, 92, 92, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #4B0082. + /// + public static readonly Color Indigo = FromRgba(75, 0, 130, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFFFF0. + /// + public static readonly Color Ivory = FromRgba(255, 255, 240, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #F0E68C. + /// + public static readonly Color Khaki = FromRgba(240, 230, 140, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #E6E6FA. + /// + public static readonly Color Lavender = FromRgba(230, 230, 250, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFF0F5. + /// + public static readonly Color LavenderBlush = FromRgba(255, 240, 245, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #7CFC00. + /// + public static readonly Color LawnGreen = FromRgba(124, 252, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFFACD. + /// + public static readonly Color LemonChiffon = FromRgba(255, 250, 205, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #ADD8E6. + /// + public static readonly Color LightBlue = FromRgba(173, 216, 230, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #F08080. + /// + public static readonly Color LightCoral = FromRgba(240, 128, 128, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #E0FFFF. + /// + public static readonly Color LightCyan = FromRgba(224, 255, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FAFAD2. + /// + public static readonly Color LightGoldenrodYellow = FromRgba(250, 250, 210, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #D3D3D3. + /// + public static readonly Color LightGray = FromRgba(211, 211, 211, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #90EE90. + /// + public static readonly Color LightGreen = FromRgba(144, 238, 144, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFB6C1. + /// + public static readonly Color LightPink = FromRgba(255, 182, 193, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFA07A. + /// + public static readonly Color LightSalmon = FromRgba(255, 160, 122, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #20B2AA. + /// + public static readonly Color LightSeaGreen = FromRgba(32, 178, 170, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #87CEFA. + /// + public static readonly Color LightSkyBlue = FromRgba(135, 206, 250, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #778899. + /// + public static readonly Color LightSlateGray = FromRgba(119, 136, 153, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #B0C4DE. + /// + public static readonly Color LightSteelBlue = FromRgba(176, 196, 222, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFFFE0. + /// + public static readonly Color LightYellow = FromRgba(255, 255, 224, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #00FF00. + /// + public static readonly Color Lime = FromRgba(0, 255, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #32CD32. + /// + public static readonly Color LimeGreen = FromRgba(50, 205, 50, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FAF0E6. + /// + public static readonly Color Linen = FromRgba(250, 240, 230, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FF00FF. + /// + public static readonly Color Magenta = FromRgba(255, 0, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #800000. + /// + public static readonly Color Maroon = FromRgba(128, 0, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #66CDAA. + /// + public static readonly Color MediumAquamarine = FromRgba(102, 205, 170, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #0000CD. + /// + public static readonly Color MediumBlue = FromRgba(0, 0, 205, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #BA55D3. + /// + public static readonly Color MediumOrchid = FromRgba(186, 85, 211, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #9370DB. + /// + public static readonly Color MediumPurple = FromRgba(147, 112, 219, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #3CB371. + /// + public static readonly Color MediumSeaGreen = FromRgba(60, 179, 113, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #7B68EE. + /// + public static readonly Color MediumSlateBlue = FromRgba(123, 104, 238, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #00FA9A. + /// + public static readonly Color MediumSpringGreen = FromRgba(0, 250, 154, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #48D1CC. + /// + public static readonly Color MediumTurquoise = FromRgba(72, 209, 204, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #C71585. + /// + public static readonly Color MediumVioletRed = FromRgba(199, 21, 133, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #191970. + /// + public static readonly Color MidnightBlue = FromRgba(25, 25, 112, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #F5FFFA. + /// + public static readonly Color MintCream = FromRgba(245, 255, 250, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFE4E1. + /// + public static readonly Color MistyRose = FromRgba(255, 228, 225, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFE4B5. + /// + public static readonly Color Moccasin = FromRgba(255, 228, 181, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFDEAD. + /// + public static readonly Color NavajoWhite = FromRgba(255, 222, 173, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #000080. + /// + public static readonly Color Navy = FromRgba(0, 0, 128, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FDF5E6. + /// + public static readonly Color OldLace = FromRgba(253, 245, 230, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #808000. + /// + public static readonly Color Olive = FromRgba(128, 128, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #6B8E23. + /// + public static readonly Color OliveDrab = FromRgba(107, 142, 35, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFA500. + /// + public static readonly Color Orange = FromRgba(255, 165, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FF4500. + /// + public static readonly Color OrangeRed = FromRgba(255, 69, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #DA70D6. + /// + public static readonly Color Orchid = FromRgba(218, 112, 214, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #EEE8AA. + /// + public static readonly Color PaleGoldenrod = FromRgba(238, 232, 170, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #98FB98. + /// + public static readonly Color PaleGreen = FromRgba(152, 251, 152, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #AFEEEE. + /// + public static readonly Color PaleTurquoise = FromRgba(175, 238, 238, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #DB7093. + /// + public static readonly Color PaleVioletRed = FromRgba(219, 112, 147, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFEFD5. + /// + public static readonly Color PapayaWhip = FromRgba(255, 239, 213, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFDAB9. + /// + public static readonly Color PeachPuff = FromRgba(255, 218, 185, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #CD853F. + /// + public static readonly Color Peru = FromRgba(205, 133, 63, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFC0CB. + /// + public static readonly Color Pink = FromRgba(255, 192, 203, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #DDA0DD. + /// + public static readonly Color Plum = FromRgba(221, 160, 221, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #B0E0E6. + /// + public static readonly Color PowderBlue = FromRgba(176, 224, 230, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #800080. + /// + public static readonly Color Purple = FromRgba(128, 0, 128, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #663399. + /// + public static readonly Color RebeccaPurple = FromRgba(102, 51, 153, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FF0000. + /// + public static readonly Color Red = FromRgba(255, 0, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #BC8F8F. + /// + public static readonly Color RosyBrown = FromRgba(188, 143, 143, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #4169E1. + /// + public static readonly Color RoyalBlue = FromRgba(65, 105, 225, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #8B4513. + /// + public static readonly Color SaddleBrown = FromRgba(139, 69, 19, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FA8072. + /// + public static readonly Color Salmon = FromRgba(250, 128, 114, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #F4A460. + /// + public static readonly Color SandyBrown = FromRgba(244, 164, 96, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #2E8B57. + /// + public static readonly Color SeaGreen = FromRgba(46, 139, 87, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFF5EE. + /// + public static readonly Color SeaShell = FromRgba(255, 245, 238, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #A0522D. + /// + public static readonly Color Sienna = FromRgba(160, 82, 45, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #C0C0C0. + /// + public static readonly Color Silver = FromRgba(192, 192, 192, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #87CEEB. + /// + public static readonly Color SkyBlue = FromRgba(135, 206, 235, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #6A5ACD. + /// + public static readonly Color SlateBlue = FromRgba(106, 90, 205, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #708090. + /// + public static readonly Color SlateGray = FromRgba(112, 128, 144, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFFAFA. + /// + public static readonly Color Snow = FromRgba(255, 250, 250, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #00FF7F. + /// + public static readonly Color SpringGreen = FromRgba(0, 255, 127, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #4682B4. + /// + public static readonly Color SteelBlue = FromRgba(70, 130, 180, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #D2B48C. + /// + public static readonly Color Tan = FromRgba(210, 180, 140, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #008080. + /// + public static readonly Color Teal = FromRgba(0, 128, 128, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #D8BFD8. + /// + public static readonly Color Thistle = FromRgba(216, 191, 216, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FF6347. + /// + public static readonly Color Tomato = FromRgba(255, 99, 71, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFFFFF. + /// + public static readonly Color Transparent = FromRgba(255, 255, 255, 0); + + /// + /// Represents a matching the W3C definition that has an hex value of #40E0D0. + /// + public static readonly Color Turquoise = FromRgba(64, 224, 208, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #EE82EE. + /// + public static readonly Color Violet = FromRgba(238, 130, 238, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #F5DEB3. + /// + public static readonly Color Wheat = FromRgba(245, 222, 179, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFFFFF. + /// + public static readonly Color White = FromRgba(255, 255, 255, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #F5F5F5. + /// + public static readonly Color WhiteSmoke = FromRgba(245, 245, 245, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #FFFF00. + /// + public static readonly Color Yellow = FromRgba(255, 255, 0, 255); + + /// + /// Represents a matching the W3C definition that has an hex value of #9ACD32. + /// + public static readonly Color YellowGreen = FromRgba(154, 205, 50, 255); + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Binarization/BinaryDitherTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/BinaryDitherTest.cs index 5f6e825f6..dcbf0ca03 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/BinaryDitherTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/BinaryDitherTest.cs @@ -25,38 +25,38 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization public void BinaryDither_CorrectProcessor() { this.operations.BinaryDither(this.orderedDither); - BinaryOrderedDitherProcessor p = this.Verify>(); + BinaryOrderedDitherProcessor p = this.Verify(); Assert.Equal(this.orderedDither, p.Dither); - Assert.Equal(NamedColors.White, p.UpperColor); - Assert.Equal(NamedColors.Black, p.LowerColor); + Assert.Equal(Color.White, p.UpperColor); + Assert.Equal(Color.Black, p.LowerColor); } [Fact] public void BinaryDither_rect_CorrectProcessor() { this.operations.BinaryDither(this.orderedDither, this.rect); - BinaryOrderedDitherProcessor p = this.Verify>(this.rect); + BinaryOrderedDitherProcessor p = this.Verify(this.rect); Assert.Equal(this.orderedDither, p.Dither); - Assert.Equal(NamedColors.White, p.UpperColor); - Assert.Equal(NamedColors.Black, p.LowerColor); + Assert.Equal(Color.White, p.UpperColor); + Assert.Equal(Color.Black, p.LowerColor); } [Fact] public void BinaryDither_index_CorrectProcessor() { - this.operations.BinaryDither(this.orderedDither, NamedColors.Yellow, NamedColors.HotPink); - BinaryOrderedDitherProcessor p = this.Verify>(); + this.operations.BinaryDither(this.orderedDither, Color.Yellow, Color.HotPink); + BinaryOrderedDitherProcessor p = this.Verify(); Assert.Equal(this.orderedDither, p.Dither); - Assert.Equal(NamedColors.Yellow, p.UpperColor); - Assert.Equal(NamedColors.HotPink, p.LowerColor); + Assert.Equal(Color.Yellow, p.UpperColor); + Assert.Equal(Color.HotPink, p.LowerColor); } [Fact] public void BinaryDither_index_rect_CorrectProcessor() { - this.operations.BinaryDither(this.orderedDither, NamedColors.Yellow, NamedColors.HotPink, this.rect); - BinaryOrderedDitherProcessor p = this.Verify>(this.rect); + this.operations.BinaryDither(this.orderedDither, Color.Yellow, Color.HotPink, this.rect); + BinaryOrderedDitherProcessor p = this.Verify(this.rect); Assert.Equal(this.orderedDither, p.Dither); - Assert.Equal(NamedColors.HotPink, p.LowerColor); + Assert.Equal(Color.HotPink, p.LowerColor); } @@ -64,44 +64,44 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization public void BinaryDither_ErrorDiffuser_CorrectProcessor() { this.operations.BinaryDiffuse(this.errorDiffuser, .4F); - BinaryErrorDiffusionProcessor p = this.Verify>(); + BinaryErrorDiffusionProcessor p = this.Verify(); Assert.Equal(this.errorDiffuser, p.Diffuser); Assert.Equal(.4F, p.Threshold); - Assert.Equal(NamedColors.White, p.UpperColor); - Assert.Equal(NamedColors.Black, p.LowerColor); + Assert.Equal(Color.White, p.UpperColor); + Assert.Equal(Color.Black, p.LowerColor); } [Fact] public void BinaryDither_ErrorDiffuser_rect_CorrectProcessor() { this.operations.BinaryDiffuse(this.errorDiffuser, .3F, this.rect); - BinaryErrorDiffusionProcessor p = this.Verify>(this.rect); + BinaryErrorDiffusionProcessor p = this.Verify(this.rect); Assert.Equal(this.errorDiffuser, p.Diffuser); Assert.Equal(.3F, p.Threshold); - Assert.Equal(NamedColors.White, p.UpperColor); - Assert.Equal(NamedColors.Black, p.LowerColor); + Assert.Equal(Color.White, p.UpperColor); + Assert.Equal(Color.Black, p.LowerColor); } [Fact] public void BinaryDither_ErrorDiffuser_CorrectProcessorWithColors() { - this.operations.BinaryDiffuse(this.errorDiffuser, .5F, NamedColors.HotPink, NamedColors.Yellow); - BinaryErrorDiffusionProcessor p = this.Verify>(); + this.operations.BinaryDiffuse(this.errorDiffuser, .5F, Color.HotPink, Color.Yellow); + BinaryErrorDiffusionProcessor p = this.Verify(); Assert.Equal(this.errorDiffuser, p.Diffuser); Assert.Equal(.5F, p.Threshold); - Assert.Equal(NamedColors.HotPink, p.UpperColor); - Assert.Equal(NamedColors.Yellow, p.LowerColor); + Assert.Equal(Color.HotPink, p.UpperColor); + Assert.Equal(Color.Yellow, p.LowerColor); } [Fact] public void BinaryDither_ErrorDiffuser_rect_CorrectProcessorWithColors() { - this.operations.BinaryDiffuse(this.errorDiffuser, .5F, NamedColors.HotPink, NamedColors.Yellow, this.rect); - BinaryErrorDiffusionProcessor p = this.Verify>(this.rect); + this.operations.BinaryDiffuse(this.errorDiffuser, .5F, Color.HotPink, Color.Yellow, this.rect); + BinaryErrorDiffusionProcessor p = this.Verify(this.rect); Assert.Equal(this.errorDiffuser, p.Diffuser); Assert.Equal(.5F, p.Threshold); - Assert.Equal(NamedColors.HotPink, p.UpperColor); - Assert.Equal(NamedColors.Yellow, p.LowerColor); + Assert.Equal(Color.HotPink, p.UpperColor); + Assert.Equal(Color.Yellow, p.LowerColor); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs index 569c4ba21..f0fcba181 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs @@ -15,40 +15,40 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization public void BinaryThreshold_CorrectProcessor() { this.operations.BinaryThreshold(.23f); - BinaryThresholdProcessor p = this.Verify>(); + BinaryThresholdProcessor p = this.Verify(); Assert.Equal(.23f, p.Threshold); - Assert.Equal(NamedColors.White, p.UpperColor); - Assert.Equal(NamedColors.Black, p.LowerColor); + Assert.Equal(Color.White, p.UpperColor); + Assert.Equal(Color.Black, p.LowerColor); } [Fact] public void BinaryThreshold_rect_CorrectProcessor() { this.operations.BinaryThreshold(.93f, this.rect); - BinaryThresholdProcessor p = this.Verify>(this.rect); + BinaryThresholdProcessor p = this.Verify(this.rect); Assert.Equal(.93f, p.Threshold); - Assert.Equal(NamedColors.White, p.UpperColor); - Assert.Equal(NamedColors.Black, p.LowerColor); + Assert.Equal(Color.White, p.UpperColor); + Assert.Equal(Color.Black, p.LowerColor); } [Fact] public void BinaryThreshold_CorrectProcessorWithUpperLower() { - this.operations.BinaryThreshold(.23f, NamedColors.HotPink, NamedColors.Yellow); - BinaryThresholdProcessor p = this.Verify>(); + this.operations.BinaryThreshold(.23f, Color.HotPink, Color.Yellow); + BinaryThresholdProcessor p = this.Verify(); Assert.Equal(.23f, p.Threshold); - Assert.Equal(NamedColors.HotPink, p.UpperColor); - Assert.Equal(NamedColors.Yellow, p.LowerColor); + Assert.Equal(Color.HotPink, p.UpperColor); + Assert.Equal(Color.Yellow, p.LowerColor); } [Fact] public void BinaryThreshold_rect_CorrectProcessorWithUpperLower() { - this.operations.BinaryThreshold(.93f, NamedColors.HotPink, NamedColors.Yellow, this.rect); - BinaryThresholdProcessor p = this.Verify>(this.rect); + this.operations.BinaryThreshold(.93f, Color.HotPink, Color.Yellow, this.rect); + BinaryThresholdProcessor p = this.Verify(this.rect); Assert.Equal(.93f, p.Threshold); - Assert.Equal(NamedColors.HotPink, p.UpperColor); - Assert.Equal(NamedColors.Yellow, p.LowerColor); + Assert.Equal(Color.HotPink, p.UpperColor); + Assert.Equal(Color.Yellow, p.LowerColor); } } } \ No newline at end of file From e5e3768f5a369e35cb965313128912d98c92db6f Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 6 May 2019 22:58:17 +0200 Subject: [PATCH 144/223] Implement WernerPalette and WebSafePalette for Color --- src/ImageSharp/Color.cs | 83 ------ .../ImageSharp => Color}/Color.NamedColors.cs | 1 + src/ImageSharp/Color/Color.WebSafePalette.cs | 163 +++++++++++ src/ImageSharp/Color/Color.WernerPalette.cs | 132 +++++++++ src/ImageSharp/Color/Color.cs | 185 ++++++++++++ src/ImageSharp/ImageSharp.csproj.DotSettings | 1 + .../Color/ColorTests.CastFrom.cs | 93 ++++++ .../Color/ColorTests.CastTo.cs | 93 ++++++ .../Color/ColorTests.ConstructFrom.cs | 93 ++++++ tests/ImageSharp.Tests/Color/ColorTests.cs | 97 ++++++ .../Color/ReferencePalette.cs | 277 ++++++++++++++++++ tests/ImageSharp.Tests/ColorTests.cs | 255 ---------------- 12 files changed, 1135 insertions(+), 338 deletions(-) delete mode 100644 src/ImageSharp/Color.cs rename src/ImageSharp/{Source/ImageSharp => Color}/Color.NamedColors.cs (99%) create mode 100644 src/ImageSharp/Color/Color.WebSafePalette.cs create mode 100644 src/ImageSharp/Color/Color.WernerPalette.cs create mode 100644 src/ImageSharp/Color/Color.cs create mode 100644 tests/ImageSharp.Tests/Color/ColorTests.CastFrom.cs create mode 100644 tests/ImageSharp.Tests/Color/ColorTests.CastTo.cs create mode 100644 tests/ImageSharp.Tests/Color/ColorTests.ConstructFrom.cs create mode 100644 tests/ImageSharp.Tests/Color/ColorTests.cs create mode 100644 tests/ImageSharp.Tests/Color/ReferencePalette.cs delete mode 100644 tests/ImageSharp.Tests/ColorTests.cs diff --git a/src/ImageSharp/Color.cs b/src/ImageSharp/Color.cs deleted file mode 100644 index 6dae76c34..000000000 --- a/src/ImageSharp/Color.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp -{ - public readonly partial struct Color - { - private readonly Rgba64 data; - - public Color(Rgba64 pixel) - { - this.data = pixel; - } - - public Color(Rgba32 pixel) - { - this.data = new Rgba64(pixel); - } - - public Color(Argb32 pixel) - { - this.data = new Rgba64(pixel); - } - - public Color(Bgra32 pixel) - { - this.data = new Rgba64(pixel); - } - - public Color(Rgb24 pixel) - { - this.data = new Rgba64(pixel); - } - - public Color(Bgr24 pixel) - { - this.data = new Rgba64(pixel); - } - - public Color(Vector4 vector) - { - this.data = new Rgba64(vector); - } - - public static implicit operator Color(Rgba64 source) => new Color(source); - - public static implicit operator Color(Rgba32 source) => new Color(source); - - public static implicit operator Color(Bgra32 source) => new Color(source); - - public static implicit operator Color(Argb32 source) => new Color(source); - - public static implicit operator Color(Rgb24 source) => new Color(source); - - public static implicit operator Color(Bgr24 source) => new Color(source); - - public static implicit operator Rgba64(Color color) => color.data; - - public static implicit operator Rgba32(Color color) => color.data.ToRgba32(); - - public static implicit operator Bgra32(Color color) => color.data.ToBgra32(); - - public static implicit operator Argb32(Color color) => color.data.ToArgb32(); - - public static implicit operator Rgb24(Color color) => color.data.ToRgb24(); - - public static implicit operator Bgr24(Color color) => color.data.ToBgr24(); - - public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(new Rgba32(r, g, b, a)); - - public TPixel ToPixel() - where TPixel : struct, IPixel - { - TPixel pixel = default; - pixel.FromRgba64(this.data); - return pixel; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Source/ImageSharp/Color.NamedColors.cs b/src/ImageSharp/Color/Color.NamedColors.cs similarity index 99% rename from src/ImageSharp/Source/ImageSharp/Color.NamedColors.cs rename to src/ImageSharp/Color/Color.NamedColors.cs index e00329d89..a712f85da 100644 --- a/src/ImageSharp/Source/ImageSharp/Color.NamedColors.cs +++ b/src/ImageSharp/Color/Color.NamedColors.cs @@ -1,5 +1,6 @@ // // Copyright (c) Six Labors and contributors. // // Licensed under the Apache License, Version 2.0. + namespace SixLabors.ImageSharp { public readonly partial struct Color diff --git a/src/ImageSharp/Color/Color.WebSafePalette.cs b/src/ImageSharp/Color/Color.WebSafePalette.cs new file mode 100644 index 000000000..13720ec49 --- /dev/null +++ b/src/ImageSharp/Color/Color.WebSafePalette.cs @@ -0,0 +1,163 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using System; + +namespace SixLabors.ImageSharp +{ + public partial struct Color + { + private static readonly Lazy WebSafePaletteLazy = new Lazy(CreateWebSafePalette, true); + + /// + /// Gets a collection of named, web safe, colors as defined in the CSS Color Module Level 4. + /// + public static ReadOnlySpan WebSafePalette => WebSafePaletteLazy.Value; + + private static Color[] CreateWebSafePalette() => new[] + { + AliceBlue, + AntiqueWhite, + Aqua, + Aquamarine, + Azure, + Beige, + Bisque, + Black, + BlanchedAlmond, + Blue, + BlueViolet, + Brown, + BurlyWood, + CadetBlue, + Chartreuse, + Chocolate, + Coral, + CornflowerBlue, + Cornsilk, + Crimson, + Cyan, + DarkBlue, + DarkCyan, + DarkGoldenrod, + DarkGray, + DarkGreen, + DarkKhaki, + DarkMagenta, + DarkOliveGreen, + DarkOrange, + DarkOrchid, + DarkRed, + DarkSalmon, + DarkSeaGreen, + DarkSlateBlue, + DarkSlateGray, + DarkTurquoise, + DarkViolet, + DeepPink, + DeepSkyBlue, + DimGray, + DodgerBlue, + Firebrick, + FloralWhite, + ForestGreen, + Fuchsia, + Gainsboro, + GhostWhite, + Gold, + Goldenrod, + Gray, + Green, + GreenYellow, + Honeydew, + HotPink, + IndianRed, + Indigo, + Ivory, + Khaki, + Lavender, + LavenderBlush, + LawnGreen, + LemonChiffon, + LightBlue, + LightCoral, + LightCyan, + LightGoldenrodYellow, + LightGray, + LightGreen, + LightPink, + LightSalmon, + LightSeaGreen, + LightSkyBlue, + LightSlateGray, + LightSteelBlue, + LightYellow, + Lime, + LimeGreen, + Linen, + Magenta, + Maroon, + MediumAquamarine, + MediumBlue, + MediumOrchid, + MediumPurple, + MediumSeaGreen, + MediumSlateBlue, + MediumSpringGreen, + MediumTurquoise, + MediumVioletRed, + MidnightBlue, + MintCream, + MistyRose, + Moccasin, + NavajoWhite, + Navy, + OldLace, + Olive, + OliveDrab, + Orange, + OrangeRed, + Orchid, + PaleGoldenrod, + PaleGreen, + PaleTurquoise, + PaleVioletRed, + PapayaWhip, + PeachPuff, + Peru, + Pink, + Plum, + PowderBlue, + Purple, + RebeccaPurple, + Red, + RosyBrown, + RoyalBlue, + SaddleBrown, + Salmon, + SandyBrown, + SeaGreen, + SeaShell, + Sienna, + Silver, + SkyBlue, + SlateBlue, + SlateGray, + Snow, + SpringGreen, + SteelBlue, + Tan, + Teal, + Thistle, + Tomato, + Transparent, + Turquoise, + Violet, + Wheat, + White, + WhiteSmoke, + Yellow, + YellowGreen + }; + } +} \ No newline at end of file diff --git a/src/ImageSharp/Color/Color.WernerPalette.cs b/src/ImageSharp/Color/Color.WernerPalette.cs new file mode 100644 index 000000000..45823479e --- /dev/null +++ b/src/ImageSharp/Color/Color.WernerPalette.cs @@ -0,0 +1,132 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using System; + +namespace SixLabors.ImageSharp +{ + public partial struct Color + { + private static readonly Lazy WernerPaletteLazy = new Lazy(CreateWernerPalette, true); + + /// + /// Gets a collection of colors as defined in the original second edition of Werner’s Nomenclature of Colours 1821. + /// The hex codes were collected and defined by Nicholas Rougeux . + /// + public static ReadOnlySpan WernerPalette => WernerPaletteLazy.Value; + + private static Color[] CreateWernerPalette() => new[] + { + FromHex("#f1e9cd"), + FromHex("#f2e7cf"), + FromHex("#ece6d0"), + FromHex("#f2eacc"), + FromHex("#f3e9ca"), + FromHex("#f2ebcd"), + FromHex("#e6e1c9"), + FromHex("#e2ddc6"), + FromHex("#cbc8b7"), + FromHex("#bfbbb0"), + FromHex("#bebeb3"), + FromHex("#b7b5ac"), + FromHex("#bab191"), + FromHex("#9c9d9a"), + FromHex("#8a8d84"), + FromHex("#5b5c61"), + FromHex("#555152"), + FromHex("#413f44"), + FromHex("#454445"), + FromHex("#423937"), + FromHex("#433635"), + FromHex("#252024"), + FromHex("#241f20"), + FromHex("#281f3f"), + FromHex("#1c1949"), + FromHex("#4f638d"), + FromHex("#383867"), + FromHex("#5c6b8f"), + FromHex("#657abb"), + FromHex("#6f88af"), + FromHex("#7994b5"), + FromHex("#6fb5a8"), + FromHex("#719ba2"), + FromHex("#8aa1a6"), + FromHex("#d0d5d3"), + FromHex("#8590ae"), + FromHex("#3a2f52"), + FromHex("#39334a"), + FromHex("#6c6d94"), + FromHex("#584c77"), + FromHex("#533552"), + FromHex("#463759"), + FromHex("#bfbac0"), + FromHex("#77747f"), + FromHex("#4a475c"), + FromHex("#b8bfaf"), + FromHex("#b2b599"), + FromHex("#979c84"), + FromHex("#5d6161"), + FromHex("#61ac86"), + FromHex("#a4b6a7"), + FromHex("#adba98"), + FromHex("#93b778"), + FromHex("#7d8c55"), + FromHex("#33431e"), + FromHex("#7c8635"), + FromHex("#8e9849"), + FromHex("#c2c190"), + FromHex("#67765b"), + FromHex("#ab924b"), + FromHex("#c8c76f"), + FromHex("#ccc050"), + FromHex("#ebdd99"), + FromHex("#ab9649"), + FromHex("#dbc364"), + FromHex("#e6d058"), + FromHex("#ead665"), + FromHex("#d09b2c"), + FromHex("#a36629"), + FromHex("#a77d35"), + FromHex("#f0d696"), + FromHex("#d7c485"), + FromHex("#f1d28c"), + FromHex("#efcc83"), + FromHex("#f3daa7"), + FromHex("#dfa837"), + FromHex("#ebbc71"), + FromHex("#d17c3f"), + FromHex("#92462f"), + FromHex("#be7249"), + FromHex("#bb603c"), + FromHex("#c76b4a"), + FromHex("#a75536"), + FromHex("#b63e36"), + FromHex("#b5493a"), + FromHex("#cd6d57"), + FromHex("#711518"), + FromHex("#e9c49d"), + FromHex("#eedac3"), + FromHex("#eecfbf"), + FromHex("#ce536b"), + FromHex("#b74a70"), + FromHex("#b7757c"), + FromHex("#612741"), + FromHex("#7a4848"), + FromHex("#3f3033"), + FromHex("#8d746f"), + FromHex("#4d3635"), + FromHex("#6e3b31"), + FromHex("#864735"), + FromHex("#553d3a"), + FromHex("#613936"), + FromHex("#7a4b3a"), + FromHex("#946943"), + FromHex("#c39e6d"), + FromHex("#513e32"), + FromHex("#8b7859"), + FromHex("#9b856b"), + FromHex("#766051"), + FromHex("#453b32") + }; + } +} \ No newline at end of file diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs new file mode 100644 index 000000000..3e20cafbd --- /dev/null +++ b/src/ImageSharp/Color/Color.cs @@ -0,0 +1,185 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers.Binary; +using System.Globalization; +using System.Numerics; + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + public readonly partial struct Color : IEquatable + { + private readonly Rgba64 data; + + public Color(Rgba64 pixel) + { + this.data = pixel; + } + + public Color(Rgba32 pixel) + { + this.data = new Rgba64(pixel); + } + + public Color(Argb32 pixel) + { + this.data = new Rgba64(pixel); + } + + public Color(Bgra32 pixel) + { + this.data = new Rgba64(pixel); + } + + public Color(Rgb24 pixel) + { + this.data = new Rgba64(pixel); + } + + public Color(Bgr24 pixel) + { + this.data = new Rgba64(pixel); + } + + public Color(Vector4 vector) + { + this.data = new Rgba64(vector); + } + + public static implicit operator Color(Rgba64 source) => new Color(source); + + public static implicit operator Color(Rgba32 source) => new Color(source); + + public static implicit operator Color(Bgra32 source) => new Color(source); + + public static implicit operator Color(Argb32 source) => new Color(source); + + public static implicit operator Color(Rgb24 source) => new Color(source); + + public static implicit operator Color(Bgr24 source) => new Color(source); + + public static implicit operator Rgba64(Color color) => color.data; + + public static implicit operator Rgba32(Color color) => color.data.ToRgba32(); + + public static implicit operator Bgra32(Color color) => color.data.ToBgra32(); + + public static implicit operator Argb32(Color color) => color.data.ToArgb32(); + + public static implicit operator Rgb24(Color color) => color.data.ToRgb24(); + + public static implicit operator Bgr24(Color color) => color.data.ToBgr24(); + + public static bool operator ==(Color left, Color right) + { + return left.Equals(right); + } + + public static bool operator !=(Color left, Color right) + { + return !left.Equals(right); + } + + public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(new Rgba32(r, g, b, a)); + + /// + /// Creates a new instance from the string representing a color in hexadecimal form. + /// + /// + /// The hexadecimal representation of the combined color components arranged + /// in rgb, rgba, rrggbb, or rrggbbaa format to match web syntax. + /// + /// Returns a that represents the color defined by the provided RGBA hex string. + public static Color FromHex(string hex) + { + Guard.NotNullOrWhiteSpace(hex, nameof(hex)); + + hex = ToRgbaHex(hex); + + if (hex is null || !uint.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint packedValue)) + { + throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex)); + } + + var rgba = new Rgba32(BinaryPrimitives.ReverseEndianness(packedValue)); + return new Color(rgba); + } + + /// + /// Gets the hexadecimal representation of the color instance in rrggbbaa form. + /// + /// A hexadecimal string representation of the value. + public string ToHex() => this.data.ToRgba32().ToHex(); + + /// + public override string ToString() => this.ToHex(); + + /// + /// Converts the specified hex value to an rrggbbaa hex value. + /// + /// The hex value to convert. + /// + /// A rrggbbaa hex value. + /// + private static string ToRgbaHex(string hex) + { + if (hex[0] == '#') + { + hex = hex.Substring(1); + } + + if (hex.Length == 8) + { + return hex; + } + + if (hex.Length == 6) + { + return hex + "FF"; + } + + if (hex.Length < 3 || hex.Length > 4) + { + return null; + } + + char r = hex[0]; + char g = hex[1]; + char b = hex[2]; + char a = hex.Length == 3 ? 'F' : hex[3]; + + return new string(new[] { r, r, g, g, b, b, a, a }); + } + + public TPixel ToPixel() + where TPixel : struct, IPixel + { + TPixel pixel = default; + pixel.FromRgba64(this.data); + return pixel; + } + + public bool Equals(Color other) + { + return this.data.PackedValue == other.data.PackedValue; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + return obj is Color other && this.Equals(other); + } + + /// + public override int GetHashCode() + { + return this.data.PackedValue.GetHashCode(); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/ImageSharp.csproj.DotSettings b/src/ImageSharp/ImageSharp.csproj.DotSettings index e446893e9..e43e92ddc 100644 --- a/src/ImageSharp/ImageSharp.csproj.DotSettings +++ b/src/ImageSharp/ImageSharp.csproj.DotSettings @@ -1,4 +1,5 @@  + True True True True diff --git a/tests/ImageSharp.Tests/Color/ColorTests.CastFrom.cs b/tests/ImageSharp.Tests/Color/ColorTests.CastFrom.cs new file mode 100644 index 000000000..22c6d55ad --- /dev/null +++ b/tests/ImageSharp.Tests/Color/ColorTests.CastFrom.cs @@ -0,0 +1,93 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ColorTests + { + public class CastFrom + { + [Fact] + public void Rgba64() + { + Rgba64 source = new Rgba64(100, 2222, 3333, 4444); + + // Act: + Color color = source; + + // Assert: + Rgba64 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Rgba32() + { + Rgba32 source = new Rgba32(1, 22, 33, 231); + + // Act: + Color color = source; + + // Assert: + Rgba32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Argb32() + { + Argb32 source = new Argb32(1, 22, 33, 231); + + // Act: + Color color = source; + + // Assert: + Argb32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Bgra32() + { + Bgra32 source = new Bgra32(1, 22, 33, 231); + + // Act: + Color color = source; + + // Assert: + Bgra32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Rgb24() + { + Rgb24 source = new Rgb24(1, 22, 231); + + // Act: + Color color = source; + + // Assert: + Rgb24 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Bgr24() + { + Bgr24 source = new Bgr24(1, 22, 231); + + // Act: + Color color = source; + + // Assert: + Bgr24 data = color.ToPixel(); + Assert.Equal(source, data); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Color/ColorTests.CastTo.cs b/tests/ImageSharp.Tests/Color/ColorTests.CastTo.cs new file mode 100644 index 000000000..d44472b28 --- /dev/null +++ b/tests/ImageSharp.Tests/Color/ColorTests.CastTo.cs @@ -0,0 +1,93 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ColorTests + { + public class CastTo + { + [Fact] + public void Rgba64() + { + Rgba64 source = new Rgba64(100, 2222, 3333, 4444); + + // Act: + Color color = new Color(source); + + // Assert: + Rgba64 data = color; + Assert.Equal(source, data); + } + + [Fact] + public void Rgba32() + { + Rgba32 source = new Rgba32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Rgba32 data = color; + Assert.Equal(source, data); + } + + [Fact] + public void Argb32() + { + Argb32 source = new Argb32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Argb32 data = color; + Assert.Equal(source, data); + } + + [Fact] + public void Bgra32() + { + Bgra32 source = new Bgra32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Bgra32 data = color; + Assert.Equal(source, data); + } + + [Fact] + public void Rgb24() + { + Rgb24 source = new Rgb24(1, 22, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Rgb24 data = color; + Assert.Equal(source, data); + } + + [Fact] + public void Bgr24() + { + Bgr24 source = new Bgr24(1, 22, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Bgr24 data = color; + Assert.Equal(source, data); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Color/ColorTests.ConstructFrom.cs b/tests/ImageSharp.Tests/Color/ColorTests.ConstructFrom.cs new file mode 100644 index 000000000..9d21cd80c --- /dev/null +++ b/tests/ImageSharp.Tests/Color/ColorTests.ConstructFrom.cs @@ -0,0 +1,93 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ColorTests + { + public class ConstructFrom + { + [Fact] + public void Rgba64() + { + Rgba64 source = new Rgba64(100, 2222, 3333, 4444); + + // Act: + Color color = new Color(source); + + // Assert: + Rgba64 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Rgba32() + { + Rgba32 source = new Rgba32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Rgba32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Argb32() + { + Argb32 source = new Argb32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Argb32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Bgra32() + { + Bgra32 source = new Bgra32(1, 22, 33, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Bgra32 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Rgb24() + { + Rgb24 source = new Rgb24(1, 22, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Rgb24 data = color.ToPixel(); + Assert.Equal(source, data); + } + + [Fact] + public void Bgr24() + { + Bgr24 source = new Bgr24(1, 22, 231); + + // Act: + Color color = new Color(source); + + // Assert: + Bgr24 data = color.ToPixel(); + Assert.Equal(source, data); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Color/ColorTests.cs b/tests/ImageSharp.Tests/Color/ColorTests.cs new file mode 100644 index 000000000..729ef94e3 --- /dev/null +++ b/tests/ImageSharp.Tests/Color/ColorTests.cs @@ -0,0 +1,97 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Linq; +using System.Reflection; + +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ColorTests + { + [Fact] + public void Equality_WhenTrue() + { + Color c1 = new Rgba64(100, 2000, 3000, 40000); + Color c2 = new Rgba64(100, 2000, 3000, 40000); + + Assert.True(c1.Equals(c2)); + Assert.True(c1 == c2); + Assert.False(c1 != c2); + Assert.True(c1.GetHashCode() == c2.GetHashCode()); + } + + [Fact] + public void Equality_WhenFalse() + { + Color c1 = new Rgba64(100, 2000, 3000, 40000); + Color c2 = new Rgba64(101, 2000, 3000, 40000); + Color c3 = new Rgba64(100, 2000, 3000, 40001); + + Assert.False(c1.Equals(c2)); + Assert.False(c2.Equals(c3)); + Assert.False(c3.Equals(c1)); + + Assert.False(c1 == c2); + Assert.True(c1 != c2); + } + + [Fact] + public void ToHex() + { + string expected = "ABCD1234"; + Color color = Color.FromHex(expected); + string actual = color.ToHex(); + + Assert.Equal(expected, actual); + } + + [Fact] + public void WebSafePalette_IsCorrect() + { + Rgba32[] actualPalette = Color.WebSafePalette.ToArray().Select(c => (Rgba32)c).ToArray(); + Assert.Equal(ReferencePalette.WebSafeColors, actualPalette); + } + + [Fact] + public void WernerPalette_IsCorrect() + { + Rgba32[] actualPalette = Color.WernerPalette.ToArray().Select(c => (Rgba32)c).ToArray(); + Assert.Equal(ReferencePalette.WernerColors, actualPalette); + } + + public class FromHex + { + [Fact] + public void ShortHex() + { + Assert.Equal(new Rgb24(255, 255, 255), (Rgb24) Color.FromHex("#fff")); + Assert.Equal(new Rgb24(255, 255, 255), (Rgb24) Color.FromHex("fff")); + Assert.Equal(new Rgba32(0, 0, 0, 255), (Rgba32) Color.FromHex("000f")); + } + + [Fact] + public void LeadingPoundIsOptional() + { + Assert.Equal(new Rgb24(0, 128, 128), (Rgb24) Color.FromHex("#008080")); + Assert.Equal(new Rgb24(0, 128, 128), (Rgb24) Color.FromHex("008080")); + } + + [Fact] + public void ThrowsOnEmpty() + { + Assert.Throws(() => Color.FromHex("")); + } + + [Fact] + public void ThrowsOnNull() + { + Assert.Throws(() => Color.FromHex(null)); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Color/ReferencePalette.cs b/tests/ImageSharp.Tests/Color/ReferencePalette.cs new file mode 100644 index 000000000..3c6e382c5 --- /dev/null +++ b/tests/ImageSharp.Tests/Color/ReferencePalette.cs @@ -0,0 +1,277 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Tests +{ + internal static class ReferencePalette + { + /// + /// Gets a collection of named, web safe, colors as defined in the CSS Color Module Level 4. + /// + public static readonly Rgba32[] WebSafeColors = + { + Rgba32.AliceBlue, + Rgba32.AntiqueWhite, + Rgba32.Aqua, + Rgba32.Aquamarine, + Rgba32.Azure, + Rgba32.Beige, + Rgba32.Bisque, + Rgba32.Black, + Rgba32.BlanchedAlmond, + Rgba32.Blue, + Rgba32.BlueViolet, + Rgba32.Brown, + Rgba32.BurlyWood, + Rgba32.CadetBlue, + Rgba32.Chartreuse, + Rgba32.Chocolate, + Rgba32.Coral, + Rgba32.CornflowerBlue, + Rgba32.Cornsilk, + Rgba32.Crimson, + Rgba32.Cyan, + Rgba32.DarkBlue, + Rgba32.DarkCyan, + Rgba32.DarkGoldenrod, + Rgba32.DarkGray, + Rgba32.DarkGreen, + Rgba32.DarkKhaki, + Rgba32.DarkMagenta, + Rgba32.DarkOliveGreen, + Rgba32.DarkOrange, + Rgba32.DarkOrchid, + Rgba32.DarkRed, + Rgba32.DarkSalmon, + Rgba32.DarkSeaGreen, + Rgba32.DarkSlateBlue, + Rgba32.DarkSlateGray, + Rgba32.DarkTurquoise, + Rgba32.DarkViolet, + Rgba32.DeepPink, + Rgba32.DeepSkyBlue, + Rgba32.DimGray, + Rgba32.DodgerBlue, + Rgba32.Firebrick, + Rgba32.FloralWhite, + Rgba32.ForestGreen, + Rgba32.Fuchsia, + Rgba32.Gainsboro, + Rgba32.GhostWhite, + Rgba32.Gold, + Rgba32.Goldenrod, + Rgba32.Gray, + Rgba32.Green, + Rgba32.GreenYellow, + Rgba32.Honeydew, + Rgba32.HotPink, + Rgba32.IndianRed, + Rgba32.Indigo, + Rgba32.Ivory, + Rgba32.Khaki, + Rgba32.Lavender, + Rgba32.LavenderBlush, + Rgba32.LawnGreen, + Rgba32.LemonChiffon, + Rgba32.LightBlue, + Rgba32.LightCoral, + Rgba32.LightCyan, + Rgba32.LightGoldenrodYellow, + Rgba32.LightGray, + Rgba32.LightGreen, + Rgba32.LightPink, + Rgba32.LightSalmon, + Rgba32.LightSeaGreen, + Rgba32.LightSkyBlue, + Rgba32.LightSlateGray, + Rgba32.LightSteelBlue, + Rgba32.LightYellow, + Rgba32.Lime, + Rgba32.LimeGreen, + Rgba32.Linen, + Rgba32.Magenta, + Rgba32.Maroon, + Rgba32.MediumAquamarine, + Rgba32.MediumBlue, + Rgba32.MediumOrchid, + Rgba32.MediumPurple, + Rgba32.MediumSeaGreen, + Rgba32.MediumSlateBlue, + Rgba32.MediumSpringGreen, + Rgba32.MediumTurquoise, + Rgba32.MediumVioletRed, + Rgba32.MidnightBlue, + Rgba32.MintCream, + Rgba32.MistyRose, + Rgba32.Moccasin, + Rgba32.NavajoWhite, + Rgba32.Navy, + Rgba32.OldLace, + Rgba32.Olive, + Rgba32.OliveDrab, + Rgba32.Orange, + Rgba32.OrangeRed, + Rgba32.Orchid, + Rgba32.PaleGoldenrod, + Rgba32.PaleGreen, + Rgba32.PaleTurquoise, + Rgba32.PaleVioletRed, + Rgba32.PapayaWhip, + Rgba32.PeachPuff, + Rgba32.Peru, + Rgba32.Pink, + Rgba32.Plum, + Rgba32.PowderBlue, + Rgba32.Purple, + Rgba32.RebeccaPurple, + Rgba32.Red, + Rgba32.RosyBrown, + Rgba32.RoyalBlue, + Rgba32.SaddleBrown, + Rgba32.Salmon, + Rgba32.SandyBrown, + Rgba32.SeaGreen, + Rgba32.SeaShell, + Rgba32.Sienna, + Rgba32.Silver, + Rgba32.SkyBlue, + Rgba32.SlateBlue, + Rgba32.SlateGray, + Rgba32.Snow, + Rgba32.SpringGreen, + Rgba32.SteelBlue, + Rgba32.Tan, + Rgba32.Teal, + Rgba32.Thistle, + Rgba32.Tomato, + Rgba32.Transparent, + Rgba32.Turquoise, + Rgba32.Violet, + Rgba32.Wheat, + Rgba32.White, + Rgba32.WhiteSmoke, + Rgba32.Yellow, + Rgba32.YellowGreen + }; + + /// + /// Gets a collection of colors as defined in the original second edition of Werner’s Nomenclature of Colours 1821. + /// The hex codes were collected and defined by Nicholas Rougeux + /// + public static readonly Rgba32[] WernerColors = + { + Rgba32.FromHex("#f1e9cd"), + Rgba32.FromHex("#f2e7cf"), + Rgba32.FromHex("#ece6d0"), + Rgba32.FromHex("#f2eacc"), + Rgba32.FromHex("#f3e9ca"), + Rgba32.FromHex("#f2ebcd"), + Rgba32.FromHex("#e6e1c9"), + Rgba32.FromHex("#e2ddc6"), + Rgba32.FromHex("#cbc8b7"), + Rgba32.FromHex("#bfbbb0"), + Rgba32.FromHex("#bebeb3"), + Rgba32.FromHex("#b7b5ac"), + Rgba32.FromHex("#bab191"), + Rgba32.FromHex("#9c9d9a"), + Rgba32.FromHex("#8a8d84"), + Rgba32.FromHex("#5b5c61"), + Rgba32.FromHex("#555152"), + Rgba32.FromHex("#413f44"), + Rgba32.FromHex("#454445"), + Rgba32.FromHex("#423937"), + Rgba32.FromHex("#433635"), + Rgba32.FromHex("#252024"), + Rgba32.FromHex("#241f20"), + Rgba32.FromHex("#281f3f"), + Rgba32.FromHex("#1c1949"), + Rgba32.FromHex("#4f638d"), + Rgba32.FromHex("#383867"), + Rgba32.FromHex("#5c6b8f"), + Rgba32.FromHex("#657abb"), + Rgba32.FromHex("#6f88af"), + Rgba32.FromHex("#7994b5"), + Rgba32.FromHex("#6fb5a8"), + Rgba32.FromHex("#719ba2"), + Rgba32.FromHex("#8aa1a6"), + Rgba32.FromHex("#d0d5d3"), + Rgba32.FromHex("#8590ae"), + Rgba32.FromHex("#3a2f52"), + Rgba32.FromHex("#39334a"), + Rgba32.FromHex("#6c6d94"), + Rgba32.FromHex("#584c77"), + Rgba32.FromHex("#533552"), + Rgba32.FromHex("#463759"), + Rgba32.FromHex("#bfbac0"), + Rgba32.FromHex("#77747f"), + Rgba32.FromHex("#4a475c"), + Rgba32.FromHex("#b8bfaf"), + Rgba32.FromHex("#b2b599"), + Rgba32.FromHex("#979c84"), + Rgba32.FromHex("#5d6161"), + Rgba32.FromHex("#61ac86"), + Rgba32.FromHex("#a4b6a7"), + Rgba32.FromHex("#adba98"), + Rgba32.FromHex("#93b778"), + Rgba32.FromHex("#7d8c55"), + Rgba32.FromHex("#33431e"), + Rgba32.FromHex("#7c8635"), + Rgba32.FromHex("#8e9849"), + Rgba32.FromHex("#c2c190"), + Rgba32.FromHex("#67765b"), + Rgba32.FromHex("#ab924b"), + Rgba32.FromHex("#c8c76f"), + Rgba32.FromHex("#ccc050"), + Rgba32.FromHex("#ebdd99"), + Rgba32.FromHex("#ab9649"), + Rgba32.FromHex("#dbc364"), + Rgba32.FromHex("#e6d058"), + Rgba32.FromHex("#ead665"), + Rgba32.FromHex("#d09b2c"), + Rgba32.FromHex("#a36629"), + Rgba32.FromHex("#a77d35"), + Rgba32.FromHex("#f0d696"), + Rgba32.FromHex("#d7c485"), + Rgba32.FromHex("#f1d28c"), + Rgba32.FromHex("#efcc83"), + Rgba32.FromHex("#f3daa7"), + Rgba32.FromHex("#dfa837"), + Rgba32.FromHex("#ebbc71"), + Rgba32.FromHex("#d17c3f"), + Rgba32.FromHex("#92462f"), + Rgba32.FromHex("#be7249"), + Rgba32.FromHex("#bb603c"), + Rgba32.FromHex("#c76b4a"), + Rgba32.FromHex("#a75536"), + Rgba32.FromHex("#b63e36"), + Rgba32.FromHex("#b5493a"), + Rgba32.FromHex("#cd6d57"), + Rgba32.FromHex("#711518"), + Rgba32.FromHex("#e9c49d"), + Rgba32.FromHex("#eedac3"), + Rgba32.FromHex("#eecfbf"), + Rgba32.FromHex("#ce536b"), + Rgba32.FromHex("#b74a70"), + Rgba32.FromHex("#b7757c"), + Rgba32.FromHex("#612741"), + Rgba32.FromHex("#7a4848"), + Rgba32.FromHex("#3f3033"), + Rgba32.FromHex("#8d746f"), + Rgba32.FromHex("#4d3635"), + Rgba32.FromHex("#6e3b31"), + Rgba32.FromHex("#864735"), + Rgba32.FromHex("#553d3a"), + Rgba32.FromHex("#613936"), + Rgba32.FromHex("#7a4b3a"), + Rgba32.FromHex("#946943"), + Rgba32.FromHex("#c39e6d"), + Rgba32.FromHex("#513e32"), + Rgba32.FromHex("#8b7859"), + Rgba32.FromHex("#9b856b"), + Rgba32.FromHex("#766051"), + Rgba32.FromHex("#453b32") + }; + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/ColorTests.cs b/tests/ImageSharp.Tests/ColorTests.cs deleted file mode 100644 index a1eaf9fae..000000000 --- a/tests/ImageSharp.Tests/ColorTests.cs +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests -{ - public class ColorTests - { - public class ConstructFrom - { - [Fact] - public void Rgba64() - { - Rgba64 source = new Rgba64(100, 2222, 3333, 4444); - - // Act: - Color color = new Color(source); - - // Assert: - Rgba64 data = color.ToPixel(); - Assert.Equal(source, data); - } - - [Fact] - public void Rgba32() - { - Rgba32 source = new Rgba32(1, 22, 33, 231); - - // Act: - Color color = new Color(source); - - // Assert: - Rgba32 data = color.ToPixel(); - Assert.Equal(source, data); - } - - [Fact] - public void Argb32() - { - Argb32 source = new Argb32(1, 22, 33, 231); - - // Act: - Color color = new Color(source); - - // Assert: - Argb32 data = color.ToPixel(); - Assert.Equal(source, data); - } - - [Fact] - public void Bgra32() - { - Bgra32 source = new Bgra32(1, 22, 33, 231); - - // Act: - Color color = new Color(source); - - // Assert: - Bgra32 data = color.ToPixel(); - Assert.Equal(source, data); - } - - [Fact] - public void Rgb24() - { - Rgb24 source = new Rgb24(1, 22, 231); - - // Act: - Color color = new Color(source); - - // Assert: - Rgb24 data = color.ToPixel(); - Assert.Equal(source, data); - } - - [Fact] - public void Bgr24() - { - Bgr24 source = new Bgr24(1, 22, 231); - - // Act: - Color color = new Color(source); - - // Assert: - Bgr24 data = color.ToPixel(); - Assert.Equal(source, data); - } - } - - public class Cast - { - [Fact] - public void Rgba64() - { - Rgba64 source = new Rgba64(100, 2222, 3333, 4444); - - // Act: - Color color = source; - - // Assert: - Rgba64 data = color.ToPixel(); - Assert.Equal(source, data); - } - - [Fact] - public void Rgba32() - { - Rgba32 source = new Rgba32(1, 22, 33, 231); - - // Act: - Color color = source; - - // Assert: - Rgba32 data = color.ToPixel(); - Assert.Equal(source, data); - } - - [Fact] - public void Argb32() - { - Argb32 source = new Argb32(1, 22, 33, 231); - - // Act: - Color color = source; - - // Assert: - Argb32 data = color.ToPixel(); - Assert.Equal(source, data); - } - - [Fact] - public void Bgra32() - { - Bgra32 source = new Bgra32(1, 22, 33, 231); - - // Act: - Color color = source; - - // Assert: - Bgra32 data = color.ToPixel(); - Assert.Equal(source, data); - } - - [Fact] - public void Rgb24() - { - Rgb24 source = new Rgb24(1, 22, 231); - - // Act: - Color color = source; - - // Assert: - Rgb24 data = color.ToPixel(); - Assert.Equal(source, data); - } - - [Fact] - public void Bgr24() - { - Bgr24 source = new Bgr24(1, 22, 231); - - // Act: - Color color = source; - - // Assert: - Bgr24 data = color.ToPixel(); - Assert.Equal(source, data); - } - } - - public class CastTo - { - [Fact] - public void Rgba64() - { - Rgba64 source = new Rgba64(100, 2222, 3333, 4444); - - // Act: - Color color = new Color(source); - - // Assert: - Rgba64 data = color; - Assert.Equal(source, data); - } - - [Fact] - public void Rgba32() - { - Rgba32 source = new Rgba32(1, 22, 33, 231); - - // Act: - Color color = new Color(source); - - // Assert: - Rgba32 data = color; - Assert.Equal(source, data); - } - - [Fact] - public void Argb32() - { - Argb32 source = new Argb32(1, 22, 33, 231); - - // Act: - Color color = new Color(source); - - // Assert: - Argb32 data = color; - Assert.Equal(source, data); - } - - [Fact] - public void Bgra32() - { - Bgra32 source = new Bgra32(1, 22, 33, 231); - - // Act: - Color color = new Color(source); - - // Assert: - Bgra32 data = color; - Assert.Equal(source, data); - } - - [Fact] - public void Rgb24() - { - Rgb24 source = new Rgb24(1, 22, 231); - - // Act: - Color color = new Color(source); - - // Assert: - Rgb24 data = color; - Assert.Equal(source, data); - } - - [Fact] - public void Bgr24() - { - Bgr24 source = new Bgr24(1, 22, 231); - - // Act: - Color color = new Color(source); - - // Assert: - Bgr24 data = color; - Assert.Equal(source, data); - } - } - } -} \ No newline at end of file From 16b24d4a08c736ea42b9e8b0b102e6cd41ba4eac Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 7 May 2019 00:02:54 +0200 Subject: [PATCH 145/223] refactor dithering and error diffusion to use Color --- src/ImageSharp/Color/Color.cs | 67 ++++++++------- .../Processing/DiffuseExtensions.cs | 69 ++++++++-------- src/ImageSharp/Processing/DitherExtensions.cs | 55 ++++++------- .../ErrorDiffusionPaletteProcessor.cs | 77 +++--------------- .../ErrorDiffusionPaletteProcessor{TPixel}.cs | 81 +++++++++++++++++++ .../OrderedDitherPaletteProcessor.cs | 70 +++------------- .../OrderedDitherPaletteProcessor{TPixel}.cs | 79 ++++++++++++++++++ .../Dithering/PaletteDitherProcessor.cs | 37 +++++++++ ...e.cs => PaletteDitherProcessor{TPixel}.cs} | 35 ++++---- .../Processing/Dithering/DitherTest.cs | 42 ++++++---- 10 files changed, 370 insertions(+), 242 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs rename src/ImageSharp/Processing/Processors/Dithering/{PaletteDitherProcessorBase.cs => PaletteDitherProcessor{TPixel}.cs} (77%) diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index 3e20cafbd..bc97393cc 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -5,6 +5,7 @@ using System; using System.Buffers.Binary; using System.Globalization; using System.Numerics; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.PixelFormats; @@ -117,6 +118,44 @@ namespace SixLabors.ImageSharp /// public override string ToString() => this.ToHex(); + public TPixel ToPixel() + where TPixel : struct, IPixel + { + TPixel pixel = default; + pixel.FromRgba64(this.data); + return pixel; + } + + public bool Equals(Color other) + { + return this.data.PackedValue == other.data.PackedValue; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + return obj is Color other && this.Equals(other); + } + + /// + public override int GetHashCode() + { + return this.data.PackedValue.GetHashCode(); + } + + internal static void ToPixel( + Configuration configuration, + ReadOnlySpan source, + Span destination) + where TPixel : struct, IPixel + { + ReadOnlySpan rgba64Span = MemoryMarshal.Cast(source); + PixelOperations.Instance.FromRgba64(Configuration.Default, rgba64Span, destination); + } + /// /// Converts the specified hex value to an rrggbbaa hex value. /// @@ -153,33 +192,5 @@ namespace SixLabors.ImageSharp return new string(new[] { r, r, g, g, b, b, a, a }); } - - public TPixel ToPixel() - where TPixel : struct, IPixel - { - TPixel pixel = default; - pixel.FromRgba64(this.data); - return pixel; - } - - public bool Equals(Color other) - { - return this.data.PackedValue == other.data.PackedValue; - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - return obj is Color other && this.Equals(other); - } - - /// - public override int GetHashCode() - { - return this.data.PackedValue.GetHashCode(); - } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/DiffuseExtensions.cs b/src/ImageSharp/Processing/DiffuseExtensions.cs index 4668363e9..cd714c3da 100644 --- a/src/ImageSharp/Processing/DiffuseExtensions.cs +++ b/src/ImageSharp/Processing/DiffuseExtensions.cs @@ -1,14 +1,15 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; +using System; + using SixLabors.ImageSharp.Processing.Processors.Dithering; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Dithering { /// - /// Defines extension methods to apply diffusion to an + /// Defines extension methods to apply diffusion to an /// using Mutate/Clone. /// public static class DiffuseExtensions @@ -16,68 +17,68 @@ namespace SixLabors.ImageSharp.Processing.Dithering /// /// Dithers the image reducing it to a web-safe palette using error diffusion. /// - /// The pixel format. /// The image this method extends. - /// The to allow chaining of operations. - public static IImageProcessingContext Diffuse(this IImageProcessingContext source) - where TPixel : struct, IPixel - => Diffuse(source, KnownDiffusers.FloydSteinberg, .5F); + /// The to allow chaining of operations. + public static IImageProcessingContext Diffuse(this IImageProcessingContext source) => + Diffuse(source, KnownDiffusers.FloydSteinberg, .5F); /// /// Dithers the image reducing it to a web-safe palette using error diffusion. /// - /// The pixel format. /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The to allow chaining of operations. - public static IImageProcessingContext Diffuse(this IImageProcessingContext source, float threshold) - where TPixel : struct, IPixel - => Diffuse(source, KnownDiffusers.FloydSteinberg, threshold); + /// The to allow chaining of operations. + public static IImageProcessingContext Diffuse(this IImageProcessingContext source, float threshold) => + Diffuse(source, KnownDiffusers.FloydSteinberg, threshold); /// /// Dithers the image reducing it to a web-safe palette using error diffusion. /// - /// The pixel format. /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The to allow chaining of operations. - public static IImageProcessingContext Diffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold) - where TPixel : struct, IPixel - => source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold)); + /// The to allow chaining of operations. + public static IImageProcessingContext Diffuse( + this IImageProcessingContext source, + IErrorDiffuser diffuser, + float threshold) => + source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold)); /// /// Dithers the image reducing it to a web-safe palette using error diffusion. /// - /// The pixel format. /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. - public static IImageProcessingContext Diffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold), rectangle); + /// The to allow chaining of operations. + public static IImageProcessingContext Diffuse( + this IImageProcessingContext source, + IErrorDiffuser diffuser, + float threshold, + Rectangle rectangle) => + source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold), rectangle); /// /// Dithers the image reducing it to the given palette using error diffusion. /// - /// The pixel format. /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The palette to select substitute colors from. - /// The to allow chaining of operations. - public static IImageProcessingContext Diffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, TPixel[] palette) - where TPixel : struct, IPixel - => source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold, palette)); + /// The to allow chaining of operations. + public static IImageProcessingContext Diffuse( + this IImageProcessingContext source, + IErrorDiffuser diffuser, + float threshold, + ReadOnlySpan palette) => + source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold, palette)); /// /// Dithers the image reducing it to the given palette using error diffusion. /// - /// The pixel format. /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. @@ -85,9 +86,13 @@ namespace SixLabors.ImageSharp.Processing.Dithering /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. - public static IImageProcessingContext Diffuse(this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, TPixel[] palette, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold, palette), rectangle); + /// The to allow chaining of operations. + public static IImageProcessingContext Diffuse( + this IImageProcessingContext source, + IErrorDiffuser diffuser, + float threshold, + ReadOnlySpan palette, + Rectangle rectangle) => + source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold, palette), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/DitherExtensions.cs b/src/ImageSharp/Processing/DitherExtensions.cs index aeb975d1c..55794aec2 100644 --- a/src/ImageSharp/Processing/DitherExtensions.cs +++ b/src/ImageSharp/Processing/DitherExtensions.cs @@ -1,14 +1,15 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; +using System; + using SixLabors.ImageSharp.Processing.Processors.Dithering; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Defines dithering extensions to apply on an + /// Defines dithering extensions to apply on an /// using Mutate/Clone. /// public static class DitherExtensions @@ -16,63 +17,63 @@ namespace SixLabors.ImageSharp.Processing /// /// Dithers the image reducing it to a web-safe palette using Bayer4x4 ordered dithering. /// - /// The pixel format. /// The image this method extends. - /// The to allow chaining of operations. - public static IImageProcessingContext Dither(this IImageProcessingContext source) - where TPixel : struct, IPixel - => Dither(source, KnownDitherers.BayerDither4x4); + /// The to allow chaining of operations. + public static IImageProcessingContext Dither(this IImageProcessingContext source) => + Dither(source, KnownDitherers.BayerDither4x4); /// /// Dithers the image reducing it to a web-safe palette using ordered dithering. /// - /// The pixel format. /// The image this method extends. /// The ordered ditherer. - /// The to allow chaining of operations. - public static IImageProcessingContext Dither(this IImageProcessingContext source, IOrderedDither dither) - where TPixel : struct, IPixel - => source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither)); + /// The to allow chaining of operations. + public static IImageProcessingContext Dither(this IImageProcessingContext source, IOrderedDither dither) => + source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither)); /// /// Dithers the image reducing it to the given palette using ordered dithering. /// - /// The pixel format. /// The image this method extends. /// The ordered ditherer. /// The palette to select substitute colors from. - /// The to allow chaining of operations. - public static IImageProcessingContext Dither(this IImageProcessingContext source, IOrderedDither dither, TPixel[] palette) - where TPixel : struct, IPixel - => source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither, palette)); + /// The to allow chaining of operations. + public static IImageProcessingContext Dither( + this IImageProcessingContext source, + IOrderedDither dither, + ReadOnlySpan palette) => + source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither, palette)); /// /// Dithers the image reducing it to a web-safe palette using ordered dithering. /// - /// The pixel format. /// The image this method extends. /// The ordered ditherer. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. - public static IImageProcessingContext Dither(this IImageProcessingContext source, IOrderedDither dither, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither), rectangle); + /// The to allow chaining of operations. + public static IImageProcessingContext Dither( + this IImageProcessingContext source, + IOrderedDither dither, + Rectangle rectangle) => + source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither), rectangle); /// /// Dithers the image reducing it to the given palette using ordered dithering. /// - /// The pixel format. /// The image this method extends. /// The ordered ditherer. /// The palette to select substitute colors from. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. - public static IImageProcessingContext Dither(this IImageProcessingContext source, IOrderedDither dither, TPixel[] palette, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither, palette), rectangle); + /// The to allow chaining of operations. + public static IImageProcessingContext Dither( + this IImageProcessingContext source, + IOrderedDither dither, + ReadOnlySpan palette, + Rectangle rectangle) => + source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither, palette), rectangle); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs index 911d3e8fd..5436a7733 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs @@ -2,21 +2,19 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; + +using SixLabors.ImageSharp.Processing.Processors.Binarization; namespace SixLabors.ImageSharp.Processing.Processors.Dithering { /// - /// An that dithers an image using error diffusion. + /// Defines a dither operation using error diffusion. + /// If no palette is given this will default to the web safe colors defined in the CSS Color Module Level 4. /// - /// The pixel format. - internal class ErrorDiffusionPaletteProcessor : PaletteDitherProcessorBase - where TPixel : struct, IPixel + public sealed class ErrorDiffusionPaletteProcessor : PaletteDitherProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The error diffuser public ErrorDiffusionPaletteProcessor(IErrorDiffuser diffuser) @@ -25,22 +23,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The error diffuser /// The threshold to split the image. Must be between 0 and 1. public ErrorDiffusionPaletteProcessor(IErrorDiffuser diffuser, float threshold) - : this(diffuser, threshold, NamedColors.WebSafePalette) + : this(diffuser, threshold, Color.WebSafePalette) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The error diffuser /// The threshold to split the image. Must be between 0 and 1. /// The palette to select substitute colors from. - public ErrorDiffusionPaletteProcessor(IErrorDiffuser diffuser, float threshold, TPixel[] palette) + public ErrorDiffusionPaletteProcessor(IErrorDiffuser diffuser, float threshold, ReadOnlySpan palette) : base(palette) { Guard.NotNull(diffuser, nameof(diffuser)); @@ -60,59 +58,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// public float Threshold { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + public override IImageProcessor CreatePixelSpecificProcessor() { - byte threshold = (byte)MathF.Round(this.Threshold * 255F); - bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); - - var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); - int startY = interest.Y; - int endY = interest.Bottom; - int startX = interest.X; - int endX = interest.Right; - - // Collect the values before looping so we can reduce our calculation count for identical sibling pixels - TPixel sourcePixel = source[startX, startY]; - TPixel previousPixel = sourcePixel; - PixelPair pair = this.GetClosestPixelPair(ref sourcePixel); - Rgba32 rgba = default; - sourcePixel.ToRgba32(ref rgba); - - // Convert to grayscale using ITU-R Recommendation BT.709 if required - byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); - - for (int y = startY; y < endY; y++) - { - Span row = source.GetPixelRowSpan(y); - - for (int x = startX; x < endX; x++) - { - sourcePixel = row[x]; - - // Check if this is the same as the last pixel. If so use that value - // rather than calculating it again. This is an inexpensive optimization. - if (!previousPixel.Equals(sourcePixel)) - { - pair = this.GetClosestPixelPair(ref sourcePixel); - - // No error to spread, exact match. - if (sourcePixel.Equals(pair.First)) - { - continue; - } - - sourcePixel.ToRgba32(ref rgba); - luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); - - // Setup the previous pointer - previousPixel = sourcePixel; - } - - TPixel transformedPixel = luminance >= threshold ? pair.Second : pair.First; - this.Diffuser.Dither(source, sourcePixel, transformedPixel, x, y, startX, startY, endX, endY); - } - } + return new ErrorDiffusionPaletteProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor{TPixel}.cs new file mode 100644 index 000000000..7edf287e8 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor{TPixel}.cs @@ -0,0 +1,81 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Dithering +{ + /// + /// An that dithers an image using error diffusion. + /// + /// The pixel format. + internal class ErrorDiffusionPaletteProcessor : PaletteDitherProcessor + where TPixel : struct, IPixel + { + public ErrorDiffusionPaletteProcessor(ErrorDiffusionPaletteProcessor definition) + : base(definition) + { + } + + private new ErrorDiffusionPaletteProcessor Definition => (ErrorDiffusionPaletteProcessor)base.Definition; + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + byte threshold = (byte)MathF.Round(this.Definition.Threshold * 255F); + bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); + + var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); + int startY = interest.Y; + int endY = interest.Bottom; + int startX = interest.X; + int endX = interest.Right; + + // Collect the values before looping so we can reduce our calculation count for identical sibling pixels + TPixel sourcePixel = source[startX, startY]; + TPixel previousPixel = sourcePixel; + PixelPair pair = this.GetClosestPixelPair(ref sourcePixel); + Rgba32 rgba = default; + sourcePixel.ToRgba32(ref rgba); + + // Convert to grayscale using ITU-R Recommendation BT.709 if required + byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + + for (int y = startY; y < endY; y++) + { + Span row = source.GetPixelRowSpan(y); + + for (int x = startX; x < endX; x++) + { + sourcePixel = row[x]; + + // Check if this is the same as the last pixel. If so use that value + // rather than calculating it again. This is an inexpensive optimization. + if (!previousPixel.Equals(sourcePixel)) + { + pair = this.GetClosestPixelPair(ref sourcePixel); + + // No error to spread, exact match. + if (sourcePixel.Equals(pair.First)) + { + continue; + } + + sourcePixel.ToRgba32(ref rgba); + luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + + // Setup the previous pointer + previousPixel = sourcePixel; + } + + TPixel transformedPixel = luminance >= threshold ? pair.Second : pair.First; + this.Definition.Diffuser.Dither(source, sourcePixel, transformedPixel, x, y, startX, startY, endX, endY); + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs index 1b4910a14..ba7c1e998 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs @@ -2,35 +2,30 @@ // Licensed under the Apache License, Version 2.0. using System; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Dithering { /// - /// An that dithers an image using error diffusion. + /// Defines a dithering operation that dithers an image using error diffusion. /// If no palette is given this will default to the web safe colors defined in the CSS Color Module Level 4. /// - /// The pixel format. - internal class OrderedDitherPaletteProcessor : PaletteDitherProcessorBase - where TPixel : struct, IPixel + public sealed class OrderedDitherPaletteProcessor : PaletteDitherProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The ordered ditherer. public OrderedDitherPaletteProcessor(IOrderedDither dither) - : this(dither, NamedColors.WebSafePalette) + : this(dither, Color.WebSafePalette) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The ordered ditherer. /// The palette to select substitute colors from. - public OrderedDitherPaletteProcessor(IOrderedDither dither, TPixel[] palette) + public OrderedDitherPaletteProcessor(IOrderedDither dither, ReadOnlySpan palette) : base(palette) => this.Dither = dither ?? throw new ArgumentNullException(nameof(dither)); /// @@ -38,57 +33,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// public IOrderedDither Dither { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + public override IImageProcessor CreatePixelSpecificProcessor() { - bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); - - var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); - int startY = interest.Y; - int endY = interest.Bottom; - int startX = interest.X; - int endX = interest.Right; - - // Collect the values before looping so we can reduce our calculation count for identical sibling pixels - TPixel sourcePixel = source[startX, startY]; - TPixel previousPixel = sourcePixel; - PixelPair pair = this.GetClosestPixelPair(ref sourcePixel); - Rgba32 rgba = default; - sourcePixel.ToRgba32(ref rgba); - - // Convert to grayscale using ITU-R Recommendation BT.709 if required - byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); - - for (int y = startY; y < endY; y++) - { - Span row = source.GetPixelRowSpan(y); - - for (int x = startX; x < endX; x++) - { - sourcePixel = row[x]; - - // Check if this is the same as the last pixel. If so use that value - // rather than calculating it again. This is an inexpensive optimization. - if (!previousPixel.Equals(sourcePixel)) - { - pair = this.GetClosestPixelPair(ref sourcePixel); - - // No error to spread, exact match. - if (sourcePixel.Equals(pair.First)) - { - continue; - } - - sourcePixel.ToRgba32(ref rgba); - luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); - - // Setup the previous pointer - previousPixel = sourcePixel; - } - - this.Dither.Dither(source, sourcePixel, pair.Second, pair.First, luminance, x, y); - } - } + return new OrderedDitherPaletteProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor{TPixel}.cs new file mode 100644 index 000000000..eefa6e522 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor{TPixel}.cs @@ -0,0 +1,79 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Dithering +{ + /// + /// An that dithers an image using error diffusion. + /// + /// The pixel format. + internal class OrderedDitherPaletteProcessor : PaletteDitherProcessor + where TPixel : struct, IPixel + { + public OrderedDitherPaletteProcessor(OrderedDitherPaletteProcessor definition) + : base(definition) + { + } + + private new OrderedDitherPaletteProcessor Definition => (OrderedDitherPaletteProcessor)base.Definition; + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8); + + var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); + int startY = interest.Y; + int endY = interest.Bottom; + int startX = interest.X; + int endX = interest.Right; + + // Collect the values before looping so we can reduce our calculation count for identical sibling pixels + TPixel sourcePixel = source[startX, startY]; + TPixel previousPixel = sourcePixel; + PixelPair pair = this.GetClosestPixelPair(ref sourcePixel); + Rgba32 rgba = default; + sourcePixel.ToRgba32(ref rgba); + + // Convert to grayscale using ITU-R Recommendation BT.709 if required + byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + + for (int y = startY; y < endY; y++) + { + Span row = source.GetPixelRowSpan(y); + + for (int x = startX; x < endX; x++) + { + sourcePixel = row[x]; + + // Check if this is the same as the last pixel. If so use that value + // rather than calculating it again. This is an inexpensive optimization. + if (!previousPixel.Equals(sourcePixel)) + { + pair = this.GetClosestPixelPair(ref sourcePixel); + + // No error to spread, exact match. + if (sourcePixel.Equals(pair.First)) + { + continue; + } + + sourcePixel.ToRgba32(ref rgba); + luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + + // Setup the previous pointer + previousPixel = sourcePixel; + } + + this.Definition.Dither.Dither(source, sourcePixel, pair.Second, pair.First, luminance, x, y); + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs new file mode 100644 index 000000000..904d02634 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs @@ -0,0 +1,37 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing.Processors.Dithering +{ + /// + /// The base class for dither and diffusion processors that consume a palette. + /// + public abstract class PaletteDitherProcessor : IImageProcessor + { + private readonly Color[] palette; + + /// + /// Initializes a new instance of the class. + /// + /// The palette to select substitute colors from. + protected PaletteDitherProcessor(ReadOnlySpan palette) + { + // This shouldn't be a perf issue: + // these arrays are small, and created with low frequency. + this.palette = palette.ToArray(); + } + + /// + /// Gets the palette to select substitute colors from. + /// + public ReadOnlySpan Palette => this.palette; + + /// + public abstract IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel; + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs similarity index 77% rename from src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs rename to src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs index 6313b74c9..334eab833 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs @@ -1,10 +1,11 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using System.Collections.Generic; using System.Numerics; using System.Runtime.CompilerServices; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; @@ -14,7 +15,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// The base class for dither and diffusion processors that consume a palette. /// /// The pixel format. - internal abstract class PaletteDitherProcessorBase : ImageProcessor + internal abstract class PaletteDitherProcessor : ImageProcessor where TPixel : struct, IPixel { private readonly Dictionary> cache = new Dictionary>(); @@ -24,19 +25,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// private Vector4[] paletteVector; + private TPixel[] palette; + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The palette to select substitute colors from. - protected PaletteDitherProcessorBase(TPixel[] palette) + protected PaletteDitherProcessor(PaletteDitherProcessor definition) { - this.Palette = palette ?? throw new ArgumentNullException(nameof(palette)); + this.Definition = definition; } - /// - /// Gets the palette to select substitute colors from. - /// - public TPixel[] Palette { get; } + protected PaletteDitherProcessor Definition { get; } /// /// Returns the two closest colors from the palette calculated via Euclidean distance in the Rgba space. @@ -74,12 +73,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering { leastDistance = distance; secondClosest = closest; - closest = this.Palette[index]; + closest = this.palette[index]; } else if (distance < secondLeastDistance) { secondLeastDistance = distance; - secondClosest = this.Palette[index]; + secondClosest = this.palette[index]; } } @@ -94,11 +93,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering { base.BeforeFrameApply(source, sourceRectangle, configuration); + // Lazy init palette: + if (this.palette is null) + { + ReadOnlySpan sourcePalette = this.Definition.Palette; + this.palette = new TPixel[sourcePalette.Length]; + Color.ToPixel(configuration, sourcePalette, this.palette); + } + // Lazy init paletteVector: if (this.paletteVector is null) { - this.paletteVector = new Vector4[this.Palette.Length]; - PixelOperations.Instance.ToVector4(configuration, (ReadOnlySpan)this.Palette, (Span)this.paletteVector, PixelConversionModifiers.Scale); + this.paletteVector = new Vector4[this.palette.Length]; + PixelOperations.Instance.ToVector4(configuration, (ReadOnlySpan)this.palette, (Span)this.paletteVector, PixelConversionModifiers.Scale); } } } diff --git a/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs b/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs index f393d5923..59dcde2a6 100644 --- a/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs +++ b/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Dithering; @@ -12,13 +14,21 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization { public class DitherTest : BaseImageOperationsExtensionTest { + private class Assert : Xunit.Assert + { + public static void Equal(ReadOnlySpan a, ReadOnlySpan b) + { + Xunit.Assert.True(a.SequenceEqual(b)); + } + } + private readonly IOrderedDither orderedDither; private readonly IErrorDiffuser errorDiffuser; - private readonly Rgba32[] TestPalette = + private readonly Color[] TestPalette = { - Rgba32.Red, - Rgba32.Green, - Rgba32.Blue + Color.Red, + Color.Green, + Color.Blue }; public DitherTest() @@ -31,24 +41,24 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization public void Dither_CorrectProcessor() { this.operations.Dither(this.orderedDither); - OrderedDitherPaletteProcessor p = this.Verify>(); + OrderedDitherPaletteProcessor p = this.Verify(); Assert.Equal(this.orderedDither, p.Dither); - Assert.Equal(NamedColors.WebSafePalette, p.Palette); + Assert.Equal(Color.WebSafePalette.ToArray(), p.Palette); } [Fact] public void Dither_rect_CorrectProcessor() { this.operations.Dither(this.orderedDither, this.rect); - OrderedDitherPaletteProcessor p = this.Verify>(this.rect); + OrderedDitherPaletteProcessor p = this.Verify(this.rect); Assert.Equal(this.orderedDither, p.Dither); - Assert.Equal(NamedColors.WebSafePalette, p.Palette); + Assert.Equal(Color.WebSafePalette, p.Palette); } [Fact] public void Dither_index_CorrectProcessor() { this.operations.Dither(this.orderedDither, this.TestPalette); - OrderedDitherPaletteProcessor p = this.Verify>(); + OrderedDitherPaletteProcessor p = this.Verify(); Assert.Equal(this.orderedDither, p.Dither); Assert.Equal(this.TestPalette, p.Palette); } @@ -57,7 +67,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization public void Dither_index_rect_CorrectProcessor() { this.operations.Dither(this.orderedDither, this.TestPalette, this.rect); - OrderedDitherPaletteProcessor p = this.Verify>(this.rect); + OrderedDitherPaletteProcessor p = this.Verify(this.rect); Assert.Equal(this.orderedDither, p.Dither); Assert.Equal(this.TestPalette, p.Palette); } @@ -67,27 +77,27 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization public void Dither_ErrorDiffuser_CorrectProcessor() { this.operations.Diffuse(this.errorDiffuser, .4F); - ErrorDiffusionPaletteProcessor p = this.Verify>(); + ErrorDiffusionPaletteProcessor p = this.Verify(); Assert.Equal(this.errorDiffuser, p.Diffuser); Assert.Equal(.4F, p.Threshold); - Assert.Equal(NamedColors.WebSafePalette, p.Palette); + Assert.Equal(Color.WebSafePalette, p.Palette); } [Fact] public void Dither_ErrorDiffuser_rect_CorrectProcessor() { this.operations.Diffuse(this.errorDiffuser, .3F, this.rect); - ErrorDiffusionPaletteProcessor p = this.Verify>(this.rect); + ErrorDiffusionPaletteProcessor p = this.Verify(this.rect); Assert.Equal(this.errorDiffuser, p.Diffuser); Assert.Equal(.3F, p.Threshold); - Assert.Equal(NamedColors.WebSafePalette, p.Palette); + Assert.Equal(Color.WebSafePalette, p.Palette); } [Fact] public void Dither_ErrorDiffuser_CorrectProcessorWithColors() { this.operations.Diffuse(this.errorDiffuser, .5F, this.TestPalette); - ErrorDiffusionPaletteProcessor p = this.Verify>(); + ErrorDiffusionPaletteProcessor p = this.Verify(); Assert.Equal(this.errorDiffuser, p.Diffuser); Assert.Equal(.5F, p.Threshold); Assert.Equal(this.TestPalette, p.Palette); @@ -97,7 +107,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization public void Dither_ErrorDiffuser_rect_CorrectProcessorWithColors() { this.operations.Diffuse(this.errorDiffuser, .5F, this.TestPalette, this.rect); - ErrorDiffusionPaletteProcessor p = this.Verify>(this.rect); + ErrorDiffusionPaletteProcessor p = this.Verify(this.rect); Assert.Equal(this.errorDiffuser, p.Diffuser); Assert.Equal(.5F, p.Threshold); Assert.Equal(this.TestPalette, p.Palette); From 3431ad321ed48e440712b60fe1ca227708e3ee58 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Tue, 7 May 2019 19:58:14 +0200 Subject: [PATCH 146/223] Add support for encoding 8-bit bitmaps --- src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs | 7 +- src/ImageSharp/Formats/Bmp/BmpEncoder.cs | 1 - src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 60 +++++++++++++++++- .../Formats/Bmp/IBmpEncoderOptions.cs | 1 - .../Quantization/QuantizedFrame{TPixel}.cs | 2 +- .../Formats/Bmp/BmpEncoderTests.cs | 9 ++- tests/ImageSharp.Tests/TestImages.cs | 1 + .../TestUtilities/PixelTypes.cs | 2 + tests/Images/Input/Bmp/pal8gs.bmp | Bin 0 -> 9254 bytes 9 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 tests/Images/Input/Bmp/pal8gs.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs b/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs index 38f5c1d66..6e1145beb 100644 --- a/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs +++ b/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs @@ -4,10 +4,15 @@ namespace SixLabors.ImageSharp.Formats.Bmp { /// - /// Enumerates the available bits per pixel for bitmap. + /// Enumerates the available bits per pixel the bitmap encoder supports. /// public enum BmpBitsPerPixel : short { + /// + /// 8 bits per pixel. Each pixel consists of 1 byte. + /// + Pixel8 = 8, + /// /// 16 bits per pixel. Each pixel consists of 2 bytes. /// diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs index 4efdedb34..f3eb9282c 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs @@ -10,7 +10,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Image encoder for writing an image to a stream as a Windows bitmap. /// - /// The encoder can currently only write 24-bit rgb images to streams. public sealed class BmpEncoder : IImageEncoder, IBmpEncoderOptions { /// diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 82483e390..530bcf8cd 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -9,6 +9,7 @@ using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.Memory; namespace SixLabors.ImageSharp.Formats.Bmp @@ -43,6 +44,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// private const int Rgba32BlueMask = 0xFF; + /// + /// The color palette for an 8 bit image will have 256 entry's with 4 bytes for each entry. + /// + private const int ColorPaletteSize8Bit = 1024; + private readonly MemoryAllocator memoryAllocator; private Configuration configuration; @@ -142,11 +148,13 @@ namespace SixLabors.ImageSharp.Formats.Bmp infoHeader.Compression = BmpCompression.BitFields; } + int colorPaletteSize = this.bitsPerPixel == BmpBitsPerPixel.Pixel8 ? ColorPaletteSize8Bit : 0; + var fileHeader = new BmpFileHeader( type: BmpConstants.TypeMarkers.Bitmap, fileSize: BmpFileHeader.Size + infoHeaderSize + infoHeader.ImageSize, reserved: 0, - offset: BmpFileHeader.Size + infoHeaderSize); + offset: BmpFileHeader.Size + infoHeaderSize + colorPaletteSize); #if NETCOREAPP2_1 Span buffer = stackalloc byte[infoHeaderSize]; @@ -198,6 +206,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp case BmpBitsPerPixel.Pixel16: this.Write16Bit(stream, pixels); break; + + case BmpBitsPerPixel.Pixel8: + this.Write8Bit(stream, image); + break; } } @@ -276,5 +288,51 @@ namespace SixLabors.ImageSharp.Formats.Bmp } } } + + /// + /// Writes an 8 Bit image with a color palette. The color palette has 256 entry's with 4 bytes for each entry. + /// + /// The type of the pixel. + /// The to write to. + /// The containing pixel data. + private void Write8Bit(Stream stream, ImageFrame image) + where TPixel : struct, IPixel + { +#if NETCOREAPP2_1 + Span colorPalette = stackalloc byte[ColorPaletteSize8Bit]; +#else + byte[] colorPalette = new byte[ColorPaletteSize8Bit]; +#endif + + var quantizer = new WuQuantizer(256); + QuantizedFrame quantized = quantizer.CreateFrameQuantizer(this.configuration).QuantizeFrame(image); + + int idx = 0; + var color = default(Rgba32); + foreach (TPixel quantizedColor in quantized.Palette) + { + quantizedColor.ToRgba32(ref color); + colorPalette[idx] = color.B; + colorPalette[idx + 1] = color.G; + colorPalette[idx + 2] = color.R; + + // Padding byte, always 0 + colorPalette[idx + 3] = 0; + idx += 4; + } + + stream.Write(colorPalette, 0, ColorPaletteSize8Bit); + + for (int y = image.Height - 1; y >= 0; y--) + { + Span pixelSpan = quantized.GetRowSpan(y); + stream.Write(pixelSpan); + + for (int i = 0; i < this.padding; i++) + { + stream.WriteByte(0); + } + } + } } } diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs index 96ec423e7..92ff09270 100644 --- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs +++ b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs @@ -6,7 +6,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Configuration options for use during bmp encoding /// - /// The encoder can currently only write 16-bit, 24-bit and 32-bit rgb images to streams. internal interface IBmpEncoderOptions { /// diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs index 38862ef44..30b8bc846 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Gets the representation of the pixels as a of contiguous memory - /// at row beginning from the the first pixel on that row. + /// at row beginning from the first pixel on that row. /// /// The row. /// The diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index 7e054734e..42ec3088d 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -114,6 +114,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] [WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] [WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] + [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] + [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] public void Encode_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) // if supportTransparency is false, a v3 bitmap header will be written where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); @@ -126,11 +128,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] [WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] [WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] + [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] + [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] public void Encode_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); [Theory] [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] + [WithFile(Bit32Rgba, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] public void Encode_PreservesAlpha(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); @@ -139,8 +144,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp { using (Image image = provider.GetImage()) { - // There is no alpha in bmp with 24 bits per pixels, so the reference image will be made opaque. - if (bitsPerPixel == BmpBitsPerPixel.Pixel24) + // There is no alpha in bmp with less then 32 bits per pixels, so the reference image will be made opaque. + if (bitsPerPixel != BmpBitsPerPixel.Pixel32) { image.Mutate(c => c.MakeOpaque()); } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index f82278ef5..62b7ae2ec 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -236,6 +236,7 @@ namespace SixLabors.ImageSharp.Tests public const string Bit1Pal1 = "Bmp/pal1p1.bmp"; public const string Bit4 = "Bmp/pal4.bmp"; public const string Bit8 = "Bmp/test8.bmp"; + public const string Bit8Gs = "Bmp/pal8gs.bmp"; public const string Bit8Inverted = "Bmp/test8-inverted.bmp"; public const string Bit16 = "Bmp/test16.bmp"; public const string Bit16Inverted = "Bmp/test16-inverted.bmp"; diff --git a/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs b/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs index e4a7572d6..78431f31a 100644 --- a/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs +++ b/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs @@ -60,6 +60,8 @@ namespace SixLabors.ImageSharp.Tests Bgra5551 = 1 << 22, + Gray8 = 1 << 23, + // TODO: Add multi-flag entries by rules defined in PackedPixelConverterHelper // "All" is handled as a separate, individual case instead of using bitwise OR diff --git a/tests/Images/Input/Bmp/pal8gs.bmp b/tests/Images/Input/Bmp/pal8gs.bmp new file mode 100644 index 0000000000000000000000000000000000000000..66a0d70dc34f6c25554ea15d779f6114bd042f74 GIT binary patch literal 9254 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 Date: Tue, 7 May 2019 20:43:12 +0200 Subject: [PATCH 147/223] Changed WuQuantizer to OctreeQuantizer --- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 530bcf8cd..0ef2046a8 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -304,7 +304,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp byte[] colorPalette = new byte[ColorPaletteSize8Bit]; #endif - var quantizer = new WuQuantizer(256); + var quantizer = new OctreeQuantizer(256); QuantizedFrame quantized = quantizer.CreateFrameQuantizer(this.configuration).QuantizeFrame(image); int idx = 0; From 44c4763e7254f54899ce010d4406e4e4deaa3801 Mon Sep 17 00:00:00 2001 From: SLane35 Date: Thu, 9 May 2019 02:46:40 +0300 Subject: [PATCH 148/223] Update Readme (#905) A few minor grammatical corrections. --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ceb28564b..515fc7196 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Designed to democratize image processing, ImageSharp brings you an incredibly po Compared to `System.Drawing` we have been able to develop something much more flexible, easier to code against, and much, much less prone to memory leaks. Gone are system-wide process-locks; ImageSharp images are thread-safe and fully supported in web environments. -Built against .NET Standard 1.3 ImageSharp can be used in device, cloud, and embedded/IoT scenarios. +Built against .NET Standard 1.3, ImageSharp can be used in device, cloud, and embedded/IoT scenarios. ### Documentation For all SixLabors projects, including ImageSharp: @@ -41,15 +41,15 @@ Install stable releases via Nuget; development releases are available via MyGet. The **ImageSharp** library is made up of multiple packages: - **SixLabors.ImageSharp** - - Contains the generic `Image` class, PixelFormats, Primitives, Configuration, and other core functionality. - - The `IImageFormat` interface, Jpeg, Png, Bmp, and Gif formats. - - Transform methods like Resize, Crop, Skew, Rotate - Anything that alters the dimensions of the image. - - Non-transform methods like Gaussian Blur, Pixelate, Edge Detection - Anything that maintains the original image dimensions. + - Contains the generic `Image` class, PixelFormats, Primitives, Configuration, and other core functionality + - The `IImageFormat` interface, Jpeg, Png, Bmp, and Gif formats + - Transform methods like Resize, Crop, Skew, Rotate - anything that alters the dimensions of the image + - Non-transform methods like Gaussian Blur, Pixelate, Edge Detection - anything that maintains the original image dimensions - **SixLabors.ImageSharp.Drawing** - - Brushes and various drawing algorithms, including drawing images. + - Brushes and various drawing algorithms, including drawing images - Various vector drawing methods for drawing paths, polygons etc. - - Text drawing. + - Text drawing ### Build Status @@ -117,7 +117,7 @@ Alternatively, you can work from command line and/or with a lightweight editor o - [Visual Studio Code](https://code.visualstudio.com/) with [C# Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp) - [.NET Core](https://www.microsoft.com/net/core#linuxubuntu) -To clone ImageSharp locally click the "Clone in Windows" button above or run the following git commands. +To clone ImageSharp locally, click the "Clone in Windows" button above or run the following git commands: ```bash git clone https://github.com/SixLabors/ImageSharp From 6ce4efe1783d576b5bd59de25dbdef397146142c Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Thu, 9 May 2019 20:35:19 +0200 Subject: [PATCH 149/223] Trying MagickReferenceDecoder for the 8bit greyscale image encoder tests --- .../Formats/Bmp/BmpEncoderTests.cs | 50 +++++++++++++++---- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index 42ec3088d..a56cee47d 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -2,10 +2,13 @@ // Licensed under the Apache License, Version 2.0. using System.IO; + +using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; using Xunit; using Xunit.Abstractions; @@ -110,13 +113,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [WithFile(Bit32Rgba, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] [WithFile(WinBmpv4, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] [WithFile(WinBmpv5, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] - // WinBmpv3 is a 24 bits per pixel image - [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] - [WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] - [WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] - [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] - [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] - public void Encode_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + public void Encode_32Bit_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) // if supportTransparency is false, a v3 bitmap header will be written where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); @@ -125,13 +122,44 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [WithFile(Bit32Rgba, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] [WithFile(WinBmpv4, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] [WithFile(WinBmpv5, PixelTypes.Rgba32 | PixelTypes.Rgb24, BmpBitsPerPixel.Pixel32)] + public void Encode_32Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); + + [Theory] + // WinBmpv3 is a 24 bits per pixel image + [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] + public void Encode_24Bit_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); + + [Theory] [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] + public void Encode_24Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); + + + [Theory] + [WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] + [WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] + public void Encode_16Bit_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); + + [Theory] [WithFile(Rgb16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] [WithFile(Bit16, PixelTypes.Bgra5551, BmpBitsPerPixel.Pixel16)] + public void Encode_16Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); + + [Theory] [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] - public void Encode_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) - where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); + public void Encode_8Bit_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false, referenceDecoder: new MagickReferenceDecoder()); + + [Theory] + [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] + [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] + public void Encode_8Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true, referenceDecoder: new MagickReferenceDecoder()); [Theory] [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] @@ -139,7 +167,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp public void Encode_PreservesAlpha(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); - private static void TestBmpEncoderCore(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel, bool supportTransparency = true) + private static void TestBmpEncoderCore(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel, bool supportTransparency = true, IImageDecoder referenceDecoder = null) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) @@ -153,7 +181,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp var encoder = new BmpEncoder { BitsPerPixel = bitsPerPixel, SupportTransparency = supportTransparency }; // Does DebugSave & load reference CompareToReferenceInput(): - image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder); + image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder, referenceDecoder: referenceDecoder); } } } From b5df1c785c0929c117fcd2d28e0f68e0e838a1d3 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Thu, 9 May 2019 22:07:04 +0200 Subject: [PATCH 150/223] Setting dither to false in the OctreeQuantizer --- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 2 +- .../Processors/Quantization/OctreeQuantizer.cs | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 0ef2046a8..be82e2cab 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -304,7 +304,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp byte[] colorPalette = new byte[ColorPaletteSize8Bit]; #endif - var quantizer = new OctreeQuantizer(256); + var quantizer = new OctreeQuantizer(dither: false, maxColors: 256); QuantizedFrame quantized = quantizer.CreateFrameQuantizer(this.configuration).QuantizeFrame(image); int idx = 0; diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs index d49023886..f5fa8c95d 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Initializes a new instance of the class. /// - /// Whether to apply dithering to the output image + /// Whether to apply dithering to the output image. public OctreeQuantizer(bool dither) : this(GetDiffuser(dither), QuantizerConstants.MaxColors) { @@ -44,7 +44,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Initializes a new instance of the class. /// - /// The error diffusion algorithm, if any, to apply to the output image + /// The maximum number of colors to hold in the color palette. + /// Whether to apply dithering to the output image. + public OctreeQuantizer(bool dither, int maxColors) + : this(GetDiffuser(dither), maxColors) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The error diffusion algorithm, if any, to apply to the output image. public OctreeQuantizer(IErrorDiffuser diffuser) : this(diffuser, QuantizerConstants.MaxColors) { @@ -53,8 +63,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Initializes a new instance of the class. /// - /// The error diffusion algorithm, if any, to apply to the output image - /// The maximum number of colors to hold in the color palette + /// The error diffusion algorithm, if any, to apply to the output image. + /// The maximum number of colors to hold in the color palette. public OctreeQuantizer(IErrorDiffuser diffuser, int maxColors) { this.Diffuser = diffuser; From ebd5cd4f5bf839325f19532cb6b26c9bfe605318 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 9 May 2019 22:18:18 +0200 Subject: [PATCH 151/223] verbose naming for Histogram Equalization stuff + make it public --- ... AdaptiveHistogramEqualizationProcessor.cs} | 18 +++++++++++++----- ...eHistogramEqualizationProcessor{TPixel}.cs} | 6 +++--- ...ogramEqualizationSlidingWindowProcessor.cs} | 16 ++++++++++++---- ...alizationSlidingWindowProcessor{TPixel}.cs} | 6 +++--- .../GlobalHistogramEqualizationProcessor.cs | 8 +++++++- .../HistogramEqualizationProcessor.cs | 6 +++--- 6 files changed, 41 insertions(+), 19 deletions(-) rename src/ImageSharp/Processing/Processors/Normalization/{AdaptiveHistEqualizationProcessor.cs => AdaptiveHistogramEqualizationProcessor.cs} (76%) rename src/ImageSharp/Processing/Processors/Normalization/{AdaptiveHistEqualizationProcessor{TPixel}.cs => AdaptiveHistogramEqualizationProcessor{TPixel}.cs} (98%) rename src/ImageSharp/Processing/Processors/Normalization/{AdaptiveHistEqualizationSWProcessor.cs => AdaptiveHistogramEqualizationSlidingWindowProcessor.cs} (72%) rename src/ImageSharp/Processing/Processors/Normalization/{AdaptiveHistEqualizationSWProcessor{TPixel}.cs => AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs} (98%) diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor.cs similarity index 76% rename from src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs rename to src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor.cs index 4fd0f853d..ad27ae020 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor.cs @@ -7,17 +7,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// Applies an adaptive histogram equalization to the image. The image is split up in tiles. For each tile a cumulative distribution function (cdf) is calculated. /// To calculate the final equalized pixel value, the cdf value of four adjacent tiles will be interpolated. /// - internal class AdaptiveHistEqualizationProcessor : HistogramEqualizationProcessor + public class AdaptiveHistogramEqualizationProcessor : HistogramEqualizationProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images /// or 65536 for 16-bit grayscale images. /// Indicating whether to clip the histogram bins at a specific value. /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. - public AdaptiveHistEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int numberOfTiles) + public AdaptiveHistogramEqualizationProcessor( + int luminanceLevels, + bool clipHistogram, + float clipLimitPercentage, + int numberOfTiles) : base(luminanceLevels, clipHistogram, clipLimitPercentage) { this.NumberOfTiles = numberOfTiles; @@ -31,7 +35,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// public override IImageProcessor CreatePixelSpecificProcessor() { - return new AdaptiveHistEqualizationProcessor(this.LuminanceLevels, this.ClipHistogram, this.ClipLimitPercentage, this.NumberOfTiles); + return new AdaptiveHistogramEqualizationProcessor( + this.LuminanceLevels, + this.ClipHistogram, + this.ClipLimitPercentage, + this.NumberOfTiles); } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs similarity index 98% rename from src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor{TPixel}.cs rename to src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs index 930c4010f..333444eb3 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs @@ -21,18 +21,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// To calculate the final equalized pixel value, the cdf value of four adjacent tiles will be interpolated. /// /// The pixel format. - internal class AdaptiveHistEqualizationProcessor : HistogramEqualizationProcessor + internal class AdaptiveHistogramEqualizationProcessor : HistogramEqualizationProcessor where TPixel : struct, IPixel { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images /// or 65536 for 16-bit grayscale images. /// Indicating whether to clip the histogram bins at a specific value. /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. - public AdaptiveHistEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int tiles) + public AdaptiveHistogramEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int tiles) : base(luminanceLevels, clipHistogram, clipLimitPercentage) { Guard.MustBeGreaterThanOrEqualTo(tiles, 2, nameof(tiles)); diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor.cs similarity index 72% rename from src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs rename to src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor.cs index cd4a9644f..36f798975 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor.cs @@ -6,17 +6,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// /// Applies an adaptive histogram equalization to the image using an sliding window approach. /// - internal class AdaptiveHistEqualizationSWProcessor : HistogramEqualizationProcessor + public class AdaptiveHistogramEqualizationSlidingWindowProcessor : HistogramEqualizationProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images /// or 65536 for 16-bit grayscale images. /// Indicating whether to clip the histogram bins at a specific value. /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. - public AdaptiveHistEqualizationSWProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int numberOfTiles) + public AdaptiveHistogramEqualizationSlidingWindowProcessor( + int luminanceLevels, + bool clipHistogram, + float clipLimitPercentage, + int numberOfTiles) : base(luminanceLevels, clipHistogram, clipLimitPercentage) { this.NumberOfTiles = numberOfTiles; @@ -30,7 +34,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// public override IImageProcessor CreatePixelSpecificProcessor() { - return new AdaptiveHistEqualizationSWProcessor(this.LuminanceLevels, this.ClipHistogram, this.ClipLimitPercentage, this.NumberOfTiles); + return new AdaptiveHistogramEqualizationSlidingWindowProcessor( + this.LuminanceLevels, + this.ClipHistogram, + this.ClipLimitPercentage, + this.NumberOfTiles); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs similarity index 98% rename from src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor{TPixel}.cs rename to src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs index 3584b1a88..40e2d41d9 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs @@ -20,18 +20,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// Applies an adaptive histogram equalization to the image using an sliding window approach. /// /// The pixel format. - internal class AdaptiveHistEqualizationSWProcessor : HistogramEqualizationProcessor + internal class AdaptiveHistogramEqualizationSlidingWindowProcessor : HistogramEqualizationProcessor where TPixel : struct, IPixel { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The number of different luminance levels. Typical values are 256 for 8-bit grayscale images /// or 65536 for 16-bit grayscale images. /// Indicating whether to clip the histogram bins at a specific value. /// Histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. /// The number of tiles the image is split into (horizontal and vertically). Minimum value is 2. Maximum value is 100. - public AdaptiveHistEqualizationSWProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int tiles) + public AdaptiveHistogramEqualizationSlidingWindowProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage, int tiles) : base(luminanceLevels, clipHistogram, clipLimitPercentage) { Guard.MustBeGreaterThanOrEqualTo(tiles, 2, nameof(tiles)); diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs index 62e018595..9af2c8352 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor.cs @@ -6,8 +6,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// /// Defines a global histogram equalization applicable to an . /// - internal class GlobalHistogramEqualizationProcessor : HistogramEqualizationProcessor + public class GlobalHistogramEqualizationProcessor : HistogramEqualizationProcessor { + /// + /// Initializes a new instance of the class. + /// + /// The number of luminance levels. + /// A value indicating whether to clip the histogram bins at a specific value. + /// The histogram clip limit in percent of the total pixels in the tile. Histogram bins which exceed this limit, will be capped at this value. public GlobalHistogramEqualizationProcessor(int luminanceLevels, bool clipHistogram, float clipLimitPercentage) : base(luminanceLevels, clipHistogram, clipLimitPercentage) { diff --git a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs index 4aad1f564..b1d12f847 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// /// Defines a processor that normalizes the histogram of an image. /// - internal abstract class HistogramEqualizationProcessor : IImageProcessor + public abstract class HistogramEqualizationProcessor : IImageProcessor { /// /// Initializes a new instance of the class. @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization break; case HistogramEqualizationMethod.AdaptiveTileInterpolation: - processor = new AdaptiveHistEqualizationProcessor( + processor = new AdaptiveHistogramEqualizationProcessor( options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage, @@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization break; case HistogramEqualizationMethod.AdaptiveSlidingWindow: - processor = new AdaptiveHistEqualizationSWProcessor( + processor = new AdaptiveHistogramEqualizationSlidingWindowProcessor( options.LuminanceLevels, options.ClipHistogram, options.ClipLimitPercentage, From 4575d44901dc4a0abb2a4b1646f580b49b017f5a Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 9 May 2019 22:32:27 +0200 Subject: [PATCH 152/223] formatting --- .../AffineTransformProcessor{TPixel}.cs | 21 ++++-- .../Transforms/AutoOrientProcessor{TPixel}.cs | 5 +- .../ProjectiveTransformProcessor{TPixel}.cs | 27 ++++++-- .../Transforms/RotateProcessor{TPixel}.cs | 68 +++++++++++-------- 4 files changed, 80 insertions(+), 41 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs index e57ce826b..5a043cb20 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs @@ -25,18 +25,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.Definition = definition; } + protected AffineTransformProcessor Definition { get; } + private Size TargetDimensions => this.Definition.TargetDimensions; private Matrix3x2 TransformMatrix => this.Definition.TransformMatrix; - protected AffineTransformProcessor Definition { get; } - /// protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = - source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions, x.Metadata.DeepClone())); + IEnumerable> frames = source.Frames.Select( + x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions, x.Metadata.DeepClone())); // Use the overload to prevent an extra frame being added return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); @@ -111,10 +111,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Use the single precision position to calculate correct bounding pixels // otherwise we get rogue pixels outside of the bounds. var point = Vector2.Transform(new Vector2(x, y), matrix); - kernel.Convolve(point, x, ref ySpanRef, ref xSpanRef, source.PixelBuffer, vectorSpan); + kernel.Convolve( + point, + x, + ref ySpanRef, + ref xSpanRef, + source.PixelBuffer, + vectorSpan); } - PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); + PixelOperations.Instance.FromVector4Destructive( + configuration, + vectorSpan, + targetRowSpan); } }); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs index 257c223dc..8b3ec8690 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs @@ -61,7 +61,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } /// - protected override void OnFrameApply(ImageFrame sourceBase, Rectangle sourceRectangle, Configuration config) + protected override void OnFrameApply( + ImageFrame sourceBase, + Rectangle sourceRectangle, + Configuration config) { // All processing happens at the image level within BeforeImageApply(); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs index e6d885803..ab07040f7 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs @@ -33,15 +33,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = - source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions.Width, this.TargetDimensions.Height, x.Metadata.DeepClone())); + IEnumerable> frames = source.Frames.Select( + x => new ImageFrame( + source.GetConfiguration(), + this.TargetDimensions.Width, + this.TargetDimensions.Height, + x.Metadata.DeepClone())); // Use the overload to prevent an extra frame being added return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); } /// - protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) + protected override void OnFrameApply( + ImageFrame source, + ImageFrame destination, + Rectangle sourceRectangle, + Configuration configuration) { Matrix4x4 transformMatrix = this.definition.TransformMatrix; @@ -110,10 +118,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Use the single precision position to calculate correct bounding pixels // otherwise we get rogue pixels outside of the bounds. Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, matrix); - kernel.Convolve(point, x, ref ySpanRef, ref xSpanRef, source.PixelBuffer, vectorSpan); + kernel.Convolve( + point, + x, + ref ySpanRef, + ref xSpanRef, + source.PixelBuffer, + vectorSpan); } - PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan); + PixelOperations.Instance.FromVector4Destructive( + configuration, + vectorSpan, + targetRowSpan); } }); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor{TPixel}.cs index aac6f6514..252cb77ab 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor{TPixel}.cs @@ -27,18 +27,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private float Degrees { get; } /// - protected override void OnFrameApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) - { - if (this.OptimizedApply(source, destination, configuration)) - { - return; - } - - base.OnFrameApply(source, destination, sourceRectangle, configuration); - } - - /// - protected override void AfterImageApply(Image source, Image destination, Rectangle sourceRectangle) + protected override void AfterImageApply( + Image source, + Image destination, + Rectangle sourceRectangle) { ExifProfile profile = destination.Metadata.ExifProfile; if (profile is null) @@ -57,6 +49,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms base.AfterImageApply(source, destination, sourceRectangle); } + /// + protected override void OnFrameApply( + ImageFrame source, + ImageFrame destination, + Rectangle sourceRectangle, + Configuration configuration) + { + if (this.OptimizedApply(source, destination, configuration)) + { + return; + } + + base.OnFrameApply(source, destination, sourceRectangle, configuration); + } + /// /// Wraps a given angle in degrees so that it falls withing the 0-360 degree range /// @@ -83,7 +90,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// The /// - private bool OptimizedApply(ImageFrame source, ImageFrame destination, Configuration configuration) + private bool OptimizedApply( + ImageFrame source, + ImageFrame destination, + Configuration configuration) { // Wrap the degrees to keep within 0-360 so we can apply optimizations when possible. float degrees = WrapDegrees(this.Degrees); @@ -117,16 +127,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } /// - /// Rotates the image 270 degrees clockwise at the centre point. + /// Rotates the image 180 degrees clockwise at the centre point. /// /// The source image. /// The destination image. /// The configuration. - private void Rotate270(ImageFrame source, ImageFrame destination, Configuration configuration) + private void Rotate180(ImageFrame source, ImageFrame destination, Configuration configuration) { int width = source.Width; int height = source.Height; - Rectangle destinationBounds = destination.Bounds(); ParallelHelper.IterateRows( source.Bounds(), @@ -136,31 +145,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int y = rows.Min; y < rows.Max; y++) { Span sourceRow = source.GetPixelRowSpan(y); + Span targetRow = destination.GetPixelRowSpan(height - y - 1); + for (int x = 0; x < width; x++) { - int newX = height - y - 1; - newX = height - newX - 1; - int newY = width - x - 1; - - if (destinationBounds.Contains(newX, newY)) - { - destination[newX, newY] = sourceRow[x]; - } + targetRow[width - x - 1] = sourceRow[x]; } } }); } /// - /// Rotates the image 180 degrees clockwise at the centre point. + /// Rotates the image 270 degrees clockwise at the centre point. /// /// The source image. /// The destination image. /// The configuration. - private void Rotate180(ImageFrame source, ImageFrame destination, Configuration configuration) + private void Rotate270(ImageFrame source, ImageFrame destination, Configuration configuration) { int width = source.Width; int height = source.Height; + Rectangle destinationBounds = destination.Bounds(); ParallelHelper.IterateRows( source.Bounds(), @@ -170,11 +175,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int y = rows.Min; y < rows.Max; y++) { Span sourceRow = source.GetPixelRowSpan(y); - Span targetRow = destination.GetPixelRowSpan(height - y - 1); - for (int x = 0; x < width; x++) { - targetRow[width - x - 1] = sourceRow[x]; + int newX = height - y - 1; + newX = height - newX - 1; + int newY = width - x - 1; + + if (destinationBounds.Contains(newX, newY)) + { + destination[newX, newY] = sourceRow[x]; + } } } }); From 9f0cce38ab4e8c5c52dbff4f9a8fa496ee87f2f9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 9 May 2019 23:39:05 +0200 Subject: [PATCH 153/223] refactor of Overlays --- src/ImageSharp/Color/Color.cs | 2 + src/ImageSharp/Primitives/ValueSize.cs | 2 +- .../Processing/BackgroundColorExtensions.cs | 45 ++++--- src/ImageSharp/Processing/GlowExtensions.cs | 98 +++++++------- .../Filters/LomographProcessor{TPixel}.cs | 4 +- .../Filters/PolaroidProcessor{TPixel}.cs | 14 +- .../Overlays/BackgroundColorProcessor.cs | 86 ++---------- .../BackgroundColorProcessor{TPixel}.cs | 101 ++++++++++++++ .../Processors/Overlays/GlowProcessor.cs | 125 ++++-------------- .../Overlays/GlowProcessor{TPixel}.cs | 112 ++++++++++++++++ .../Processors/Overlays/VignetteProcessor.cs | 120 +++-------------- .../Overlays/VignetteProcessor{TPixel}.cs | 114 ++++++++++++++++ .../Processing/VignetteExtensions.cs | 121 ++++++++++------- tests/ImageSharp.Benchmarks/Samplers/Glow.cs | 4 +- .../ImageSharp.Tests/Drawing/BeziersTests.cs | 6 +- .../ImageSharp.Tests/Drawing/DrawImageTest.cs | 2 +- .../ImageSharp.Tests/Drawing/DrawPathTests.cs | 8 +- .../Drawing/LineComplexPolygonTests.cs | 17 ++- tests/ImageSharp.Tests/Drawing/LineTests.cs | 33 ++--- .../ImageSharp.Tests/Drawing/PolygonTests.cs | 9 +- .../Drawing/SolidBezierTests.cs | 16 +-- .../Drawing/SolidComplexPolygonTests.cs | 9 +- .../Drawing/SolidPolygonTests.cs | 25 ++-- .../Processing/Effects/BackgroundColorTest.cs | 24 ++-- .../Processing/Overlays/GlowTest.cs | 16 +-- .../Processing/Overlays/VignetteTest.cs | 18 +-- .../Processors/Effects/BackgroundColorTest.cs | 4 +- .../Processors/Overlays/GlowTest.cs | 6 +- .../Processors/Overlays/OverlayTestBase.cs | 13 +- .../Processors/Overlays/VignetteTest.cs | 6 +- 30 files changed, 652 insertions(+), 508 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index bc97393cc..021cea415 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -86,6 +86,8 @@ namespace SixLabors.ImageSharp public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(new Rgba32(r, g, b, a)); + public static Color FromRgb(byte r, byte g, byte b) => FromRgba(r, g, b, 255); + /// /// Creates a new instance from the string representing a color in hexadecimal form. /// diff --git a/src/ImageSharp/Primitives/ValueSize.cs b/src/ImageSharp/Primitives/ValueSize.cs index 44bee5030..577e9187a 100644 --- a/src/ImageSharp/Primitives/ValueSize.cs +++ b/src/ImageSharp/Primitives/ValueSize.cs @@ -7,7 +7,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Primitives { /// - /// Represents a value in relation to a value on the image + /// Represents a value in relation to a value on the image. /// internal readonly struct ValueSize : IEquatable { diff --git a/src/ImageSharp/Processing/BackgroundColorExtensions.cs b/src/ImageSharp/Processing/BackgroundColorExtensions.cs index 3b794e335..dd1cc1ed2 100644 --- a/src/ImageSharp/Processing/BackgroundColorExtensions.cs +++ b/src/ImageSharp/Processing/BackgroundColorExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Overlays; using SixLabors.Primitives; @@ -16,53 +15,55 @@ namespace SixLabors.ImageSharp.Processing /// /// Replaces the background color of image with the given one. /// - /// The pixel format. /// The image this method extends. /// The color to set as the background. - /// The . - public static IImageProcessingContext BackgroundColor(this IImageProcessingContext source, TPixel color) - where TPixel : struct, IPixel - => BackgroundColor(source, GraphicsOptions.Default, color); + /// The to allow chaining of operations. + public static IImageProcessingContext BackgroundColor(this IImageProcessingContext source, Color color) => + BackgroundColor(source, GraphicsOptions.Default, color); /// /// Replaces the background color of image with the given one. /// - /// The pixel format. /// The image this method extends. /// The color to set as the background. /// /// The structure that specifies the portion of the image object to alter. /// - /// The . - public static IImageProcessingContext BackgroundColor(this IImageProcessingContext source, TPixel color, Rectangle rectangle) - where TPixel : struct, IPixel - => BackgroundColor(source, GraphicsOptions.Default, color, rectangle); + /// The to allow chaining of operations. + public static IImageProcessingContext BackgroundColor( + this IImageProcessingContext source, + Color color, + Rectangle rectangle) => + BackgroundColor(source, GraphicsOptions.Default, color, rectangle); /// /// Replaces the background color of image with the given one. /// - /// The pixel format. /// The image this method extends. /// The options effecting pixel blending. /// The color to set as the background. - /// The . - public static IImageProcessingContext BackgroundColor(this IImageProcessingContext source, GraphicsOptions options, TPixel color) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BackgroundColorProcessor(color, options)); + /// The to allow chaining of operations. + public static IImageProcessingContext BackgroundColor( + this IImageProcessingContext source, + GraphicsOptions options, + Color color) => + source.ApplyProcessor(new BackgroundColorProcessor(color, options)); /// /// Replaces the background color of image with the given one. /// - /// The pixel format. /// The image this method extends. /// The options effecting pixel blending. /// The color to set as the background. /// /// The structure that specifies the portion of the image object to alter. /// - /// The . - public static IImageProcessingContext BackgroundColor(this IImageProcessingContext source, GraphicsOptions options, TPixel color, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new BackgroundColorProcessor(color, options), rectangle); + /// The to allow chaining of operations. + public static IImageProcessingContext BackgroundColor( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + Rectangle rectangle) => + source.ApplyProcessor(new BackgroundColorProcessor(color, options), rectangle); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/GlowExtensions.cs b/src/ImageSharp/Processing/GlowExtensions.cs index 759fdccbe..39734882b 100644 --- a/src/ImageSharp/Processing/GlowExtensions.cs +++ b/src/ImageSharp/Processing/GlowExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing.Processors.Overlays; using SixLabors.Primitives; @@ -17,22 +16,18 @@ namespace SixLabors.ImageSharp.Processing /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The to allow chaining of operations. - public static IImageProcessingContext Glow(this IImageProcessingContext source) - where TPixel : struct, IPixel - => Glow(source, GraphicsOptions.Default); + public static IImageProcessingContext Glow(this IImageProcessingContext source) => + Glow(source, GraphicsOptions.Default); /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The color to set as the glow. /// The to allow chaining of operations. - public static IImageProcessingContext Glow(this IImageProcessingContext source, TPixel color) - where TPixel : struct, IPixel + public static IImageProcessingContext Glow(this IImageProcessingContext source, Color color) { return Glow(source, GraphicsOptions.Default, color); } @@ -40,31 +35,26 @@ namespace SixLabors.ImageSharp.Processing /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The the radius. /// The to allow chaining of operations. - public static IImageProcessingContext Glow(this IImageProcessingContext source, float radius) - where TPixel : struct, IPixel - => Glow(source, GraphicsOptions.Default, radius); + public static IImageProcessingContext Glow(this IImageProcessingContext source, float radius) => + Glow(source, GraphicsOptions.Default, radius); /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext Glow(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel - => source.Glow(GraphicsOptions.Default, rectangle); + public static IImageProcessingContext Glow(this IImageProcessingContext source, Rectangle rectangle) => + source.Glow(GraphicsOptions.Default, rectangle); /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The color to set as the glow. /// The the radius. @@ -72,63 +62,66 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext Glow(this IImageProcessingContext source, TPixel color, float radius, Rectangle rectangle) - where TPixel : struct, IPixel - => source.Glow(GraphicsOptions.Default, color, ValueSize.Absolute(radius), rectangle); + public static IImageProcessingContext Glow( + this IImageProcessingContext source, + Color color, + float radius, + Rectangle rectangle) => + source.Glow(GraphicsOptions.Default, color, ValueSize.Absolute(radius), rectangle); /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting things like blending. /// The to allow chaining of operations. - public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options) - where TPixel : struct, IPixel - => source.Glow(options, NamedColors.Black, ValueSize.PercentageOfWidth(0.5f)); + public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options) => + source.Glow(options, Color.Black, ValueSize.PercentageOfWidth(0.5f)); /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting things like blending. /// The color to set as the glow. /// The to allow chaining of operations. - public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, TPixel color) - where TPixel : struct, IPixel - => source.Glow(options, color, ValueSize.PercentageOfWidth(0.5f)); + public static IImageProcessingContext Glow( + this IImageProcessingContext source, + GraphicsOptions options, + Color color) => + source.Glow(options, color, ValueSize.PercentageOfWidth(0.5f)); /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting things like blending. /// The the radius. /// The to allow chaining of operations. - public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, float radius) - where TPixel : struct, IPixel - => source.Glow(options, NamedColors.Black, ValueSize.Absolute(radius)); + public static IImageProcessingContext Glow( + this IImageProcessingContext source, + GraphicsOptions options, + float radius) => + source.Glow(options, Color.Black, ValueSize.Absolute(radius)); /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting things like blending. /// /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, Rectangle rectangle) - where TPixel : struct, IPixel - => source.Glow(options, NamedColors.Black, ValueSize.PercentageOfWidth(0.5f), rectangle); + public static IImageProcessingContext Glow( + this IImageProcessingContext source, + GraphicsOptions options, + Rectangle rectangle) => + source.Glow(options, Color.Black, ValueSize.PercentageOfWidth(0.5f), rectangle); /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting things like blending. /// The color to set as the glow. @@ -137,14 +130,17 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float radius, Rectangle rectangle) - where TPixel : struct, IPixel - => source.Glow(options, color, ValueSize.Absolute(radius), rectangle); + public static IImageProcessingContext Glow( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float radius, + Rectangle rectangle) => + source.Glow(options, color, ValueSize.Absolute(radius), rectangle); /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting things like blending. /// The color to set as the glow. @@ -153,21 +149,27 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - private static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, TPixel color, ValueSize radius, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new GlowProcessor(color, radius, options), rectangle); + private static IImageProcessingContext Glow( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + ValueSize radius, + Rectangle rectangle) => + source.ApplyProcessor(new GlowProcessor(color, radius, options), rectangle); /// /// Applies a radial glow effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting things like blending. /// The color to set as the glow. /// The the radius. /// The to allow chaining of operations. - private static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options, TPixel color, ValueSize radius) - where TPixel : struct, IPixel - => source.ApplyProcessor(new GlowProcessor(color, radius, options)); + private static IImageProcessingContext Glow( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + ValueSize radius) => + source.ApplyProcessor(new GlowProcessor(color, radius, options)); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs index c15cf6fc9..e0f85945a 100644 --- a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters internal class LomographProcessor : FilterProcessor where TPixel : struct, IPixel { - private static readonly TPixel VeryDarkGreen = ColorBuilder.FromRGBA(0, 10, 0, 255); + private static readonly Color VeryDarkGreen = Color.FromRgba(0, 10, 0, 255); /// /// Initializes a new instance of the class. @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// protected override void AfterFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { - new VignetteProcessor(VeryDarkGreen).Apply(source, sourceRectangle, configuration); + new VignetteProcessor(VeryDarkGreen).Apply(source, sourceRectangle, configuration); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs index befcfc1f4..0f511ee29 100644 --- a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs @@ -13,8 +13,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters internal class PolaroidProcessor : FilterProcessor where TPixel : struct, IPixel { - private static readonly TPixel VeryDarkOrange = ColorBuilder.FromRGB(102, 34, 0); - private static readonly TPixel LightOrange = ColorBuilder.FromRGBA(255, 153, 102, 128); + private static readonly Color LightOrange = Color.FromRgba(255, 153, 102, 128); + + private static readonly Color VeryDarkOrange = Color.FromRgb(102, 34, 0); /// /// Initializes a new instance of the class. @@ -26,10 +27,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters } /// - protected override void AfterFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + protected override void AfterFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) { - new VignetteProcessor(VeryDarkOrange).Apply(source, sourceRectangle, configuration); - new GlowProcessor(LightOrange, source.Width / 4F).Apply(source, sourceRectangle, configuration); + new VignetteProcessor(VeryDarkOrange).Apply(source, sourceRectangle, configuration); + new GlowProcessor(LightOrange, source.Width / 4F).Apply(source, sourceRectangle, configuration); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs index 25787ff92..0dd0c4118 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs @@ -1,31 +1,21 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; -using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Memory; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Overlays { /// - /// Sets the background color of the image. + /// Defines a processing operation to replace the background color of an . /// - /// The pixel format. - internal class BackgroundColorProcessor : ImageProcessor - where TPixel : struct, IPixel + public sealed class BackgroundColorProcessor : IImageProcessor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The to set the background color to. + /// The to set the background color to. /// The options defining blending algorithm and amount. - public BackgroundColorProcessor(TPixel color, GraphicsOptions options) + public BackgroundColorProcessor(Color color, GraphicsOptions options) { this.Color = color; this.GraphicsOptions = options; @@ -39,69 +29,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays /// /// Gets the background color value. /// - public TPixel Color { get; } + public Color Color { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - int startY = sourceRectangle.Y; - int endY = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - int width = maxX - minX; - - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); - - using (IMemoryOwner colors = source.MemoryAllocator.Allocate(width)) - using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width)) - { - // Be careful! Do not capture colorSpan & amountSpan in the lambda below! - Span colorSpan = colors.GetSpan(); - Span amountSpan = amount.GetSpan(); - - colorSpan.Fill(this.Color); - amountSpan.Fill(this.GraphicsOptions.BlendPercentage); - - PixelBlender blender = PixelOperations.Instance.GetPixelBlender(this.GraphicsOptions); - - ParallelHelper.IterateRows( - workingRect, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span destination = - source.GetPixelRowSpan(y - startY).Slice(minX - startX, width); - - // This switched color & destination in the 2nd and 3rd places because we are applying the target color under the current one - blender.Blend( - source.Configuration, - destination, - colors.GetSpan(), - destination, - amount.GetSpan()); - } - }); - } + return new BackgroundColorProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs new file mode 100644 index 000000000..c4af59fec --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs @@ -0,0 +1,101 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Overlays +{ + /// + /// Sets the background color of the image. + /// + /// The pixel format. + internal class BackgroundColorProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly BackgroundColorProcessor definition; + + /// + /// Initializes a new instance of the class. + /// + public BackgroundColorProcessor(BackgroundColorProcessor definition) + { + this.definition = definition; + } + + /// + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) + { + TPixel color = this.definition.Color.ToPixel(); + GraphicsOptions graphicsOptions = this.definition.GraphicsOptions; + + int startY = sourceRectangle.Y; + int endY = sourceRectangle.Bottom; + int startX = sourceRectangle.X; + int endX = sourceRectangle.Right; + + // Align start/end positions. + int minX = Math.Max(0, startX); + int maxX = Math.Min(source.Width, endX); + int minY = Math.Max(0, startY); + int maxY = Math.Min(source.Height, endY); + + // Reset offset if necessary. + if (minX > 0) + { + startX = 0; + } + + if (minY > 0) + { + startY = 0; + } + + int width = maxX - minX; + + var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + + using (IMemoryOwner colors = source.MemoryAllocator.Allocate(width)) + using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width)) + { + // Be careful! Do not capture colorSpan & amountSpan in the lambda below! + Span colorSpan = colors.GetSpan(); + Span amountSpan = amount.GetSpan(); + + colorSpan.Fill(color); + amountSpan.Fill(graphicsOptions.BlendPercentage); + + PixelBlender blender = PixelOperations.Instance.GetPixelBlender(graphicsOptions); + + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span destination = + source.GetPixelRowSpan(y - startY).Slice(minX - startX, width); + + // This switched color & destination in the 2nd and 3rd places because we are applying the target color under the current one + blender.Blend( + source.Configuration, + destination, + colors.GetSpan(), + destination, + amount.GetSpan()); + } + }); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs index 21f6be69f..4927a0ed7 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs @@ -1,69 +1,56 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; -using System.Numerics; -using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; -using SixLabors.Memory; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Overlays { /// - /// An that applies a radial glow effect an . + /// Defines a radial glow effect applicable to an . /// - /// The pixel format. - internal class GlowProcessor : ImageProcessor - where TPixel : struct, IPixel + public sealed class GlowProcessor : IImageProcessor { - private readonly PixelBlender blender; - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color or the glow. - public GlowProcessor(TPixel color) + public GlowProcessor(Color color) : this(color, 0) { } + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color or the glow. - /// The radius of the glow. - public GlowProcessor(TPixel color, ValueSize radius) - : this(color, radius, GraphicsOptions.Default) + /// The options effecting blending and composition. + public GlowProcessor(Color color, GraphicsOptions options) + : this(color, 0, options) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color or the glow. - /// The options effecting blending and composition. - public GlowProcessor(TPixel color, GraphicsOptions options) - : this(color, 0, options) + /// The radius of the glow. + internal GlowProcessor(Color color, ValueSize radius) + : this(color, radius, GraphicsOptions.Default) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color or the glow. /// The radius of the glow. /// The options effecting blending and composition. - public GlowProcessor(TPixel color, ValueSize radius, GraphicsOptions options) + internal GlowProcessor(Color color, ValueSize radius, GraphicsOptions options) { this.GlowColor = color; this.Radius = radius; - this.blender = PixelOperations.Instance.GetPixelBlender(options); this.GraphicsOptions = options; } @@ -73,86 +60,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays public GraphicsOptions GraphicsOptions { get; } /// - /// Gets or sets the glow color to apply. + /// Gets the glow color to apply. /// - public TPixel GlowColor { get; set; } + public Color GlowColor { get; } /// - /// Gets or sets the the radius. + /// Gets the the radius. /// - public ValueSize Radius { get; set; } + internal ValueSize Radius { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - // TODO: can we simplify the rectangle calculation? - int startY = sourceRectangle.Y; - int endY = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - TPixel glowColor = this.GlowColor; - Vector2 center = Rectangle.Center(sourceRectangle); - - float finalRadius = this.Radius.Calculate(source.Size()); - - float maxDistance = finalRadius > 0 ? MathF.Min(finalRadius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - int width = maxX - minX; - int offsetX = minX - startX; - - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); - - using (IMemoryOwner rowColors = source.MemoryAllocator.Allocate(width)) - { - rowColors.GetSpan().Fill(glowColor); - - ParallelHelper.IterateRowsWithTempBuffer( - workingRect, - configuration, - (rows, amounts) => - { - Span amountsSpan = amounts.Span; - - for (int y = rows.Min; y < rows.Max; y++) - { - int offsetY = y - startY; - - for (int i = 0; i < width; i++) - { - float distance = Vector2.Distance(center, new Vector2(i + offsetX, offsetY)); - amountsSpan[i] = - (this.GraphicsOptions.BlendPercentage * (1 - (.95F * (distance / maxDistance)))) - .Clamp(0, 1); - } - - Span destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width); - - this.blender.Blend( - source.Configuration, - destination, - destination, - rowColors.GetSpan(), - amountsSpan); - } - }); - } + return new GlowProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs new file mode 100644 index 000000000..3201fcbfe --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs @@ -0,0 +1,112 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Numerics; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Overlays +{ + /// + /// An that applies a radial glow effect an . + /// + /// The pixel format. + internal class GlowProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly PixelBlender blender; + + private readonly GlowProcessor definition; + + public GlowProcessor(GlowProcessor definition) + { + this.definition = definition; + this.blender = PixelOperations.Instance.GetPixelBlender(definition.GraphicsOptions); + } + + /// + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) + { + // TODO: can we simplify the rectangle calculation? + int startY = sourceRectangle.Y; + int endY = sourceRectangle.Bottom; + int startX = sourceRectangle.X; + int endX = sourceRectangle.Right; + TPixel glowColor = this.definition.GlowColor.ToPixel(); + Vector2 center = Rectangle.Center(sourceRectangle); + + float finalRadius = this.definition.Radius.Calculate(source.Size()); + + float maxDistance = finalRadius > 0 + ? MathF.Min(finalRadius, sourceRectangle.Width * .5F) + : sourceRectangle.Width * .5F; + + // Align start/end positions. + int minX = Math.Max(0, startX); + int maxX = Math.Min(source.Width, endX); + int minY = Math.Max(0, startY); + int maxY = Math.Min(source.Height, endY); + + // Reset offset if necessary. + if (minX > 0) + { + startX = 0; + } + + if (minY > 0) + { + startY = 0; + } + + int width = maxX - minX; + int offsetX = minX - startX; + + var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + + float blendPercentage = this.definition.GraphicsOptions.BlendPercentage; + + using (IMemoryOwner rowColors = source.MemoryAllocator.Allocate(width)) + { + rowColors.GetSpan().Fill(glowColor); + + ParallelHelper.IterateRowsWithTempBuffer( + workingRect, + configuration, + (rows, amounts) => + { + Span amountsSpan = amounts.Span; + + for (int y = rows.Min; y < rows.Max; y++) + { + int offsetY = y - startY; + + for (int i = 0; i < width; i++) + { + float distance = Vector2.Distance(center, new Vector2(i + offsetX, offsetY)); + amountsSpan[i] = + (blendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1); + } + + Span destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width); + + this.blender.Blend( + source.Configuration, + destination, + destination, + rowColors.GetSpan(), + amountsSpan); + } + }); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs index a8fa1d65c..66bf9f1af 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs @@ -1,63 +1,48 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; -using System.Numerics; -using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; -using SixLabors.Memory; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Overlays { /// - /// An that applies a radial vignette effect to an . + /// Defines a radial vignette effect applicable to an . /// - /// The pixel format. - internal class VignetteProcessor : ImageProcessor - where TPixel : struct, IPixel + public sealed class VignetteProcessor : IImageProcessor { - private readonly PixelBlender blender; - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color of the vignette. - public VignetteProcessor(TPixel color) + public VignetteProcessor(Color color) : this(color, GraphicsOptions.Default) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color of the vignette. /// The options effecting blending and composition. - public VignetteProcessor(TPixel color, GraphicsOptions options) + public VignetteProcessor(Color color, GraphicsOptions options) { this.VignetteColor = color; this.GraphicsOptions = options; - this.blender = PixelOperations.Instance.GetPixelBlender(options); } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color of the vignette. /// The x-radius. /// The y-radius. /// The options effecting blending and composition. - public VignetteProcessor(TPixel color, ValueSize radiusX, ValueSize radiusY, GraphicsOptions options) + internal VignetteProcessor(Color color, ValueSize radiusX, ValueSize radiusY, GraphicsOptions options) { this.VignetteColor = color; this.RadiusX = radiusX; this.RadiusY = radiusY; - this.blender = PixelOperations.Instance.GetPixelBlender(options); this.GraphicsOptions = options; } @@ -67,94 +52,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays public GraphicsOptions GraphicsOptions { get; } /// - /// Gets or sets the vignette color to apply. + /// Gets the vignette color to apply. /// - public TPixel VignetteColor { get; set; } + public Color VignetteColor { get; } /// - /// Gets or sets the the x-radius. + /// Gets the the x-radius. /// - public ValueSize RadiusX { get; set; } + internal ValueSize RadiusX { get; } /// - /// Gets or sets the the y-radius. + /// Gets the the y-radius. /// - public ValueSize RadiusY { get; set; } + internal ValueSize RadiusY { get; } - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel { - int startY = sourceRectangle.Y; - int endY = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - TPixel vignetteColor = this.VignetteColor; - Vector2 centre = Rectangle.Center(sourceRectangle); - - Size sourceSize = source.Size(); - float finalRadiusX = this.RadiusX.Calculate(sourceSize); - float finalRadiusY = this.RadiusY.Calculate(sourceSize); - float rX = finalRadiusX > 0 ? MathF.Min(finalRadiusX, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; - float rY = finalRadiusY > 0 ? MathF.Min(finalRadiusY, sourceRectangle.Height * .5F) : sourceRectangle.Height * .5F; - float maxDistance = MathF.Sqrt((rX * rX) + (rY * rY)); - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - int width = maxX - minX; - int offsetX = minX - startX; - - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); - - using (IMemoryOwner rowColors = source.MemoryAllocator.Allocate(width)) - { - rowColors.GetSpan().Fill(vignetteColor); - - ParallelHelper.IterateRowsWithTempBuffer( - workingRect, - configuration, - (rows, amounts) => - { - Span amountsSpan = amounts.Span; - - for (int y = rows.Min; y < rows.Max; y++) - { - int offsetY = y - startY; - - for (int i = 0; i < width; i++) - { - float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY)); - amountsSpan[i] = - (this.GraphicsOptions.BlendPercentage * (.9F * (distance / maxDistance))).Clamp( - 0, - 1); - } - - Span destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width); - - this.blender.Blend( - source.Configuration, - destination, - destination, - rowColors.GetSpan(), - amountsSpan); - } - }); - } + return new VignetteProcessor(this); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs new file mode 100644 index 000000000..78c3cec5e --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs @@ -0,0 +1,114 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Numerics; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Overlays +{ + /// + /// An that applies a radial vignette effect to an . + /// + /// The pixel format. + internal class VignetteProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly PixelBlender blender; + + private readonly VignetteProcessor definition; + + public VignetteProcessor(VignetteProcessor definition) + { + this.definition = definition; + this.blender = PixelOperations.Instance.GetPixelBlender(definition.GraphicsOptions); + } + + /// + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) + { + int startY = sourceRectangle.Y; + int endY = sourceRectangle.Bottom; + int startX = sourceRectangle.X; + int endX = sourceRectangle.Right; + TPixel vignetteColor = this.definition.VignetteColor.ToPixel(); + Vector2 centre = Rectangle.Center(sourceRectangle); + + Size sourceSize = source.Size(); + float finalRadiusX = this.definition.RadiusX.Calculate(sourceSize); + float finalRadiusY = this.definition.RadiusY.Calculate(sourceSize); + float rX = finalRadiusX > 0 + ? MathF.Min(finalRadiusX, sourceRectangle.Width * .5F) + : sourceRectangle.Width * .5F; + float rY = finalRadiusY > 0 + ? MathF.Min(finalRadiusY, sourceRectangle.Height * .5F) + : sourceRectangle.Height * .5F; + float maxDistance = MathF.Sqrt((rX * rX) + (rY * rY)); + + // Align start/end positions. + int minX = Math.Max(0, startX); + int maxX = Math.Min(source.Width, endX); + int minY = Math.Max(0, startY); + int maxY = Math.Min(source.Height, endY); + + // Reset offset if necessary. + if (minX > 0) + { + startX = 0; + } + + if (minY > 0) + { + startY = 0; + } + + int width = maxX - minX; + int offsetX = minX - startX; + + var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + float blendPercentage = this.definition.GraphicsOptions.BlendPercentage; + + using (IMemoryOwner rowColors = source.MemoryAllocator.Allocate(width)) + { + rowColors.GetSpan().Fill(vignetteColor); + + ParallelHelper.IterateRowsWithTempBuffer( + workingRect, + configuration, + (rows, amounts) => + { + Span amountsSpan = amounts.Span; + + for (int y = rows.Min; y < rows.Max; y++) + { + int offsetY = y - startY; + + for (int i = 0; i < width; i++) + { + float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY)); + amountsSpan[i] = (blendPercentage * (.9F * (distance / maxDistance))).Clamp(0, 1); + } + + Span destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width); + + this.blender.Blend( + source.Configuration, + destination, + destination, + rowColors.GetSpan(), + amountsSpan); + } + }); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/VignetteExtensions.cs b/src/ImageSharp/Processing/VignetteExtensions.cs index 63cdee3f8..74a59d3e1 100644 --- a/src/ImageSharp/Processing/VignetteExtensions.cs +++ b/src/ImageSharp/Processing/VignetteExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing.Processors.Overlays; using SixLabors.Primitives; @@ -9,7 +8,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing { /// - /// Defines extensions that allow the application of a radial glow to an + /// Defines extensions that allow the application of a radial glow to an /// using Mutate/Clone. /// public static class VignetteExtensions @@ -17,53 +16,47 @@ namespace SixLabors.ImageSharp.Processing /// /// Applies a radial vignette effect to an image. /// - /// The pixel format. /// The image this method extends. /// The to allow chaining of operations. - public static IImageProcessingContext Vignette(this IImageProcessingContext source) - where TPixel : struct, IPixel - => Vignette(source, GraphicsOptions.Default); + public static IImageProcessingContext Vignette(this IImageProcessingContext source) => + Vignette(source, GraphicsOptions.Default); /// /// Applies a radial vignette effect to an image. /// - /// The pixel format. /// The image this method extends. /// The color to set as the vignette. /// The to allow chaining of operations. - public static IImageProcessingContext Vignette(this IImageProcessingContext source, TPixel color) - where TPixel : struct, IPixel - => Vignette(source, GraphicsOptions.Default, color); + public static IImageProcessingContext Vignette(this IImageProcessingContext source, Color color) => + Vignette(source, GraphicsOptions.Default, color); /// /// Applies a radial vignette effect to an image. /// - /// The pixel format. /// The image this method extends. /// The the x-radius. /// The the y-radius. /// The to allow chaining of operations. - public static IImageProcessingContext Vignette(this IImageProcessingContext source, float radiusX, float radiusY) - where TPixel : struct, IPixel - => Vignette(source, GraphicsOptions.Default, radiusX, radiusY); + public static IImageProcessingContext Vignette( + this IImageProcessingContext source, + float radiusX, + float radiusY) => + Vignette(source, GraphicsOptions.Default, radiusX, radiusY); /// /// Applies a radial vignette effect to an image. /// - /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext Vignette(this IImageProcessingContext source, Rectangle rectangle) - where TPixel : struct, IPixel - => Vignette(source, GraphicsOptions.Default, rectangle); + public static IImageProcessingContext Vignette(this IImageProcessingContext source, Rectangle rectangle) => + Vignette(source, GraphicsOptions.Default, rectangle); /// /// Applies a radial vignette effect to an image. /// - /// The pixel format. /// The image this method extends. /// The color to set as the vignette. /// The the x-radius. @@ -72,64 +65,82 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext Vignette(this IImageProcessingContext source, TPixel color, float radiusX, float radiusY, Rectangle rectangle) - where TPixel : struct, IPixel - => source.Vignette(GraphicsOptions.Default, color, radiusX, radiusY, rectangle); + public static IImageProcessingContext Vignette( + this IImageProcessingContext source, + Color color, + float radiusX, + float radiusY, + Rectangle rectangle) => + source.Vignette(GraphicsOptions.Default, color, radiusX, radiusY, rectangle); /// /// Applies a radial vignette effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting pixel blending. /// The to allow chaining of operations. - public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options) - where TPixel : struct, IPixel - => source.VignetteInternal(options, NamedColors.Black, ValueSize.PercentageOfWidth(.5f), ValueSize.PercentageOfHeight(.5f)); + public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options) => + source.VignetteInternal( + options, + Color.Black, + ValueSize.PercentageOfWidth(.5f), + ValueSize.PercentageOfHeight(.5f)); /// /// Applies a radial vignette effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting pixel blending. /// The color to set as the vignette. /// The to allow chaining of operations. - public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options, TPixel color) - where TPixel : struct, IPixel - => source.VignetteInternal(options, color, ValueSize.PercentageOfWidth(.5f), ValueSize.PercentageOfHeight(.5f)); + public static IImageProcessingContext Vignette( + this IImageProcessingContext source, + GraphicsOptions options, + Color color) => + source.VignetteInternal( + options, + color, + ValueSize.PercentageOfWidth(.5f), + ValueSize.PercentageOfHeight(.5f)); /// /// Applies a radial vignette effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting pixel blending. /// The the x-radius. /// The the y-radius. /// The to allow chaining of operations. - public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options, float radiusX, float radiusY) - where TPixel : struct, IPixel - => source.VignetteInternal(options, NamedColors.Black, radiusX, radiusY); + public static IImageProcessingContext Vignette( + this IImageProcessingContext source, + GraphicsOptions options, + float radiusX, + float radiusY) => + source.VignetteInternal(options, Color.Black, radiusX, radiusY); /// /// Applies a radial vignette effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting pixel blending. /// /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options, Rectangle rectangle) - where TPixel : struct, IPixel - => source.VignetteInternal(options, NamedColors.Black, ValueSize.PercentageOfWidth(.5f), ValueSize.PercentageOfHeight(.5f), rectangle); + public static IImageProcessingContext Vignette( + this IImageProcessingContext source, + GraphicsOptions options, + Rectangle rectangle) => + source.VignetteInternal( + options, + Color.Black, + ValueSize.PercentageOfWidth(.5f), + ValueSize.PercentageOfHeight(.5f), + rectangle); /// /// Applies a radial vignette effect to an image. /// - /// The pixel format. /// The image this method extends. /// The options effecting pixel blending. /// The color to set as the vignette. @@ -139,16 +150,30 @@ namespace SixLabors.ImageSharp.Processing /// The structure that specifies the portion of the image object to alter. /// /// The to allow chaining of operations. - public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float radiusX, float radiusY, Rectangle rectangle) - where TPixel : struct, IPixel - => source.VignetteInternal(options, color, radiusX, radiusY, rectangle); + public static IImageProcessingContext Vignette( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float radiusX, + float radiusY, + Rectangle rectangle) => + source.VignetteInternal(options, color, radiusX, radiusY, rectangle); - private static IImageProcessingContext VignetteInternal(this IImageProcessingContext source, GraphicsOptions options, TPixel color, ValueSize radiusX, ValueSize radiusY, Rectangle rectangle) - where TPixel : struct, IPixel - => source.ApplyProcessor(new VignetteProcessor(color, radiusX, radiusY, options), rectangle); + private static IImageProcessingContext VignetteInternal( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + ValueSize radiusX, + ValueSize radiusY, + Rectangle rectangle) => + source.ApplyProcessor(new VignetteProcessor(color, radiusX, radiusY, options), rectangle); - private static IImageProcessingContext VignetteInternal(this IImageProcessingContext source, GraphicsOptions options, TPixel color, ValueSize radiusX, ValueSize radiusY) - where TPixel : struct, IPixel - => source.ApplyProcessor(new VignetteProcessor(color, radiusX, radiusY, options)); + private static IImageProcessingContext VignetteInternal( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + ValueSize radiusX, + ValueSize radiusY) => + source.ApplyProcessor(new VignetteProcessor(color, radiusX, radiusY, options)); } } \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs index 15b82e022..29f69cdd5 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs @@ -20,14 +20,14 @@ namespace SixLabors.ImageSharp.Benchmarks public class Glow : BenchmarkBase { - private GlowProcessor bulk; + private GlowProcessor bulk; private GlowProcessorParallel parallel; [GlobalSetup] public void Setup() { - this.bulk = new GlowProcessor(NamedColors.Beige, 800 * .5f, GraphicsOptions.Default); + this.bulk = new GlowProcessor(Color.Beige, 800 * .5f, GraphicsOptions.Default); this.parallel = new GlowProcessorParallel(NamedColors.Beige) { Radius = 800 * .5f, }; } diff --git a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs b/tests/ImageSharp.Tests/Drawing/BeziersTests.cs index 69b2098dc..cc8f27f3a 100644 --- a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs +++ b/tests/ImageSharp.Tests/Drawing/BeziersTests.cs @@ -19,8 +19,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing string path = TestEnvironment.CreateOutputDirectory("Drawing", "BezierLine"); using (var image = new Image(500, 500)) { + image.Mutate(x => x.BackgroundColor(Color.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).DrawBeziers( + x => x.DrawBeziers( Rgba32.HotPink, 5, new SixLabors.Primitives.PointF[] @@ -56,8 +57,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { + image.Mutate(x => x.BackgroundColor(Color.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).DrawBeziers( + x => x.DrawBeziers( color, 10, new SixLabors.Primitives.PointF[] diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs index ee04d4388..54b04390e 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs @@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Tests // Apply a background color so we can see the translation. blend.Mutate(x => x.Transform(builder)); - blend.Mutate(x => x.BackgroundColor(NamedColors.HotPink)); + blend.Mutate(x => x.BackgroundColor(Color.HotPink)); // Lets center the matrix so we can tell whether any cut-off issues we may have belong to the drawing processor var position = new Point((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); diff --git a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs index 0d791fbd2..d2485f334 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs @@ -30,8 +30,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing new Vector2(10, 400)); var p = new Path(linerSegemnt, bazierSegment); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(Rgba32.HotPink, 5, p)); + + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Draw(Rgba32.HotPink, 5, p)); image.Save($"{path}/Simple.png"); Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); @@ -67,7 +68,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(color, 10, p)); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Draw(color, 10, p)); image.Save($"{path}/Opacity.png"); //shift background color towards forground color by the opacity amount diff --git a/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs index d827975c7..06961bec4 100644 --- a/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs @@ -31,7 +31,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); image.Save($"{path}/Simple.png"); Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); @@ -73,7 +74,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); image.Save($"{path}/SimpleVanishHole.png"); Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); @@ -113,7 +115,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); image.Save($"{path}/SimpleOverlapping.png"); Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); @@ -147,9 +150,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { - image.Mutate(x => x - .BackgroundColor(Rgba32.Blue) - .Draw(Pens.Dash(Rgba32.HotPink, 5), simplePath.Clip(hole1))); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Draw(Pens.Dash(Rgba32.HotPink, 5), simplePath.Clip(hole1))); image.Save($"{path}/Dashed.png"); } } @@ -171,7 +173,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Draw(color, 5, simplePath.Clip(hole1))); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Draw(color, 5, simplePath.Clip(hole1))); image.Save($"{path}/Opacity.png"); //shift background color towards forground color by the opacity amount diff --git a/tests/ImageSharp.Tests/Drawing/LineTests.cs b/tests/ImageSharp.Tests/Drawing/LineTests.cs index 43dec547e..1cc0fd1a4 100644 --- a/tests/ImageSharp.Tests/Drawing/LineTests.cs +++ b/tests/ImageSharp.Tests/Drawing/LineTests.cs @@ -19,8 +19,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); using (var image = new Image(500, 500)) { + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).DrawLines( + x => x.DrawLines( Rgba32.HotPink, 5, new Vector2(10, 10), @@ -43,8 +44,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); using (var image = new Image(500, 500)) { + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).DrawLines( + x => x.DrawLines( new GraphicsOptions(false), Rgba32.HotPink, 5, @@ -68,9 +70,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); using (var image = new Image(500, 500)) { - image.Mutate(x => x - .BackgroundColor(Rgba32.Blue) - .DrawLines(Pens.Dash(Rgba32.HotPink, 5), + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.DrawLines(Pens.Dash(Rgba32.HotPink, 5), new SixLabors.Primitives.PointF[] { new Vector2(10, 10), new Vector2(200, 150), @@ -86,9 +87,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); using (var image = new Image(500, 500)) { - image.Mutate(x => x - .BackgroundColor(Rgba32.Blue) - .DrawLines(Pens.Dot(Rgba32.HotPink, 5), + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.DrawLines(Pens.Dot(Rgba32.HotPink, 5), new SixLabors.Primitives.PointF[] { new Vector2(10, 10), new Vector2(200, 150), @@ -104,9 +104,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); using (var image = new Image(500, 500)) { - image.Mutate(x => x - .BackgroundColor(Rgba32.Blue) - .DrawLines(Pens.DashDot(Rgba32.HotPink, 5), + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.DrawLines(Pens.DashDot(Rgba32.HotPink, 5), new SixLabors.Primitives.PointF[] { new Vector2(10, 10), new Vector2(200, 150), @@ -122,9 +121,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); var image = new Image(500, 500); - image.Mutate(x => x - .BackgroundColor(Rgba32.Blue) - .DrawLines(Pens.DashDotDot(Rgba32.HotPink, 5), new SixLabors.Primitives.PointF[] { + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.DrawLines(Pens.DashDotDot(Rgba32.HotPink, 5), + new SixLabors.Primitives.PointF[] { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) @@ -141,8 +140,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing var image = new Image(500, 500); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).DrawLines( + x => x.DrawLines( color, 10, new Vector2(10, 10), @@ -169,8 +169,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing var image = new Image(500, 500); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).DrawLines( + x => x.DrawLines( Rgba32.HotPink, 10, new Vector2(10, 10), diff --git a/tests/ImageSharp.Tests/Drawing/PolygonTests.cs b/tests/ImageSharp.Tests/Drawing/PolygonTests.cs index 6ea9c647f..febb39c20 100644 --- a/tests/ImageSharp.Tests/Drawing/PolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/PolygonTests.cs @@ -20,8 +20,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (Image image = new Image(500, 500)) { + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).DrawPolygon( + x => x.DrawPolygon( Rgba32.HotPink, 5, new Vector2(10, 10), @@ -54,7 +55,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (Image image = new Image(500, 500)) { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).DrawPolygon(color, 10, simplePath)); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.DrawPolygon(color, 10, simplePath)); image.Save($"{path}/Opacity.png"); //shift background color towards forground color by the opacity amount @@ -79,8 +81,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (Image image = new Image(500, 500)) { + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).Draw(Rgba32.HotPink, 10, new Rectangle(10, 10, 190, 140))); + x => x.Draw(Rgba32.HotPink, 10, new Rectangle(10, 10, 190, 140))); image.Save($"{path}/Rectangle.png"); Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); diff --git a/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs b/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs index 23acc1a44..e8f53de01 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs @@ -24,15 +24,13 @@ namespace SixLabors.ImageSharp.Tests.Drawing new Vector2(300, 400) }; - TPixel blue = NamedColors.Blue; - TPixel hotPink = NamedColors.HotPink; + Color blue = Color.Blue; + Color hotPink = Color.HotPink; using (Image image = provider.GetImage()) { - - image.Mutate(x => x - .BackgroundColor(blue) - .Fill(hotPink, new Polygon(new CubicBezierLineSegment(simplePath)))); + image.Mutate(x => x.BackgroundColor(blue)); + image.Mutate(x => x.Fill(hotPink.ToPixel(), new Polygon(new CubicBezierLineSegment(simplePath)))); image.DebugSave(provider); image.CompareToReferenceOutput(provider); } @@ -55,9 +53,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = provider.GetImage() as Image) { - image.Mutate(x => x - .BackgroundColor(Rgba32.Blue) - .Fill(color, new Polygon(new CubicBezierLineSegment(simplePath)))); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + + image.Mutate(x => x.Fill(color, new Polygon(new CubicBezierLineSegment(simplePath)))); image.DebugSave(provider); image.CompareToReferenceOutput(provider); } diff --git a/tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs index 2c9628e84..0e997ad7e 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs @@ -31,7 +31,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing // var clipped = new Rectangle(10, 10, 100, 100).Clip(new Rectangle(20, 0, 20, 20)); using (var image = new Image(500, 500)) { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Fill(Rgba32.HotPink, clipped)); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Fill(Rgba32.HotPink, clipped)); image.Save($"{path}/Simple.png"); Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); @@ -59,7 +60,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Fill(Rgba32.HotPink, simplePath.Clip(hole1))); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Fill(Rgba32.HotPink, simplePath.Clip(hole1))); image.Save($"{path}/SimpleOverlapping.png"); Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); @@ -88,7 +90,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).Fill(color, simplePath.Clip(hole1))); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Fill(color, simplePath.Clip(hole1))); image.Save($"{path}/Opacity.png"); //shift background color towards forground color by the opacity amount diff --git a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs index 5660518eb..6a299aad7 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs @@ -68,8 +68,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).FillPolygon( + x => x.FillPolygon( new GraphicsOptions(false), Rgba32.HotPink, simplePath)); @@ -101,9 +102,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing { var brush = new ImageBrush(brushImage); - image.Mutate(x => x - .BackgroundColor(Rgba32.Blue) - .FillPolygon(brush, simplePath)); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.FillPolygon(brush, simplePath)); image.Save($"{path}/Image.png"); } } @@ -121,7 +121,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue).FillPolygon(color, simplePath)); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.FillPolygon(color, simplePath)); image.Save($"{path}/Opacity.png"); //shift background color towards forground color by the opacity amount @@ -140,8 +141,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(500, 500)) { + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).Fill( + x => x.Fill( Rgba32.HotPink, new SixLabors.Shapes.RectangularPolygon(10, 10, 190, 140))); image.Save($"{path}/Rectangle.png"); @@ -166,8 +168,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var image = new Image(100, 100)) { + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate( - x => x.BackgroundColor(Rgba32.Blue).Fill(Rgba32.HotPink, new RegularPolygon(50, 50, 3, 30))); + x => x.Fill(Rgba32.HotPink, new RegularPolygon(50, 50, 3, 30))); image.Save($"{path}/Triangle.png"); Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); @@ -186,9 +189,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing config.MaxDegreeOfParallelism = 1; using (var image = new Image(config, 100, 100)) { - image.Mutate(x => x - .BackgroundColor(Rgba32.Blue) - .Fill(Rgba32.HotPink, new RegularPolygon(50, 50, 7, 30, -(float)Math.PI))); + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); + image.Mutate(x => x.Fill(Rgba32.HotPink, + new RegularPolygon(50, 50, 7, 30, -(float)Math.PI))); image.Save($"{path}/Septagon.png"); } } @@ -202,8 +205,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing config.MaxDegreeOfParallelism = 1; using (var image = new Image(config, 100, 100)) { + image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); image.Mutate(x => x - .BackgroundColor(Rgba32.Blue) .Fill(Rgba32.HotPink, new EllipsePolygon(50, 50, 30, 50) .Rotate((float)(Math.PI / 3)))); image.Save($"{path}/ellipse.png"); diff --git a/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs b/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs index 7775de2d2..14758958f 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs @@ -14,41 +14,41 @@ namespace SixLabors.ImageSharp.Tests.Processing.Effects [Fact] public void BackgroundColor_amount_BackgroundColorProcessorDefaultsSet() { - this.operations.BackgroundColor(Rgba32.BlanchedAlmond); - var processor = this.Verify>(); + this.operations.BackgroundColor(Color.BlanchedAlmond); + var processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.GraphicsOptions); - Assert.Equal(Rgba32.BlanchedAlmond, processor.Color); + Assert.Equal(Color.BlanchedAlmond, processor.Color); } [Fact] public void BackgroundColor_amount_rect_BackgroundColorProcessorDefaultsSet() { - this.operations.BackgroundColor(Rgba32.BlanchedAlmond, this.rect); - var processor = this.Verify>(this.rect); + this.operations.BackgroundColor(Color.BlanchedAlmond, this.rect); + var processor = this.Verify(this.rect); Assert.Equal(GraphicsOptions.Default, processor.GraphicsOptions); - Assert.Equal(Rgba32.BlanchedAlmond, processor.Color); + Assert.Equal(Color.BlanchedAlmond, processor.Color); } [Fact] public void BackgroundColor_amount_options_BackgroundColorProcessorDefaultsSet() { - this.operations.BackgroundColor(this.options, Rgba32.BlanchedAlmond); - var processor = this.Verify>(); + this.operations.BackgroundColor(this.options, Color.BlanchedAlmond); + var processor = this.Verify(); Assert.Equal(this.options, processor.GraphicsOptions); - Assert.Equal(Rgba32.BlanchedAlmond, processor.Color); + Assert.Equal(Color.BlanchedAlmond, processor.Color); } [Fact] public void BackgroundColor_amount_rect_options_BackgroundColorProcessorDefaultsSet() { - this.operations.BackgroundColor(this.options, Rgba32.BlanchedAlmond, this.rect); - var processor = this.Verify>(this.rect); + this.operations.BackgroundColor(this.options, Color.BlanchedAlmond, this.rect); + var processor = this.Verify(this.rect); Assert.Equal(this.options, processor.GraphicsOptions); - Assert.Equal(Rgba32.BlanchedAlmond, processor.Color); + Assert.Equal(Color.BlanchedAlmond, processor.Color); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs b/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs index 899082e36..0301f5c03 100644 --- a/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs +++ b/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs @@ -18,10 +18,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays public void Glow_GlowProcessorWithDefaultValues() { this.operations.Glow(); - var p = this.Verify>(); + var p = this.Verify(); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); - Assert.Equal(Rgba32.Black, p.GlowColor); + Assert.Equal(Color.Black, p.GlowColor); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.Radius); } @@ -29,10 +29,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays public void Glow_Color_GlowProcessorWithDefaultValues() { this.operations.Glow(Rgba32.Aquamarine); - var p = this.Verify>(); + var p = this.Verify(); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); - Assert.Equal(Rgba32.Aquamarine, p.GlowColor); + Assert.Equal(Color.Aquamarine, p.GlowColor); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.Radius); } @@ -40,10 +40,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays public void Glow_Radux_GlowProcessorWithDefaultValues() { this.operations.Glow(3.5f); - var p = this.Verify>(); + var p = this.Verify(); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); - Assert.Equal(Rgba32.Black, p.GlowColor); + Assert.Equal(Color.Black, p.GlowColor); Assert.Equal(ValueSize.Absolute(3.5f), p.Radius); } @@ -52,10 +52,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays { var rect = new Rectangle(12, 123, 43, 65); this.operations.Glow(rect); - var p = this.Verify>(rect); + var p = this.Verify(rect); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); - Assert.Equal(Rgba32.Black, p.GlowColor); + Assert.Equal(Color.Black, p.GlowColor); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.Radius); } } diff --git a/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs b/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs index f47bffe26..2538aa137 100644 --- a/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs +++ b/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs @@ -16,10 +16,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays public void Vignette_VignetteProcessorWithDefaultValues() { this.operations.Vignette(); - var p = this.Verify>(); + var p = this.Verify(); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); - Assert.Equal(Rgba32.Black, p.VignetteColor); + Assert.Equal(Color.Black, p.VignetteColor); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.RadiusX); Assert.Equal(ValueSize.PercentageOfHeight(.5f), p.RadiusY); } @@ -27,11 +27,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays [Fact] public void Vignette_Color_VignetteProcessorWithDefaultValues() { - this.operations.Vignette(Rgba32.Aquamarine); - var p = this.Verify>(); + this.operations.Vignette(Color.Aquamarine); + var p = this.Verify(); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); - Assert.Equal(Rgba32.Aquamarine, p.VignetteColor); + Assert.Equal(Color.Aquamarine, p.VignetteColor); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.RadiusX); Assert.Equal(ValueSize.PercentageOfHeight(.5f), p.RadiusY); } @@ -40,10 +40,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays public void Vignette_Radux_VignetteProcessorWithDefaultValues() { this.operations.Vignette(3.5f, 12123f); - var p = this.Verify>(); + var p = this.Verify(); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); - Assert.Equal(Rgba32.Black, p.VignetteColor); + Assert.Equal(Color.Black, p.VignetteColor); Assert.Equal(ValueSize.Absolute(3.5f), p.RadiusX); Assert.Equal(ValueSize.Absolute(12123f), p.RadiusY); } @@ -53,10 +53,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Overlays { var rect = new Rectangle(12, 123, 43, 65); this.operations.Vignette(rect); - var p = this.Verify>(rect); + var p = this.Verify(rect); Assert.Equal(GraphicsOptions.Default, p.GraphicsOptions); - Assert.Equal(Rgba32.Black, p.VignetteColor); + Assert.Equal(Color.Black, p.VignetteColor); Assert.Equal(ValueSize.PercentageOfWidth(.5f), p.RadiusX); Assert.Equal(ValueSize.PercentageOfHeight(.5f), p.RadiusY); } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs index d7f77c956..dc6ff6f3e 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects public void FullImage(TestImageProvider provider) where TPixel : struct, IPixel { - provider.RunValidatingProcessorTest(x => x.BackgroundColor(NamedColors.HotPink)); + provider.RunValidatingProcessorTest(x => x.BackgroundColor(Color.HotPink)); } [Theory] @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects where TPixel : struct, IPixel { provider.RunRectangleConstrainedValidatingProcessorTest( - (x, rect) => x.BackgroundColor(NamedColors.HotPink, rect)); + (x, rect) => x.BackgroundColor(Color.HotPink, rect)); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs index 113c13b8a..27aeb4b05 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs @@ -13,11 +13,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays [GroupOutput("Overlays")] public class GlowTest : OverlayTestBase { - protected override void Apply(IImageProcessingContext ctx, T color) => ctx.Glow(color); + protected override void Apply(IImageProcessingContext ctx, Color color) => ctx.Glow(color); - protected override void Apply(IImageProcessingContext ctx, float radiusX, float radiusY) => + protected override void Apply(IImageProcessingContext ctx, float radiusX, float radiusY) => ctx.Glow(radiusX); - protected override void Apply(IImageProcessingContext ctx, Rectangle rect) => ctx.Glow(rect); + protected override void Apply(IImageProcessingContext ctx, Rectangle rect) => ctx.Glow(rect); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs b/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs index d2abcd731..788f7e1ad 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs @@ -27,8 +27,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays where TPixel : struct, IPixel { provider.Utility.TestGroupName = this.GetType().Name; - var f = (FieldInfo)typeof(NamedColors).GetMember(colorName)[0]; - TPixel color = (TPixel)f.GetValue(null); + var f = (FieldInfo)typeof(Color).GetMember(colorName)[0]; + Color color = (Color)f.GetValue(null); provider.RunValidatingProcessorTest(x => this.Apply(x, color), colorName, ValidatorComparer, appendPixelTypeToFileName: false); } @@ -58,13 +58,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays provider.RunRectangleConstrainedValidatingProcessorTest((x, rect) => this.Apply(x, rect)); } - protected abstract void Apply(IImageProcessingContext ctx, T color) - where T : struct, IPixel; + protected abstract void Apply(IImageProcessingContext ctx, Color color); - protected abstract void Apply(IImageProcessingContext ctx, float radiusX, float radiusY) - where T : struct, IPixel; + protected abstract void Apply(IImageProcessingContext ctx, float radiusX, float radiusY); - protected abstract void Apply(IImageProcessingContext ctx, Rectangle rect) - where T : struct, IPixel; + protected abstract void Apply(IImageProcessingContext ctx, Rectangle rect); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs index ad04a827d..9448feefe 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs @@ -9,11 +9,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays [GroupOutput("Overlays")] public class VignetteTest : OverlayTestBase { - protected override void Apply(IImageProcessingContext ctx, T color) => ctx.Vignette(color); + protected override void Apply(IImageProcessingContext ctx, Color color) => ctx.Vignette(color); - protected override void Apply(IImageProcessingContext ctx, float radiusX, float radiusY) => + protected override void Apply(IImageProcessingContext ctx, float radiusX, float radiusY) => ctx.Vignette(radiusX, radiusY); - protected override void Apply(IImageProcessingContext ctx, Rectangle rect) => ctx.Vignette(rect); + protected override void Apply(IImageProcessingContext ctx, Rectangle rect) => ctx.Vignette(rect); } } \ No newline at end of file From 390bda87fed5beb0ced15fde800599e842a91aa2 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 9 May 2019 23:49:58 +0200 Subject: [PATCH 154/223] made AutoOrientExtensions non-generic --- src/ImageSharp/Processing/AutoOrientExtensions.cs | 10 ++++------ .../Processing/Transforms/AutoOrientTests.cs | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ImageSharp/Processing/AutoOrientExtensions.cs b/src/ImageSharp/Processing/AutoOrientExtensions.cs index d065d4583..a831e2d9a 100644 --- a/src/ImageSharp/Processing/AutoOrientExtensions.cs +++ b/src/ImageSharp/Processing/AutoOrientExtensions.cs @@ -7,7 +7,7 @@ using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Processing { /// - /// Defines extensions that allow the application of auto-orientation operations to an + /// Defines extensions that allow the application of auto-orientation operations to an /// using Mutate/Clone. /// public static class AutoOrientExtensions @@ -15,11 +15,9 @@ namespace SixLabors.ImageSharp.Processing /// /// Adjusts an image so that its orientation is suitable for viewing. Adjustments are based on EXIF metadata embedded in the image. /// - /// The pixel format. /// The image to auto rotate. - /// The - public static IImageProcessingContext AutoOrient(this IImageProcessingContext source) - where TPixel : struct, IPixel - => source.ApplyProcessor(new AutoOrientProcessor()); + /// The to allow chaining of operations. + public static IImageProcessingContext AutoOrient(this IImageProcessingContext source) + => source.ApplyProcessor(new AutoOrientProcessor()); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs index bba4661db..0547b46e3 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public void AutoOrient_AutoOrientProcessor() { this.operations.AutoOrient(); - this.Verify>(); + this.Verify(); } } } \ No newline at end of file From f888f5d43653273f0ffde00128a18ca58283c7bd Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 10 May 2019 00:24:28 +0200 Subject: [PATCH 155/223] cleanup and document Color --- src/ImageSharp/Color/Color.Conversions.cs | 162 +++++++++++++++++++ src/ImageSharp/Color/Color.NamedColors.cs | 7 +- src/ImageSharp/Color/Color.WebSafePalette.cs | 9 +- src/ImageSharp/Color/Color.WernerPalette.cs | 7 +- src/ImageSharp/Color/Color.cs | 107 ++++++------ 5 files changed, 226 insertions(+), 66 deletions(-) create mode 100644 src/ImageSharp/Color/Color.Conversions.cs diff --git a/src/ImageSharp/Color/Color.Conversions.cs b/src/ImageSharp/Color/Color.Conversions.cs new file mode 100644 index 000000000..001aee5a4 --- /dev/null +++ b/src/ImageSharp/Color/Color.Conversions.cs @@ -0,0 +1,162 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Numerics; + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + /// + /// Contains constructors and implicit conversion methods. + /// + public readonly partial struct Color + { + /// + /// Initializes a new instance of the struct. + /// + /// The containing the color information. + public Color(Rgba64 pixel) + { + this.data = pixel; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The containing the color information. + public Color(Rgba32 pixel) + { + this.data = new Rgba64(pixel); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The containing the color information. + public Color(Argb32 pixel) + { + this.data = new Rgba64(pixel); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The containing the color information. + public Color(Bgra32 pixel) + { + this.data = new Rgba64(pixel); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The containing the color information. + public Color(Rgb24 pixel) + { + this.data = new Rgba64(pixel); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The containing the color information. + public Color(Bgr24 pixel) + { + this.data = new Rgba64(pixel); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The containing the color information. + public Color(Vector4 vector) + { + this.data = new Rgba64(vector); + } + + /// + /// Converts an to . + /// + /// The . + /// The . + public static implicit operator Color(Rgba64 source) => new Color(source); + + /// + /// Converts an to . + /// + /// The . + /// The . + public static implicit operator Color(Rgba32 source) => new Color(source); + + /// + /// Converts an to . + /// + /// The . + /// The . + public static implicit operator Color(Bgra32 source) => new Color(source); + + /// + /// Converts an to . + /// + /// The . + /// The . + public static implicit operator Color(Argb32 source) => new Color(source); + + /// + /// Converts an to . + /// + /// The . + /// The . + public static implicit operator Color(Rgb24 source) => new Color(source); + + /// + /// Converts an to . + /// + /// The . + /// The . + public static implicit operator Color(Bgr24 source) => new Color(source); + + /// + /// Converts a to . + /// + /// The . + /// The . + public static implicit operator Rgba64(Color color) => color.data; + + /// + /// Converts a to . + /// + /// The . + /// The . + public static implicit operator Rgba32(Color color) => color.data.ToRgba32(); + + /// + /// Converts a to . + /// + /// The . + /// The . + public static implicit operator Bgra32(Color color) => color.data.ToBgra32(); + + /// + /// Converts a to . + /// + /// The . + /// The . + public static implicit operator Argb32(Color color) => color.data.ToArgb32(); + + /// + /// Converts a to . + /// + /// The . + /// The . + public static implicit operator Rgb24(Color color) => color.data.ToRgb24(); + + /// + /// Converts a to . + /// + /// The . + /// The . + public static implicit operator Bgr24(Color color) => color.data.ToBgr24(); + } +} \ No newline at end of file diff --git a/src/ImageSharp/Color/Color.NamedColors.cs b/src/ImageSharp/Color/Color.NamedColors.cs index a712f85da..8811516c1 100644 --- a/src/ImageSharp/Color/Color.NamedColors.cs +++ b/src/ImageSharp/Color/Color.NamedColors.cs @@ -1,8 +1,11 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. namespace SixLabors.ImageSharp { + /// + /// Contains static named color values. + /// public readonly partial struct Color { /// diff --git a/src/ImageSharp/Color/Color.WebSafePalette.cs b/src/ImageSharp/Color/Color.WebSafePalette.cs index 13720ec49..506432ac2 100644 --- a/src/ImageSharp/Color/Color.WebSafePalette.cs +++ b/src/ImageSharp/Color/Color.WebSafePalette.cs @@ -1,16 +1,19 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. using System; namespace SixLabors.ImageSharp { + /// + /// Contains the definition of . + /// public partial struct Color { private static readonly Lazy WebSafePaletteLazy = new Lazy(CreateWebSafePalette, true); /// - /// Gets a collection of named, web safe, colors as defined in the CSS Color Module Level 4. + /// Gets a collection of named, web safe colors as defined in the CSS Color Module Level 4. /// public static ReadOnlySpan WebSafePalette => WebSafePaletteLazy.Value; diff --git a/src/ImageSharp/Color/Color.WernerPalette.cs b/src/ImageSharp/Color/Color.WernerPalette.cs index 45823479e..37980b15f 100644 --- a/src/ImageSharp/Color/Color.WernerPalette.cs +++ b/src/ImageSharp/Color/Color.WernerPalette.cs @@ -1,10 +1,13 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. using System; namespace SixLabors.ImageSharp { + /// + /// Contains the definition of . + /// public partial struct Color { private static readonly Lazy WernerPaletteLazy = new Lazy(CreateWernerPalette, true); diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index 021cea415..94b5dde2e 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -11,81 +11,58 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { + /// + /// Represents a color value that is convertible to all implementations. + /// public readonly partial struct Color : IEquatable { private readonly Rgba64 data; - public Color(Rgba64 pixel) - { - this.data = pixel; - } - - public Color(Rgba32 pixel) - { - this.data = new Rgba64(pixel); - } - - public Color(Argb32 pixel) - { - this.data = new Rgba64(pixel); - } - - public Color(Bgra32 pixel) - { - this.data = new Rgba64(pixel); - } - - public Color(Rgb24 pixel) - { - this.data = new Rgba64(pixel); - } - - public Color(Bgr24 pixel) - { - this.data = new Rgba64(pixel); - } - - public Color(Vector4 vector) - { - this.data = new Rgba64(vector); - } - - public static implicit operator Color(Rgba64 source) => new Color(source); - - public static implicit operator Color(Rgba32 source) => new Color(source); - - public static implicit operator Color(Bgra32 source) => new Color(source); - - public static implicit operator Color(Argb32 source) => new Color(source); - - public static implicit operator Color(Rgb24 source) => new Color(source); - - public static implicit operator Color(Bgr24 source) => new Color(source); - - public static implicit operator Rgba64(Color color) => color.data; - - public static implicit operator Rgba32(Color color) => color.data.ToRgba32(); - - public static implicit operator Bgra32(Color color) => color.data.ToBgra32(); - - public static implicit operator Argb32(Color color) => color.data.ToArgb32(); - - public static implicit operator Rgb24(Color color) => color.data.ToRgb24(); - - public static implicit operator Bgr24(Color color) => color.data.ToBgr24(); - + /// + /// Checks whether two structures are equal. + /// + /// The left hand operand. + /// The right hand operand. + /// + /// True if the parameter is equal to the parameter; + /// otherwise, false. + /// public static bool operator ==(Color left, Color right) { return left.Equals(right); } + /// + /// Checks whether two structures are equal. + /// + /// The left hand operand. + /// The right hand operand. + /// + /// True if the parameter is not equal to the parameter; + /// otherwise, false. + /// public static bool operator !=(Color left, Color right) { return !left.Equals(right); } + /// + /// Creates a from RGBA bytes. + /// + /// The red component (0-255). + /// The green component (0-255). + /// The blue component (0-255). + /// The alpha component (0-255). + /// The . public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(new Rgba32(r, g, b, a)); + /// + /// Creates a from RGB bytes. + /// + /// The red component (0-255). + /// The green component (0-255). + /// The blue component (0-255). + /// The . public static Color FromRgb(byte r, byte g, byte b) => FromRgba(r, g, b, 255); /// @@ -120,6 +97,12 @@ namespace SixLabors.ImageSharp /// public override string ToString() => this.ToHex(); + /// + /// Converts the color instance to an + /// implementation defined by . + /// + /// The pixel type to convert to. + /// The pixel value. public TPixel ToPixel() where TPixel : struct, IPixel { @@ -128,17 +111,20 @@ namespace SixLabors.ImageSharp return pixel; } + /// public bool Equals(Color other) { return this.data.PackedValue == other.data.PackedValue; } + /// public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } + return obj is Color other && this.Equals(other); } @@ -148,6 +134,9 @@ namespace SixLabors.ImageSharp return this.data.PackedValue.GetHashCode(); } + /// + /// Bulk convert a span of to a span of a specified pixel type. + /// internal static void ToPixel( Configuration configuration, ReadOnlySpan source, From 24de58ab096a57ddc2840be4588b56bfdfebbe9b Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 10 May 2019 00:26:34 +0200 Subject: [PATCH 156/223] cleanup --- .../Processors/Binarization/BinaryOrderedDitherProcessor.cs | 3 +++ .../Processors/Binarization/BinaryThresholdProcessor.cs | 4 ++-- .../Processors/Overlays/BackgroundColorProcessor.cs | 2 +- .../Processing/Processors/Overlays/GlowProcessor.cs | 1 - 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs index 99c57171c..6cf1a9526 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs @@ -8,6 +8,9 @@ using SixLabors.ImageSharp.Processing.Processors.Dithering; namespace SixLabors.ImageSharp.Processing.Processors.Binarization { + /// + /// Defines a binary threshold filtering using ordered dithering. + /// public class BinaryOrderedDitherProcessor : IImageProcessor { /// diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs index 50086936c..83701aa8a 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs @@ -41,12 +41,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization public float Threshold { get; } /// - /// Gets or sets the color to use for pixels that are above the threshold. + /// Gets the color to use for pixels that are above the threshold. /// public Color UpperColor { get; } /// - /// Gets or sets the color to use for pixels that fall below the threshold. + /// Gets the color to use for pixels that fall below the threshold. /// public Color LowerColor { get; } diff --git a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs index 0dd0c4118..62848172a 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs @@ -6,7 +6,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Overlays { /// - /// Defines a processing operation to replace the background color of an . + /// Defines a processing operation to replace the background color of an . /// public sealed class BackgroundColorProcessor : IImageProcessor { diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs index 4927a0ed7..dcdddb217 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs @@ -20,7 +20,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays { } - /// /// Initializes a new instance of the class. /// From e0afde9967924a0d54a98479ea99f42c224b32a8 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Fri, 10 May 2019 20:28:46 +0200 Subject: [PATCH 157/223] Switched back to the default reference decoder --- tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index a56cee47d..f3d6e0fa8 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -153,13 +153,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] public void Encode_8Bit_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) - where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false, referenceDecoder: new MagickReferenceDecoder()); + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); [Theory] [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] public void Encode_8Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) - where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true, referenceDecoder: new MagickReferenceDecoder()); + where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); [Theory] [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] @@ -167,7 +167,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp public void Encode_PreservesAlpha(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); - private static void TestBmpEncoderCore(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel, bool supportTransparency = true, IImageDecoder referenceDecoder = null) + private static void TestBmpEncoderCore(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel, bool supportTransparency = true) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) @@ -181,7 +181,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp var encoder = new BmpEncoder { BitsPerPixel = bitsPerPixel, SupportTransparency = supportTransparency }; // Does DebugSave & load reference CompareToReferenceInput(): - image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder, referenceDecoder: referenceDecoder); + image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder); } } } From 5ae27735e527359a7d7ba9470bab9669efa5694b Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 10 May 2019 22:59:43 +0200 Subject: [PATCH 158/223] Made PaletteQuantizer non-generic all the way --- src/ImageSharp/Color/Color.WebSafePalette.cs | 2 +- src/ImageSharp/Color/Color.WernerPalette.cs | 2 +- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 11 +- .../Processing/DiffuseExtensions.cs | 4 +- src/ImageSharp/Processing/DitherExtensions.cs | 4 +- .../ErrorDiffusionPaletteProcessor.cs | 2 +- .../OrderedDitherPaletteProcessor.cs | 2 +- .../Dithering/PaletteDitherProcessor.cs | 10 +- .../PaletteDitherProcessor{TPixel}.cs | 51 ++++---- .../Processors/Overlays/GlowProcessor.cs | 2 +- ...e{TPixel}.cs => FrameQuantizer{TPixel}.cs} | 43 +++++-- .../OctreeFrameQuantizer{TPixel}.cs | 6 +- .../PaletteFrameQuantizer{TPixel}.cs | 13 ++- .../Quantization/PaletteQuantizer.cs | 59 +++++----- .../Quantization/PaletteQuantizer{TPixel}.cs | 110 ------------------ .../Quantization/WebSafePaletteQuantizer.cs | 13 +-- .../Quantization/WernerPaletteQuantizer.cs | 13 +-- .../Quantization/WuFrameQuantizer{TPixel}.cs | 6 +- .../Processing/Dithering/DitherTest.cs | 2 +- .../Quantization/PaletteQuantizerTests.cs | 28 ++--- 20 files changed, 143 insertions(+), 240 deletions(-) rename src/ImageSharp/Processing/Processors/Quantization/{FrameQuantizerBase{TPixel}.cs => FrameQuantizer{TPixel}.cs} (81%) delete mode 100644 src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs diff --git a/src/ImageSharp/Color/Color.WebSafePalette.cs b/src/ImageSharp/Color/Color.WebSafePalette.cs index 506432ac2..8e5fb2a55 100644 --- a/src/ImageSharp/Color/Color.WebSafePalette.cs +++ b/src/ImageSharp/Color/Color.WebSafePalette.cs @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp /// /// Gets a collection of named, web safe colors as defined in the CSS Color Module Level 4. /// - public static ReadOnlySpan WebSafePalette => WebSafePaletteLazy.Value; + public static ReadOnlyMemory WebSafePalette => WebSafePaletteLazy.Value; private static Color[] CreateWebSafePalette() => new[] { diff --git a/src/ImageSharp/Color/Color.WernerPalette.cs b/src/ImageSharp/Color/Color.WernerPalette.cs index 37980b15f..768fe065c 100644 --- a/src/ImageSharp/Color/Color.WernerPalette.cs +++ b/src/ImageSharp/Color/Color.WernerPalette.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp /// Gets a collection of colors as defined in the original second edition of Werner’s Nomenclature of Colours 1821. /// The hex codes were collected and defined by Nicholas Rougeux . /// - public static ReadOnlySpan WernerPalette => WernerPaletteLazy.Value; + public static ReadOnlyMemory WernerPalette => WernerPaletteLazy.Value; private static Color[] CreateWernerPalette() => new[] { diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 12a515cca..2770790a2 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -144,8 +144,6 @@ namespace SixLabors.ImageSharp.Formats.Gif private void EncodeGlobal(Image image, QuantizedFrame quantized, int transparencyIndex, Stream stream) where TPixel : struct, IPixel { - var palleteQuantizer = new PaletteQuantizer(quantized.Palette, this.quantizer.Diffuser); - for (int i = 0; i < image.Frames.Count; i++) { ImageFrame frame = image.Frames[i]; @@ -160,10 +158,13 @@ namespace SixLabors.ImageSharp.Formats.Gif } else { - using (IFrameQuantizer palleteFrameQuantizer = palleteQuantizer.CreateFrameQuantizer(image.GetConfiguration())) - using (QuantizedFrame paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame)) + using (IFrameQuantizer palleteFrameQuantizer = + new PaletteFrameQuantizer(this.quantizer.Diffuser, quantized.Palette)) { - this.WriteImageData(paletteQuantized, stream); + using (QuantizedFrame paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame)) + { + this.WriteImageData(paletteQuantized, stream); + } } } } diff --git a/src/ImageSharp/Processing/DiffuseExtensions.cs b/src/ImageSharp/Processing/DiffuseExtensions.cs index cd714c3da..f9a1bdde0 100644 --- a/src/ImageSharp/Processing/DiffuseExtensions.cs +++ b/src/ImageSharp/Processing/DiffuseExtensions.cs @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Dithering this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, - ReadOnlySpan palette) => + ReadOnlyMemory palette) => source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold, palette)); /// @@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Processing.Dithering this IImageProcessingContext source, IErrorDiffuser diffuser, float threshold, - ReadOnlySpan palette, + ReadOnlyMemory palette, Rectangle rectangle) => source.ApplyProcessor(new ErrorDiffusionPaletteProcessor(diffuser, threshold, palette), rectangle); } diff --git a/src/ImageSharp/Processing/DitherExtensions.cs b/src/ImageSharp/Processing/DitherExtensions.cs index 55794aec2..f83a9e9e8 100644 --- a/src/ImageSharp/Processing/DitherExtensions.cs +++ b/src/ImageSharp/Processing/DitherExtensions.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing public static IImageProcessingContext Dither( this IImageProcessingContext source, IOrderedDither dither, - ReadOnlySpan palette) => + ReadOnlyMemory palette) => source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither, palette)); /// @@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Processing public static IImageProcessingContext Dither( this IImageProcessingContext source, IOrderedDither dither, - ReadOnlySpan palette, + ReadOnlyMemory palette, Rectangle rectangle) => source.ApplyProcessor(new OrderedDitherPaletteProcessor(dither, palette), rectangle); } diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs index 5436a7733..e0b79c2b2 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// The error diffuser /// The threshold to split the image. Must be between 0 and 1. /// The palette to select substitute colors from. - public ErrorDiffusionPaletteProcessor(IErrorDiffuser diffuser, float threshold, ReadOnlySpan palette) + public ErrorDiffusionPaletteProcessor(IErrorDiffuser diffuser, float threshold, ReadOnlyMemory palette) : base(palette) { Guard.NotNull(diffuser, nameof(diffuser)); diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs index ba7c1e998..ac6554d4c 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// /// The ordered ditherer. /// The palette to select substitute colors from. - public OrderedDitherPaletteProcessor(IOrderedDither dither, ReadOnlySpan palette) + public OrderedDitherPaletteProcessor(IOrderedDither dither, ReadOnlyMemory palette) : base(palette) => this.Dither = dither ?? throw new ArgumentNullException(nameof(dither)); /// diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs index 904d02634..de798b64b 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs @@ -12,23 +12,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// public abstract class PaletteDitherProcessor : IImageProcessor { - private readonly Color[] palette; - /// /// Initializes a new instance of the class. /// /// The palette to select substitute colors from. - protected PaletteDitherProcessor(ReadOnlySpan palette) + protected PaletteDitherProcessor(ReadOnlyMemory palette) { - // This shouldn't be a perf issue: - // these arrays are small, and created with low frequency. - this.palette = palette.ToArray(); + this.Palette = palette; } /// /// Gets the palette to select substitute colors from. /// - public ReadOnlySpan Palette => this.palette; + public ReadOnlyMemory Palette { get; } /// public abstract IImageProcessor CreatePixelSpecificProcessor() diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs index 334eab833..205b589b1 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs @@ -20,13 +20,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering { private readonly Dictionary> cache = new Dictionary>(); + private TPixel[] palette; + /// /// The vector representation of the image palette. /// private Vector4[] paletteVector; - private TPixel[] palette; - /// /// Initializes a new instance of the class. /// @@ -37,6 +37,33 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering protected PaletteDitherProcessor Definition { get; } + protected override void BeforeFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) + { + base.BeforeFrameApply(source, sourceRectangle, configuration); + + // Lazy init palette: + if (this.palette is null) + { + ReadOnlySpan sourcePalette = this.Definition.Palette.Span; + this.palette = new TPixel[sourcePalette.Length]; + Color.ToPixel(configuration, sourcePalette, this.palette); + } + + // Lazy init paletteVector: + if (this.paletteVector is null) + { + this.paletteVector = new Vector4[this.palette.Length]; + PixelOperations.Instance.ToVector4( + configuration, + (ReadOnlySpan)this.palette, + (Span)this.paletteVector, + PixelConversionModifiers.Scale); + } + } + /// /// Returns the two closest colors from the palette calculated via Euclidean distance in the Rgba space. /// @@ -88,25 +115,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering return pair; } - - protected override void BeforeFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - base.BeforeFrameApply(source, sourceRectangle, configuration); - - // Lazy init palette: - if (this.palette is null) - { - ReadOnlySpan sourcePalette = this.Definition.Palette; - this.palette = new TPixel[sourcePalette.Length]; - Color.ToPixel(configuration, sourcePalette, this.palette); - } - - // Lazy init paletteVector: - if (this.paletteVector is null) - { - this.paletteVector = new Vector4[this.palette.Length]; - PixelOperations.Instance.ToVector4(configuration, (ReadOnlySpan)this.palette, (Span)this.paletteVector, PixelConversionModifiers.Scale); - } - } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs index dcdddb217..255be5ed5 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays } /// - /// Gets the options effecting blending and composition + /// Gets the options effecting blending and composition. /// public GraphicsOptions GraphicsOptions { get; } diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs similarity index 81% rename from src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs rename to src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs index f23343f6d..6d8136513 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The base class for all implementations /// /// The pixel format. - public abstract class FrameQuantizerBase : IFrameQuantizer + public abstract class FrameQuantizer : IFrameQuantizer where TPixel : struct, IPixel { /// @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization private Vector4[] paletteVector; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The quantizer /// @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// only call the method. /// If two passes are required, the code will also call . /// - protected FrameQuantizerBase(IQuantizer quantizer, bool singlePass) + protected FrameQuantizer(IQuantizer quantizer, bool singlePass) { Guard.NotNull(quantizer, nameof(quantizer)); @@ -52,6 +52,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.Dither = this.Diffuser != null; this.singlePass = singlePass; } + + /// + /// Initializes a new instance of the class. + /// + /// The diffuser + /// + /// If true, the quantization process only needs to loop through the source pixels once + /// + /// + /// If you construct this class with a true for , then the code will + /// only call the method. + /// If two passes are required, the code will also call . + /// + protected FrameQuantizer(IErrorDiffuser diffuser, bool singlePass) + { + this.Diffuser = diffuser; + this.Dither = this.Diffuser != null; + this.singlePass = singlePass; + } /// public bool Dither { get; } @@ -77,22 +96,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } // Collect the palette. Required before the second pass runs. - TPixel[] palette = this.GetPalette(); + ReadOnlyMemory palette = this.GetPalette(); this.paletteVector = new Vector4[palette.Length]; - PixelOperations.Instance.ToVector4(image.Configuration, (ReadOnlySpan)palette, (Span)this.paletteVector, PixelConversionModifiers.Scale); - var quantizedFrame = new QuantizedFrame(image.MemoryAllocator, width, height, palette); + PixelOperations.Instance.ToVector4(image.Configuration, palette.Span, (Span)this.paletteVector, PixelConversionModifiers.Scale); + + // TODO: Pass ReadOnlyMemory instead of array! + var quantizedFrame = new QuantizedFrame( + image.MemoryAllocator, + width, + height, + palette.Span.ToArray()); if (this.Dither) { // We clone the image as we don't want to alter the original via dithering. using (ImageFrame clone = image.Clone()) { - this.SecondPass(clone, quantizedFrame.GetPixelSpan(), palette, width, height); + this.SecondPass(clone, quantizedFrame.GetPixelSpan(), palette.Span, width, height); } } else { - this.SecondPass(image, quantizedFrame.GetPixelSpan(), palette, width, height); + this.SecondPass(image, quantizedFrame.GetPixelSpan(), palette.Span, width, height); } return quantizedFrame; @@ -134,7 +159,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// /// - protected abstract TPixel[] GetPalette(); + protected abstract ReadOnlyMemory GetPalette(); /// /// Returns the index of the first instance of the transparent color in the palette. diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs index dd56375f6..85a4d2029 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// /// The pixel format. - internal sealed class OctreeFrameQuantizer : FrameQuantizerBase + internal sealed class OctreeFrameQuantizer : FrameQuantizer where TPixel : struct, IPixel { /// @@ -136,10 +136,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } } - internal TPixel[] AotGetPalette() => this.GetPalette(); + internal ReadOnlyMemory AotGetPalette() => this.GetPalette(); /// - protected override TPixel[] GetPalette() => this.octree.Palletize(this.colors); + protected override ReadOnlyMemory GetPalette() => this.octree.Palletize(this.colors); /// /// Process the pixel in the second pass of the algorithm. diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs index f8a19f8c4..265c343e6 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteFrameQuantizer{TPixel}.cs @@ -6,6 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Dithering; namespace SixLabors.ImageSharp.Processing.Processors.Quantization { @@ -14,21 +15,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// /// The pixel format. - internal sealed class PaletteFrameQuantizer : FrameQuantizerBase + internal sealed class PaletteFrameQuantizer : FrameQuantizer where TPixel : struct, IPixel { /// /// The reduced image palette. /// - private readonly TPixel[] palette; + private readonly ReadOnlyMemory palette; /// /// Initializes a new instance of the class. /// - /// The palette quantizer. + /// The palette quantizer. /// An array of all colors in the palette. - public PaletteFrameQuantizer(IQuantizer quantizer, TPixel[] colors) - : base(quantizer, true) => this.palette = colors; + public PaletteFrameQuantizer(IErrorDiffuser diffuser, ReadOnlyMemory colors) + : base(diffuser, true) => this.palette = colors; /// protected override void SecondPass( @@ -85,7 +86,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected override TPixel[] GetPalette() => this.palette; + protected override ReadOnlyMemory GetPalette() => this.palette; /// /// Process the pixel in the second pass of the algorithm diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs index 6b2be3d03..ba434a4b2 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Dithering; @@ -14,61 +15,65 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// By default the quantizer uses dithering. /// /// - public abstract class PaletteQuantizer : IQuantizer + public class PaletteQuantizer : IQuantizer { /// /// Initializes a new instance of the class. /// - protected PaletteQuantizer() - : this(true) + /// The palette. + public PaletteQuantizer(ReadOnlyMemory palette) + : this(palette, true) { } /// /// Initializes a new instance of the class. /// + /// The palette. /// Whether to apply dithering to the output image - protected PaletteQuantizer(bool dither) - : this(GetDiffuser(dither)) + public PaletteQuantizer(ReadOnlyMemory palette, bool dither) + : this(palette, GetDiffuser(dither)) { } /// /// Initializes a new instance of the class. /// + /// The palette. /// The error diffusion algorithm, if any, to apply to the output image - protected PaletteQuantizer(IErrorDiffuser diffuser) => this.Diffuser = diffuser; + public PaletteQuantizer(ReadOnlyMemory palette, IErrorDiffuser diffuser) + { + this.Palette = palette; + this.Diffuser = diffuser; + } /// public IErrorDiffuser Diffuser { get; } - /// - public abstract IFrameQuantizer CreateFrameQuantizer(Configuration configuration) - where TPixel : struct, IPixel; - - /// - public abstract IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) - where TPixel : struct, IPixel; - /// - /// Creates the generic frame quantizer. + /// Gets the palette. /// - /// The pixel format. - /// The to configure internal operations. - /// The color palette. - /// The maximum number of colors to hold in the color palette. - /// The - protected IFrameQuantizer CreateFrameQuantizer(Configuration configuration, TPixel[] palette, int maxColors) + public ReadOnlyMemory Palette { get; } + + /// + public IFrameQuantizer CreateFrameQuantizer(Configuration configuration) where TPixel : struct, IPixel { - int max = Math.Min(QuantizerConstants.MaxColors, Math.Min(maxColors, palette.Length)); + TPixel[] palette = new TPixel[this.Palette.Length]; + Color.ToPixel(configuration, this.Palette.Span, palette.AsSpan()); + return new PaletteFrameQuantizer(this.Diffuser, palette); + } - if (max != palette.Length) - { - return new PaletteFrameQuantizer(this, palette.AsSpan(0, max).ToArray()); - } + /// + public IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) + where TPixel : struct, IPixel + { + maxColors = maxColors.Clamp(QuantizerConstants.MinColors, QuantizerConstants.MaxColors); + int max = Math.Min(maxColors, this.Palette.Length); - return new PaletteFrameQuantizer(this, palette); + TPixel[] palette = new TPixel[max]; + Color.ToPixel(configuration, this.Palette.Span.Slice(0, max), palette.AsSpan()); + return new PaletteFrameQuantizer(this.Diffuser, palette); } private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null; diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs deleted file mode 100644 index a350adfc0..000000000 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors.Dithering; - -namespace SixLabors.ImageSharp.Processing.Processors.Quantization -{ - /// - /// A generic palette quantizer. - /// - /// The pixel format. - public class PaletteQuantizer : IQuantizer - where TPixel : struct, IPixel - { - /// - /// Initializes a new instance of the class. - /// - /// The color palette to use. - public PaletteQuantizer(TPixel[] palette) - : this(palette, true) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The color palette to use. - /// Whether to apply dithering to the output image - public PaletteQuantizer(TPixel[] palette, bool dither) - : this(palette, GetDiffuser(dither)) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The color palette to use. - /// The error diffusion algorithm, if any, to apply to the output image - public PaletteQuantizer(TPixel[] palette, IErrorDiffuser diffuser) - { - Guard.MustBeBetweenOrEqualTo(palette.Length, QuantizerConstants.MinColors, QuantizerConstants.MaxColors, nameof(palette)); - this.Palette = palette; - this.Diffuser = diffuser; - } - - /// - public IErrorDiffuser Diffuser { get; } - - /// - /// Gets the palette. - /// - public TPixel[] Palette { get; } - - /// - /// Creates the generic frame quantizer. - /// - /// The to configure internal operations. - /// The . - public IFrameQuantizer CreateFrameQuantizer(Configuration configuration) - => ((IQuantizer)this).CreateFrameQuantizer(configuration); - - /// - /// Creates the generic frame quantizer. - /// - /// The to configure internal operations. - /// The maximum number of colors to hold in the color palette. - /// The . - public IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) - => ((IQuantizer)this).CreateFrameQuantizer(configuration, maxColors); - - /// - IFrameQuantizer IQuantizer.CreateFrameQuantizer(Configuration configuration) - { - if (!typeof(TPixel).Equals(typeof(TPixel1))) - { - throw new InvalidOperationException("Generic method type must be the same as class type."); - } - - TPixel[] paletteRef = this.Palette; - return new PaletteFrameQuantizer(this, Unsafe.As(ref paletteRef)); - } - - /// - IFrameQuantizer IQuantizer.CreateFrameQuantizer(Configuration configuration, int maxColors) - { - if (!typeof(TPixel).Equals(typeof(TPixel1))) - { - throw new InvalidOperationException("Generic method type must be the same as class type."); - } - - TPixel[] paletteRef = this.Palette; - TPixel1[] castPalette = Unsafe.As(ref paletteRef); - - maxColors = maxColors.Clamp(QuantizerConstants.MinColors, QuantizerConstants.MaxColors); - int max = Math.Min(maxColors, castPalette.Length); - - if (max != castPalette.Length) - { - return new PaletteFrameQuantizer(this, castPalette.AsSpan(0, max).ToArray()); - } - - return new PaletteFrameQuantizer(this, castPalette); - } - - private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null; - } -} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/WebSafePaletteQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/WebSafePaletteQuantizer.cs index 93630a916..3f6dfde28 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WebSafePaletteQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WebSafePaletteQuantizer.cs @@ -15,6 +15,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// Initializes a new instance of the class. /// public WebSafePaletteQuantizer() + : this(true) { } @@ -23,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Whether to apply dithering to the output image public WebSafePaletteQuantizer(bool dither) - : base(dither) + : base(Color.WebSafePalette, dither) { } @@ -32,16 +33,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// The error diffusion algorithm, if any, to apply to the output image public WebSafePaletteQuantizer(IErrorDiffuser diffuser) - : base(diffuser) + : base(Color.WebSafePalette, diffuser) { } - - /// - public override IFrameQuantizer CreateFrameQuantizer(Configuration configuration) - => this.CreateFrameQuantizer(configuration, NamedColors.WebSafePalette.Length); - - /// - public override IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) - => this.CreateFrameQuantizer(configuration, NamedColors.WebSafePalette, maxColors); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/WernerPaletteQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/WernerPaletteQuantizer.cs index 2ff9f5090..d659ecabf 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WernerPaletteQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WernerPaletteQuantizer.cs @@ -16,6 +16,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// Initializes a new instance of the class. /// public WernerPaletteQuantizer() + : this(true) { } @@ -24,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Whether to apply dithering to the output image public WernerPaletteQuantizer(bool dither) - : base(dither) + : base(Color.WernerPalette, dither) { } @@ -33,16 +34,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// The error diffusion algorithm, if any, to apply to the output image public WernerPaletteQuantizer(IErrorDiffuser diffuser) - : base(diffuser) + : base(Color.WernerPalette, diffuser) { } - - /// - public override IFrameQuantizer CreateFrameQuantizer(Configuration configuration) - => this.CreateFrameQuantizer(configuration, NamedColors.WernerPalette.Length); - - /// - public override IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) - => this.CreateFrameQuantizer(configuration, NamedColors.WernerPalette, maxColors); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs index 1f1513adf..95918f564 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// /// The pixel format. - internal sealed class WuFrameQuantizer : FrameQuantizerBase + internal sealed class WuFrameQuantizer : FrameQuantizer where TPixel : struct, IPixel { // The following two variables determine the amount of bits to preserve when calculating the histogram. @@ -171,10 +171,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.tag?.Dispose(); } - internal TPixel[] AotGetPalette() => this.GetPalette(); + internal ReadOnlyMemory AotGetPalette() => this.GetPalette(); /// - protected override TPixel[] GetPalette() + protected override ReadOnlyMemory GetPalette() { if (this.palette is null) { diff --git a/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs b/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs index 59dcde2a6..d91688cd2 100644 --- a/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs +++ b/tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization this.operations.Dither(this.orderedDither); OrderedDitherPaletteProcessor p = this.Verify(); Assert.Equal(this.orderedDither, p.Dither); - Assert.Equal(Color.WebSafePalette.ToArray(), p.Palette); + Assert.Equal(Color.WebSafePalette, p.Palette); } [Fact] diff --git a/tests/ImageSharp.Tests/Processing/Processors/Quantization/PaletteQuantizerTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Quantization/PaletteQuantizerTests.cs index a4e6edd53..05ce70047 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Quantization/PaletteQuantizerTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Quantization/PaletteQuantizerTests.cs @@ -11,21 +11,21 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Quantization { public class PaletteQuantizerTests { - private static readonly Rgba32[] Rgb = new Rgba32[] { Rgba32.Red, Rgba32.Green, Rgba32.Blue }; + private static readonly Color[] Rgb = new Color[] { Rgba32.Red, Rgba32.Green, Rgba32.Blue }; [Fact] public void PaletteQuantizerConstructor() { - var quantizer = new PaletteQuantizer(Rgb); + var quantizer = new PaletteQuantizer(Rgb); Assert.Equal(Rgb, quantizer.Palette); Assert.Equal(KnownDiffusers.FloydSteinberg, quantizer.Diffuser); - quantizer = new PaletteQuantizer(Rgb, false); + quantizer = new PaletteQuantizer(Rgb, false); Assert.Equal(Rgb, quantizer.Palette); Assert.Null(quantizer.Diffuser); - quantizer = new PaletteQuantizer(Rgb, KnownDiffusers.Atkinson); + quantizer = new PaletteQuantizer(Rgb, KnownDiffusers.Atkinson); Assert.Equal(Rgb, quantizer.Palette); Assert.Equal(KnownDiffusers.Atkinson, quantizer.Diffuser); } @@ -33,35 +33,27 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Quantization [Fact] public void PaletteQuantizerCanCreateFrameQuantizer() { - var quantizer = new PaletteQuantizer(Rgb); - IFrameQuantizer frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default); + var quantizer = new PaletteQuantizer(Rgb); + IFrameQuantizer frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default); Assert.NotNull(frameQuantizer); Assert.True(frameQuantizer.Dither); Assert.Equal(KnownDiffusers.FloydSteinberg, frameQuantizer.Diffuser); - quantizer = new PaletteQuantizer(Rgb, false); - frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default); + quantizer = new PaletteQuantizer(Rgb, false); + frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default); Assert.NotNull(frameQuantizer); Assert.False(frameQuantizer.Dither); Assert.Null(frameQuantizer.Diffuser); - quantizer = new PaletteQuantizer(Rgb, KnownDiffusers.Atkinson); - frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default); + quantizer = new PaletteQuantizer(Rgb, KnownDiffusers.Atkinson); + frameQuantizer = quantizer.CreateFrameQuantizer(Configuration.Default); Assert.NotNull(frameQuantizer); Assert.True(frameQuantizer.Dither); Assert.Equal(KnownDiffusers.Atkinson, frameQuantizer.Diffuser); } - [Fact] - public void PaletteQuantizerThrowsOnInvalidGenericMethodCall() - { - var quantizer = new PaletteQuantizer(Rgb); - - Assert.Throws(() => ((IQuantizer)quantizer).CreateFrameQuantizer(Configuration.Default)); - } - [Fact] public void KnownQuantizersWebSafeTests() { From db76572c31944ba04439f34d9d5ddd9b5437a023 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 10 May 2019 23:11:04 +0200 Subject: [PATCH 159/223] QuantizedFrame using ReadOnlyMemory --- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 4 +- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 2 +- .../Quantization/FrameQuantizer{TPixel}.cs | 84 +++++++++---------- .../Quantization/QuantizeProcessor{TPixel}.cs | 5 +- .../Quantization/QuantizedFrame{TPixel}.cs | 4 +- .../Quantization/QuantizedImageTests.cs | 7 +- .../Quantization/WuQuantizerTests.cs | 10 ++- 7 files changed, 62 insertions(+), 54 deletions(-) diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 2770790a2..9270bb6b1 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -233,7 +233,7 @@ namespace SixLabors.ImageSharp.Formats.Gif { Span rgbaSpan = rgbaBuffer.GetSpan(); ref Rgba32 paletteRef = ref MemoryMarshal.GetReference(rgbaSpan); - PixelOperations.Instance.ToRgba32(this.configuration, quantized.Palette, rgbaSpan); + PixelOperations.Instance.ToRgba32(this.configuration, quantized.Palette.Span, rgbaSpan); for (int i = quantized.Palette.Length - 1; i >= 0; i--) { @@ -436,7 +436,7 @@ namespace SixLabors.ImageSharp.Formats.Gif { PixelOperations.Instance.ToRgb24Bytes( this.configuration, - image.Palette.AsSpan(), + image.Palette.Span, colorTable.GetSpan(), pixelCount); stream.Write(colorTable.Array, 0, colorTableLength); diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 7415b0753..db0c7f258 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -666,7 +666,7 @@ namespace SixLabors.ImageSharp.Formats.Png where TPixel : struct, IPixel { // Grab the palette and write it to the stream. - TPixel[] palette = quantized.Palette; + ReadOnlySpan palette = quantized.Palette.Span; int paletteLength = Math.Min(palette.Length, 256); int colorTableLength = paletteLength * 3; bool anyAlpha = false; diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs index 6d8136513..eac31b21d 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Numerics; using System.Runtime.CompilerServices; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Dithering; @@ -52,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.Dither = this.Diffuser != null; this.singlePass = singlePass; } - + /// /// Initializes a new instance of the class. /// @@ -73,10 +74,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } /// - public bool Dither { get; } + public IErrorDiffuser Diffuser { get; } /// - public IErrorDiffuser Diffuser { get; } + public bool Dither { get; } + + /// + public virtual void Dispose() + { + } /// public virtual QuantizedFrame QuantizeFrame(ImageFrame image) @@ -98,14 +104,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization // Collect the palette. Required before the second pass runs. ReadOnlyMemory palette = this.GetPalette(); this.paletteVector = new Vector4[palette.Length]; - PixelOperations.Instance.ToVector4(image.Configuration, palette.Span, (Span)this.paletteVector, PixelConversionModifiers.Scale); + PixelOperations.Instance.ToVector4( + image.Configuration, + palette.Span, + (Span)this.paletteVector, + PixelConversionModifiers.Scale); - // TODO: Pass ReadOnlyMemory instead of array! - var quantizedFrame = new QuantizedFrame( - image.MemoryAllocator, - width, - height, - palette.Span.ToArray()); + var quantizedFrame = new QuantizedFrame(image.MemoryAllocator, width, height, palette); if (this.Dither) { @@ -123,11 +128,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization return quantizedFrame; } - /// - public virtual void Dispose() - { - } - /// /// Execute the first pass through the pixels in the image to create the palette. /// @@ -139,19 +139,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } /// - /// Execute a second pass through the image to assign the pixels to a palette entry. + /// Returns the closest color from the palette to the given color by calculating the + /// Euclidean distance in the Rgba colorspace. /// - /// The source image. - /// The output pixel array. - /// The output color palette. - /// The width in pixels of the image. - /// The height in pixels of the image. - protected abstract void SecondPass( - ImageFrame source, - Span output, - ReadOnlySpan palette, - int width, - int height); + /// The color. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected byte GetClosestPixel(ref TPixel pixel) + { + // Check if the color is in the lookup table + if (this.distanceCache.TryGetValue(pixel, out byte value)) + { + return value; + } + + return this.GetClosestPixelSlow(ref pixel); + } /// /// Retrieve the palette for the quantized image. @@ -185,22 +188,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } /// - /// Returns the closest color from the palette to the given color by calculating the - /// Euclidean distance in the Rgba colorspace. + /// Execute a second pass through the image to assign the pixels to a palette entry. /// - /// The color. - /// The - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected byte GetClosestPixel(ref TPixel pixel) - { - // Check if the color is in the lookup table - if (this.distanceCache.TryGetValue(pixel, out byte value)) - { - return value; - } - - return this.GetClosestPixelSlow(ref pixel); - } + /// The source image. + /// The output pixel array. + /// The output color palette. + /// The width in pixels of the image. + /// The height in pixels of the image. + protected abstract void SecondPass( + ImageFrame source, + Span output, + ReadOnlySpan palette, + int width, + int height); [MethodImpl(MethodImplOptions.NoInlining)] private byte GetClosestPixelSlow(ref TPixel pixel) diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs index b52343a2a..4f134d98d 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs @@ -43,12 +43,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization { Span row = source.GetPixelRowSpan(y); ReadOnlySpan quantizedPixelSpan = quantized.GetPixelSpan(); + + ReadOnlySpan paletteSpan = quantized.Palette.Span; + int yy = y * source.Width; for (int x = 0; x < source.Width; x++) { int i = x + yy; - row[x] = quantized.Palette[Math.Min(paletteCount, quantizedPixelSpan[i])]; + row[x] = paletteSpan[Math.Min(paletteCount, quantizedPixelSpan[i])]; } } } diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs index 38862ef44..ae5b5dda8 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The image width. /// The image height. /// The color palette. - public QuantizedFrame(MemoryAllocator memoryAllocator, int width, int height, TPixel[] palette) + public QuantizedFrame(MemoryAllocator memoryAllocator, int width, int height, ReadOnlyMemory palette) { Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); @@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Gets the color palette of this . /// - public TPixel[] Palette { get; private set; } + public ReadOnlyMemory Palette { get; private set; } /// /// Gets the pixels of this . diff --git a/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs b/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs index a0d7869e3..b0de058f8 100644 --- a/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs +++ b/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; @@ -85,9 +87,10 @@ namespace SixLabors.ImageSharp.Tests // Transparent pixels are much more likely to be found at the end of a palette int index = -1; Rgba32 trans = default; - for (int i = quantized.Palette.Length - 1; i >= 0; i--) + ReadOnlySpan paletteSpan = quantized.Palette.Span; + for (int i = paletteSpan.Length - 1; i >= 0; i--) { - quantized.Palette[i].ToRgba32(ref trans); + paletteSpan[i].ToRgba32(ref trans); if (trans.Equals(default)) { diff --git a/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs b/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs index 3eacd74ea..716273699 100644 --- a/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs +++ b/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization Assert.Equal(1, result.Palette.Length); Assert.Equal(1, result.GetPixelSpan().Length); - Assert.Equal(Rgba32.Black, result.Palette[0]); + Assert.Equal(Rgba32.Black, result.Palette.Span[0]); Assert.Equal(0, result.GetPixelSpan()[0]); } } @@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization Assert.Equal(1, result.Palette.Length); Assert.Equal(1, result.GetPixelSpan().Length); - Assert.Equal(default, result.Palette[0]); + Assert.Equal(default, result.Palette.Span[0]); Assert.Equal(0, result.GetPixelSpan()[0]); } } @@ -82,6 +82,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization var actualImage = new Image(1, 256); + ReadOnlySpan paletteSpan = result.Palette.Span; int paletteCount = result.Palette.Length - 1; for (int y = 0; y < actualImage.Height; y++) { @@ -92,7 +93,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization for (int x = 0; x < actualImage.Width; x++) { int i = x + yy; - row[x] = result.Palette[Math.Min(paletteCount, quantizedPixelSpan[i])]; + row[x] = paletteSpan[Math.Min(paletteCount, quantizedPixelSpan[i])]; } } @@ -146,6 +147,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization Assert.Equal(4 * 8, result.Palette.Length); Assert.Equal(256, result.GetPixelSpan().Length); + ReadOnlySpan paletteSpan = result.Palette.Span; int paletteCount = result.Palette.Length - 1; for (int y = 0; y < actualImage.Height; y++) { @@ -156,7 +158,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization for (int x = 0; x < actualImage.Width; x++) { int i = x + yy; - row[x] = result.Palette[Math.Min(paletteCount, quantizedPixelSpan[i])]; + row[x] = paletteSpan[Math.Min(paletteCount, quantizedPixelSpan[i])]; } } } From 7fc201812766700f80393f0934ce0b132644905f Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 10 May 2019 23:31:46 +0200 Subject: [PATCH 160/223] Correct readonly-semantics for QuantizedFrame --- src/ImageSharp/Advanced/AotCompilerTools.cs | 2 +- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 2 +- src/ImageSharp/Formats/Gif/LzwEncoder.cs | 6 ++--- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 2 +- .../Quantization/FrameQuantizer{TPixel}.cs | 7 ++--- .../Quantization/QuantizeProcessor{TPixel}.cs | 2 +- .../Quantization/QuantizedFrame{TPixel}.cs | 11 +++++--- .../Quantization/WuFrameQuantizer{TPixel}.cs | 26 ++++++++++++------- .../Processors/Quantization/WuQuantizer.cs | 8 ++++-- 9 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index eb6991e6a..82df7304e 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Advanced private static void AotCompileWuQuantizer() where TPixel : struct, IPixel { - var test = new WuFrameQuantizer(new WuQuantizer(false)); + var test = new WuFrameQuantizer(Configuration.Default.MemoryAllocator, new WuQuantizer(false)); test.QuantizeFrame(new ImageFrame(Configuration.Default, 1, 1)); test.AotGetPalette(); } diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 9270bb6b1..ac9757094 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -164,7 +164,7 @@ namespace SixLabors.ImageSharp.Formats.Gif using (QuantizedFrame paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame)) { this.WriteImageData(paletteQuantized, stream); - } + } } } } diff --git a/src/ImageSharp/Formats/Gif/LzwEncoder.cs b/src/ImageSharp/Formats/Gif/LzwEncoder.cs index 2d32fd23a..b4c80a3da 100644 --- a/src/ImageSharp/Formats/Gif/LzwEncoder.cs +++ b/src/ImageSharp/Formats/Gif/LzwEncoder.cs @@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The span of indexed pixels. /// The stream to write to. - public void Encode(Span indexedPixels, Stream stream) + public void Encode(ReadOnlySpan indexedPixels, Stream stream) { // Write "initial code size" byte stream.WriteByte((byte)this.initialCodeSize); @@ -251,7 +251,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The span of indexed pixels. /// The initial bits. /// The stream to write to. - private void Compress(Span indexedPixels, int intialBits, Stream stream) + private void Compress(ReadOnlySpan indexedPixels, int intialBits, Stream stream) { int fcode; int c; @@ -375,7 +375,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - private int NextPixel(Span indexedPixels) + private int NextPixel(ReadOnlySpan indexedPixels) { return indexedPixels[this.position++] & 0xFF; } diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index db0c7f258..7bdced536 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -676,7 +676,7 @@ namespace SixLabors.ImageSharp.Formats.Png { ref byte colorTableRef = ref MemoryMarshal.GetReference(colorTable.GetSpan()); ref byte alphaTableRef = ref MemoryMarshal.GetReference(alphaTable.GetSpan()); - Span quantizedSpan = quantized.GetPixelSpan(); + ReadOnlySpan quantizedSpan = quantized.GetPixelSpan(); Rgba32 rgba = default; diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs index eac31b21d..d753b08a8 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } /// - public virtual QuantizedFrame QuantizeFrame(ImageFrame image) + public QuantizedFrame QuantizeFrame(ImageFrame image) { Guard.NotNull(image, nameof(image)); @@ -112,17 +112,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization var quantizedFrame = new QuantizedFrame(image.MemoryAllocator, width, height, palette); + Span pixelSpan = quantizedFrame.GetWritablePixelSpan(); if (this.Dither) { // We clone the image as we don't want to alter the original via dithering. using (ImageFrame clone = image.Clone()) { - this.SecondPass(clone, quantizedFrame.GetPixelSpan(), palette.Span, width, height); + this.SecondPass(clone, pixelSpan, palette.Span, width, height); } } else { - this.SecondPass(image, quantizedFrame.GetPixelSpan(), palette.Span, width, height); + this.SecondPass(image, pixelSpan, palette.Span, width, height); } return quantizedFrame; diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs index 4f134d98d..21071dd8a 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization ReadOnlySpan quantizedPixelSpan = quantized.GetPixelSpan(); ReadOnlySpan paletteSpan = quantized.Palette.Span; - + int yy = y * source.Width; for (int x = 0; x < source.Width; x++) diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs index ae5b5dda8..a4d06ac2e 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The image width. /// The image height. /// The color palette. - public QuantizedFrame(MemoryAllocator memoryAllocator, int width, int height, ReadOnlyMemory palette) + internal QuantizedFrame(MemoryAllocator memoryAllocator, int width, int height, ReadOnlyMemory palette) { Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); @@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// The [MethodImpl(InliningOptions.ShortMethod)] - public Span GetPixelSpan() => this.pixels.GetSpan(); + public ReadOnlySpan GetPixelSpan() => this.pixels.GetSpan(); /// /// Gets the representation of the pixels as a of contiguous memory @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// The row. /// The [MethodImpl(InliningOptions.ShortMethod)] - public Span GetRowSpan(int rowIndex) => this.GetPixelSpan().Slice(rowIndex * this.Width, this.Width); + public ReadOnlySpan GetRowSpan(int rowIndex) => this.GetPixelSpan().Slice(rowIndex * this.Width, this.Width); /// public void Dispose() @@ -76,5 +76,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.pixels = null; this.Palette = null; } + + /// + /// Get the non-readonly span of pixel data so can fill it. + /// + internal Span GetWritablePixelSpan() => this.pixels.GetSpan(); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs index 95918f564..2b1a24aee 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs @@ -120,33 +120,31 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// Initializes a new instance of the class. /// + /// The . /// The wu quantizer /// /// The Wu quantizer is a two pass algorithm. The initial pass sets up the 3-D color histogram, /// the second pass quantizes a color based on the position in the histogram. /// - public WuFrameQuantizer(WuQuantizer quantizer) - : this(quantizer, quantizer.MaxColors) + public WuFrameQuantizer(MemoryAllocator memoryAllocator, WuQuantizer quantizer) + : this(memoryAllocator, quantizer, quantizer.MaxColors) { } /// /// Initializes a new instance of the class. /// + /// The . /// The wu quantizer. /// The maximum number of colors to hold in the color palette. /// /// The Wu quantizer is a two pass algorithm. The initial pass sets up the 3-D color histogram, /// the second pass quantizes a color based on the position in the histogram. /// - public WuFrameQuantizer(WuQuantizer quantizer, int maxColors) - : base(quantizer, false) => this.colors = maxColors; - - /// - public override QuantizedFrame QuantizeFrame(ImageFrame image) + public WuFrameQuantizer(MemoryAllocator memoryAllocator, WuQuantizer quantizer, int maxColors) + : base(quantizer, false) { - Guard.NotNull(image, nameof(image)); - MemoryAllocator memoryAllocator = image.MemoryAllocator; + Guard.NotNull(memoryAllocator, nameof(memoryAllocator)); this.vwt = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); this.vmr = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); @@ -156,7 +154,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.m2 = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); this.tag = memoryAllocator.Allocate(TableLength, AllocationOptions.Clean); - return base.QuantizeFrame(image); + this.colors = maxColors; } /// @@ -169,6 +167,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.vma?.Dispose(); this.m2?.Dispose(); this.tag?.Dispose(); + + this.vwt = null; + this.vmr = null; + this.vmg = null; + this.vmb = null; + this.vma = null; + this.m2 = null; + this.tag = null; } internal ReadOnlyMemory AotGetPalette() => this.GetPalette(); diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs index eb8b0fec9..b80cedeb3 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs @@ -72,14 +72,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// public IFrameQuantizer CreateFrameQuantizer(Configuration configuration) where TPixel : struct, IPixel - => new WuFrameQuantizer(this); + { + Guard.NotNull(configuration, nameof(configuration)); + return new WuFrameQuantizer(configuration.MemoryAllocator, this); + } /// public IFrameQuantizer CreateFrameQuantizer(Configuration configuration, int maxColors) where TPixel : struct, IPixel { + Guard.NotNull(configuration, nameof(configuration)); maxColors = maxColors.Clamp(QuantizerConstants.MinColors, QuantizerConstants.MaxColors); - return new WuFrameQuantizer(this, maxColors); + return new WuFrameQuantizer(configuration.MemoryAllocator, this, maxColors); } private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null; From fef3a11b232857f805e727c4a2f125a77076d9c9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 11 May 2019 00:11:26 +0200 Subject: [PATCH 161/223] introduce IQuantizedFrame --- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 16 ++++---- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 8 ++-- .../Quantization/FrameQuantizer{TPixel}.cs | 2 +- .../Quantization/IFrameQuantizer{TPixel}.cs | 2 +- .../Quantization/IQuantizedFrame{TPixel}.cs | 38 +++++++++++++++++++ .../Quantization/QuantizeProcessor{TPixel}.cs | 4 +- .../Quantization/QuantizedFrameExtensions.cs | 29 ++++++++++++++ .../Quantization/QuantizedFrame{TPixel}.cs | 12 +----- .../Quantization/QuantizedImageTests.cs | 6 +-- .../Quantization/WuQuantizerTests.cs | 10 ++--- 10 files changed, 92 insertions(+), 35 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Quantization/IQuantizedFrame{TPixel}.cs create mode 100644 src/ImageSharp/Processing/Processors/Quantization/QuantizedFrameExtensions.cs diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index ac9757094..36e27866e 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Formats.Gif bool useGlobalTable = this.colorTableMode == GifColorTableMode.Global; // Quantize the image returning a palette. - QuantizedFrame quantized = null; + IQuantizedFrame quantized = null; using (IFrameQuantizer frameQuantizer = this.quantizer.CreateFrameQuantizer(image.GetConfiguration())) { quantized = frameQuantizer.QuantizeFrame(image.Frames.RootFrame); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.Formats.Gif stream.WriteByte(GifConstants.EndIntroducer); } - private void EncodeGlobal(Image image, QuantizedFrame quantized, int transparencyIndex, Stream stream) + private void EncodeGlobal(Image image, IQuantizedFrame quantized, int transparencyIndex, Stream stream) where TPixel : struct, IPixel { for (int i = 0; i < image.Frames.Count; i++) @@ -161,7 +161,7 @@ namespace SixLabors.ImageSharp.Formats.Gif using (IFrameQuantizer palleteFrameQuantizer = new PaletteFrameQuantizer(this.quantizer.Diffuser, quantized.Palette)) { - using (QuantizedFrame paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame)) + using (IQuantizedFrame paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame)) { this.WriteImageData(paletteQuantized, stream); } @@ -170,7 +170,7 @@ namespace SixLabors.ImageSharp.Formats.Gif } } - private void EncodeLocal(Image image, QuantizedFrame quantized, Stream stream) + private void EncodeLocal(Image image, IQuantizedFrame quantized, Stream stream) where TPixel : struct, IPixel { ImageFrame previousFrame = null; @@ -222,7 +222,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// /// The . /// - private int GetTransparentIndex(QuantizedFrame quantized) + private int GetTransparentIndex(IQuantizedFrame quantized) where TPixel : struct, IPixel { // Transparent pixels are much more likely to be found at the end of a palette @@ -425,7 +425,7 @@ namespace SixLabors.ImageSharp.Formats.Gif /// The pixel format. /// The to encode. /// The stream to write to. - private void WriteColorTable(QuantizedFrame image, Stream stream) + private void WriteColorTable(IQuantizedFrame image, Stream stream) where TPixel : struct, IPixel { // The maximum number of colors for the bit depth @@ -447,9 +447,9 @@ namespace SixLabors.ImageSharp.Formats.Gif /// Writes the image pixel data to the stream. /// /// The pixel format. - /// The containing indexed pixels. + /// The containing indexed pixels. /// The stream to write to. - private void WriteImageData(QuantizedFrame image, Stream stream) + private void WriteImageData(IQuantizedFrame image, Stream stream) where TPixel : struct, IPixel { using (var encoder = new LzwEncoder(this.memoryAllocator, (byte)this.bitDepth)) diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 7bdced536..cbc35f3c3 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -227,7 +227,7 @@ namespace SixLabors.ImageSharp.Formats.Png stream.Write(PngConstants.HeaderBytes, 0, PngConstants.HeaderBytes.Length); - QuantizedFrame quantized = null; + IQuantizedFrame quantized = null; if (this.pngColorType == PngColorType.Palette) { byte bits = (byte)this.pngBitDepth; @@ -511,7 +511,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The quantized pixels. Can be null. /// The row. /// The - private IManagedByteBuffer EncodePixelRow(ReadOnlySpan rowSpan, QuantizedFrame quantized, int row) + private IManagedByteBuffer EncodePixelRow(ReadOnlySpan rowSpan, IQuantizedFrame quantized, int row) where TPixel : struct, IPixel { switch (this.pngColorType) @@ -662,7 +662,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The pixel format. /// The containing image data. /// The quantized frame. - private void WritePaletteChunk(Stream stream, QuantizedFrame quantized) + private void WritePaletteChunk(Stream stream, IQuantizedFrame quantized) where TPixel : struct, IPixel { // Grab the palette and write it to the stream. @@ -808,7 +808,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The image. /// The quantized pixel data. Can be null. /// The stream. - private void WriteDataChunks(ImageFrame pixels, QuantizedFrame quantized, Stream stream) + private void WriteDataChunks(ImageFrame pixels, IQuantizedFrame quantized, Stream stream) where TPixel : struct, IPixel { this.bytesPerScanline = this.CalculateScanlineLength(this.width); diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs index d753b08a8..e6ffecc84 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization } /// - public QuantizedFrame QuantizeFrame(ImageFrame image) + public IQuantizedFrame QuantizeFrame(ImageFrame image) { Guard.NotNull(image, nameof(image)); diff --git a/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs index f0b68b3a0..54dabab0a 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/IFrameQuantizer{TPixel}.cs @@ -31,6 +31,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// /// A representing a quantized version of the image pixels. /// - QuantizedFrame QuantizeFrame(ImageFrame image); + IQuantizedFrame QuantizeFrame(ImageFrame image); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/IQuantizedFrame{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/IQuantizedFrame{TPixel}.cs new file mode 100644 index 000000000..42016459b --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Quantization/IQuantizedFrame{TPixel}.cs @@ -0,0 +1,38 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing.Processors.Quantization +{ + /// + /// Defines an abstraction to represent a quantized image frame where the pixels indexed by a color palette. + /// + /// The pixel format. + public interface IQuantizedFrame : IDisposable + where TPixel : struct, IPixel + { + /// + /// Gets the width of this . + /// + int Width { get; } + + /// + /// Gets the height of this . + /// + int Height { get; } + + /// + /// Gets the color palette of this . + /// + ReadOnlyMemory Palette { get; } + + /// + /// Gets the pixels of this . + /// + /// The The pixel span. + ReadOnlySpan GetPixelSpan(); + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs index 21071dd8a..5cb45e8d7 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs @@ -31,8 +31,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { - using (IFrameQuantizer executor = this.quantizer.CreateFrameQuantizer(configuration)) - using (QuantizedFrame quantized = executor.QuantizeFrame(source)) + using (IFrameQuantizer frameQuantizer = this.quantizer.CreateFrameQuantizer(configuration)) + using (IQuantizedFrame quantized = frameQuantizer.QuantizeFrame(source)) { int paletteCount = quantized.Palette.Length - 1; diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrameExtensions.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrameExtensions.cs new file mode 100644 index 000000000..fa3d36e10 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrameExtensions.cs @@ -0,0 +1,29 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing.Processors.Quantization +{ + /// + /// Contains extension methods for . + /// + public static class QuantizedFrameExtensions + { + /// + /// Gets the representation of the pixels as a of contiguous memory + /// at row beginning from the the first pixel on that row. + /// + /// The . + /// The row. + /// The pixel type. + /// The pixel row as a . + [MethodImpl(InliningOptions.ShortMethod)] + public static ReadOnlySpan GetRowSpan(this IQuantizedFrame frame, int rowIndex) + where TPixel : struct, IPixel + => frame.GetPixelSpan().Slice(rowIndex * frame.Width, frame.Width); + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs index a4d06ac2e..cbea82c1f 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs @@ -8,14 +8,13 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; -// TODO: Consider pooling the TPixel palette also. For Rgba48+ this would end up on th LOH if 256 colors. namespace SixLabors.ImageSharp.Processing.Processors.Quantization { /// /// Represents a quantized image frame where the pixels indexed by a color palette. /// /// The pixel format. - public class QuantizedFrame : IDisposable + public class QuantizedFrame : IQuantizedFrame where TPixel : struct, IPixel { private IMemoryOwner pixels; @@ -60,15 +59,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization [MethodImpl(InliningOptions.ShortMethod)] public ReadOnlySpan GetPixelSpan() => this.pixels.GetSpan(); - /// - /// Gets the representation of the pixels as a of contiguous memory - /// at row beginning from the the first pixel on that row. - /// - /// The row. - /// The - [MethodImpl(InliningOptions.ShortMethod)] - public ReadOnlySpan GetRowSpan(int rowIndex) => this.GetPixelSpan().Slice(rowIndex * this.Width, this.Width); - /// public void Dispose() { diff --git a/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs b/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs index b0de058f8..04e9803af 100644 --- a/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs +++ b/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Tests foreach (ImageFrame frame in image.Frames) { - QuantizedFrame quantized = + IQuantizedFrame quantized = quantizer.CreateFrameQuantizer(this.Configuration).QuantizeFrame(frame); int index = this.GetTransparentIndex(quantized); @@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Tests foreach (ImageFrame frame in image.Frames) { - QuantizedFrame quantized = + IQuantizedFrame quantized = quantizer.CreateFrameQuantizer(this.Configuration).QuantizeFrame(frame); int index = this.GetTransparentIndex(quantized); @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Tests } } - private int GetTransparentIndex(QuantizedFrame quantized) + private int GetTransparentIndex(IQuantizedFrame quantized) where TPixel : struct, IPixel { // Transparent pixels are much more likely to be found at the end of a palette diff --git a/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs b/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs index 716273699..a1de7fd4b 100644 --- a/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs +++ b/tests/ImageSharp.Tests/Quantization/WuQuantizerTests.cs @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization var quantizer = new WuQuantizer(false); using (var image = new Image(config, 1, 1, Rgba32.Black)) - using (QuantizedFrame result = quantizer.CreateFrameQuantizer(config).QuantizeFrame(image.Frames[0])) + using (IQuantizedFrame result = quantizer.CreateFrameQuantizer(config).QuantizeFrame(image.Frames[0])) { Assert.Equal(1, result.Palette.Length); Assert.Equal(1, result.GetPixelSpan().Length); @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization var quantizer = new WuQuantizer(false); using (var image = new Image(config, 1, 1, default(Rgba32))) - using (QuantizedFrame result = quantizer.CreateFrameQuantizer(config).QuantizeFrame(image.Frames[0])) + using (IQuantizedFrame result = quantizer.CreateFrameQuantizer(config).QuantizeFrame(image.Frames[0])) { Assert.Equal(1, result.Palette.Length); Assert.Equal(1, result.GetPixelSpan().Length); @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization Configuration config = Configuration.Default; var quantizer = new WuQuantizer(false); using (IFrameQuantizer frameQuantizer = quantizer.CreateFrameQuantizer(config)) - using (QuantizedFrame result = frameQuantizer.QuantizeFrame(image.Frames[0])) + using (IQuantizedFrame result = frameQuantizer.QuantizeFrame(image.Frames[0])) { Assert.Equal(256, result.Palette.Length); Assert.Equal(256, result.GetPixelSpan().Length); @@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization Configuration config = Configuration.Default; var quantizer = new WuQuantizer(false); using (IFrameQuantizer frameQuantizer = quantizer.CreateFrameQuantizer(config)) - using (QuantizedFrame result = frameQuantizer.QuantizeFrame(image.Frames[0])) + using (IQuantizedFrame result = frameQuantizer.QuantizeFrame(image.Frames[0])) { Assert.Equal(48, result.Palette.Length); } @@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp.Tests.Quantization var quantizer = new WuQuantizer(false); using (IFrameQuantizer frameQuantizer = quantizer.CreateFrameQuantizer(config)) - using (QuantizedFrame result = frameQuantizer.QuantizeFrame(image.Frames[0])) + using (IQuantizedFrame result = frameQuantizer.QuantizeFrame(image.Frames[0])) { Assert.Equal(4 * 8, result.Palette.Length); Assert.Equal(256, result.GetPixelSpan().Length); From a3cb4c978888ab99721b1764c492b29f59c782e1 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 11 May 2019 00:33:00 +0200 Subject: [PATCH 162/223] move all extension methods under a subfolder (non-namespace providing) --- src/ImageSharp/ImageSharp.csproj.DotSettings | 1 + .../Processing/{ => Extensions}/AutoOrientExtensions.cs | 0 .../Processing/{ => Extensions}/BackgroundColorExtensions.cs | 0 .../Processing/{ => Extensions}/BinaryDiffuseExtensions.cs | 0 .../Processing/{ => Extensions}/BinaryDitherExtensions.cs | 0 .../Processing/{ => Extensions}/BinaryThresholdExtensions.cs | 0 .../Processing/{ => Extensions}/BlackWhiteExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/BoxBlurExtensions.cs | 0 .../Processing/{ => Extensions}/BrightnessExtensions.cs | 0 .../Processing/{ => Extensions}/ColorBlindnessExtensions.cs | 0 .../Processing/{ => Extensions}/ContrastExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/CropExtensions.cs | 0 .../Processing/{ => Extensions}/DetectEdgesExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/DiffuseExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/DitherExtensions.cs | 0 .../Processing/{ => Extensions}/EntropyCropExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/FilterExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/FlipExtensions.cs | 0 .../Processing/{ => Extensions}/GaussianBlurExtensions.cs | 0 .../Processing/{ => Extensions}/GaussianSharpenExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/GlowExtensions.cs | 0 .../Processing/{ => Extensions}/GrayscaleExtensions.cs | 0 .../HistogramEqualizationExtensions.cs} | 2 +- src/ImageSharp/Processing/{ => Extensions}/HueExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/InvertExtensions.cs | 0 .../Processing/{ => Extensions}/KodachromeExtensions.cs | 0 .../Processing/{ => Extensions}/LomographExtensions.cs | 0 .../Processing/{ => Extensions}/OilPaintExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/OpacityExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/PadExtensions.cs | 0 .../Processing/{ => Extensions}/PixelateExtensions.cs | 0 .../Processing/{ => Extensions}/PolaroidExtensions.cs | 0 .../Processing/{ => Extensions}/ProcessingExtensions.cs | 0 .../Processing/{ => Extensions}/QuantizeExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/ResizeExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/RotateExtensions.cs | 0 .../Processing/{ => Extensions}/RotateFlipExtensions.cs | 0 .../Processing/{ => Extensions}/SaturateExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/SepiaExtensions.cs | 0 src/ImageSharp/Processing/{ => Extensions}/SkewExtensions.cs | 0 .../Processing/{ => Extensions}/TransformExtensions.cs | 0 .../Processing/{ => Extensions}/VignetteExtensions.cs | 0 42 files changed, 2 insertions(+), 1 deletion(-) rename src/ImageSharp/Processing/{ => Extensions}/AutoOrientExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/BackgroundColorExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/BinaryDiffuseExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/BinaryDitherExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/BinaryThresholdExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/BlackWhiteExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/BoxBlurExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/BrightnessExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/ColorBlindnessExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/ContrastExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/CropExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/DetectEdgesExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/DiffuseExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/DitherExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/EntropyCropExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/FilterExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/FlipExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/GaussianBlurExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/GaussianSharpenExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/GlowExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/GrayscaleExtensions.cs (100%) rename src/ImageSharp/Processing/{HistogramEqualizationExtension.cs => Extensions/HistogramEqualizationExtensions.cs} (96%) rename src/ImageSharp/Processing/{ => Extensions}/HueExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/InvertExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/KodachromeExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/LomographExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/OilPaintExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/OpacityExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/PadExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/PixelateExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/PolaroidExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/ProcessingExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/QuantizeExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/ResizeExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/RotateExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/RotateFlipExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/SaturateExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/SepiaExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/SkewExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/TransformExtensions.cs (100%) rename src/ImageSharp/Processing/{ => Extensions}/VignetteExtensions.cs (100%) diff --git a/src/ImageSharp/ImageSharp.csproj.DotSettings b/src/ImageSharp/ImageSharp.csproj.DotSettings index e43e92ddc..018ca75cd 100644 --- a/src/ImageSharp/ImageSharp.csproj.DotSettings +++ b/src/ImageSharp/ImageSharp.csproj.DotSettings @@ -7,6 +7,7 @@ True True True + True True True True \ No newline at end of file diff --git a/src/ImageSharp/Processing/AutoOrientExtensions.cs b/src/ImageSharp/Processing/Extensions/AutoOrientExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/AutoOrientExtensions.cs rename to src/ImageSharp/Processing/Extensions/AutoOrientExtensions.cs diff --git a/src/ImageSharp/Processing/BackgroundColorExtensions.cs b/src/ImageSharp/Processing/Extensions/BackgroundColorExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/BackgroundColorExtensions.cs rename to src/ImageSharp/Processing/Extensions/BackgroundColorExtensions.cs diff --git a/src/ImageSharp/Processing/BinaryDiffuseExtensions.cs b/src/ImageSharp/Processing/Extensions/BinaryDiffuseExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/BinaryDiffuseExtensions.cs rename to src/ImageSharp/Processing/Extensions/BinaryDiffuseExtensions.cs diff --git a/src/ImageSharp/Processing/BinaryDitherExtensions.cs b/src/ImageSharp/Processing/Extensions/BinaryDitherExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/BinaryDitherExtensions.cs rename to src/ImageSharp/Processing/Extensions/BinaryDitherExtensions.cs diff --git a/src/ImageSharp/Processing/BinaryThresholdExtensions.cs b/src/ImageSharp/Processing/Extensions/BinaryThresholdExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/BinaryThresholdExtensions.cs rename to src/ImageSharp/Processing/Extensions/BinaryThresholdExtensions.cs diff --git a/src/ImageSharp/Processing/BlackWhiteExtensions.cs b/src/ImageSharp/Processing/Extensions/BlackWhiteExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/BlackWhiteExtensions.cs rename to src/ImageSharp/Processing/Extensions/BlackWhiteExtensions.cs diff --git a/src/ImageSharp/Processing/BoxBlurExtensions.cs b/src/ImageSharp/Processing/Extensions/BoxBlurExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/BoxBlurExtensions.cs rename to src/ImageSharp/Processing/Extensions/BoxBlurExtensions.cs diff --git a/src/ImageSharp/Processing/BrightnessExtensions.cs b/src/ImageSharp/Processing/Extensions/BrightnessExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/BrightnessExtensions.cs rename to src/ImageSharp/Processing/Extensions/BrightnessExtensions.cs diff --git a/src/ImageSharp/Processing/ColorBlindnessExtensions.cs b/src/ImageSharp/Processing/Extensions/ColorBlindnessExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/ColorBlindnessExtensions.cs rename to src/ImageSharp/Processing/Extensions/ColorBlindnessExtensions.cs diff --git a/src/ImageSharp/Processing/ContrastExtensions.cs b/src/ImageSharp/Processing/Extensions/ContrastExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/ContrastExtensions.cs rename to src/ImageSharp/Processing/Extensions/ContrastExtensions.cs diff --git a/src/ImageSharp/Processing/CropExtensions.cs b/src/ImageSharp/Processing/Extensions/CropExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/CropExtensions.cs rename to src/ImageSharp/Processing/Extensions/CropExtensions.cs diff --git a/src/ImageSharp/Processing/DetectEdgesExtensions.cs b/src/ImageSharp/Processing/Extensions/DetectEdgesExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/DetectEdgesExtensions.cs rename to src/ImageSharp/Processing/Extensions/DetectEdgesExtensions.cs diff --git a/src/ImageSharp/Processing/DiffuseExtensions.cs b/src/ImageSharp/Processing/Extensions/DiffuseExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/DiffuseExtensions.cs rename to src/ImageSharp/Processing/Extensions/DiffuseExtensions.cs diff --git a/src/ImageSharp/Processing/DitherExtensions.cs b/src/ImageSharp/Processing/Extensions/DitherExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/DitherExtensions.cs rename to src/ImageSharp/Processing/Extensions/DitherExtensions.cs diff --git a/src/ImageSharp/Processing/EntropyCropExtensions.cs b/src/ImageSharp/Processing/Extensions/EntropyCropExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/EntropyCropExtensions.cs rename to src/ImageSharp/Processing/Extensions/EntropyCropExtensions.cs diff --git a/src/ImageSharp/Processing/FilterExtensions.cs b/src/ImageSharp/Processing/Extensions/FilterExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/FilterExtensions.cs rename to src/ImageSharp/Processing/Extensions/FilterExtensions.cs diff --git a/src/ImageSharp/Processing/FlipExtensions.cs b/src/ImageSharp/Processing/Extensions/FlipExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/FlipExtensions.cs rename to src/ImageSharp/Processing/Extensions/FlipExtensions.cs diff --git a/src/ImageSharp/Processing/GaussianBlurExtensions.cs b/src/ImageSharp/Processing/Extensions/GaussianBlurExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/GaussianBlurExtensions.cs rename to src/ImageSharp/Processing/Extensions/GaussianBlurExtensions.cs diff --git a/src/ImageSharp/Processing/GaussianSharpenExtensions.cs b/src/ImageSharp/Processing/Extensions/GaussianSharpenExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/GaussianSharpenExtensions.cs rename to src/ImageSharp/Processing/Extensions/GaussianSharpenExtensions.cs diff --git a/src/ImageSharp/Processing/GlowExtensions.cs b/src/ImageSharp/Processing/Extensions/GlowExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/GlowExtensions.cs rename to src/ImageSharp/Processing/Extensions/GlowExtensions.cs diff --git a/src/ImageSharp/Processing/GrayscaleExtensions.cs b/src/ImageSharp/Processing/Extensions/GrayscaleExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/GrayscaleExtensions.cs rename to src/ImageSharp/Processing/Extensions/GrayscaleExtensions.cs diff --git a/src/ImageSharp/Processing/HistogramEqualizationExtension.cs b/src/ImageSharp/Processing/Extensions/HistogramEqualizationExtensions.cs similarity index 96% rename from src/ImageSharp/Processing/HistogramEqualizationExtension.cs rename to src/ImageSharp/Processing/Extensions/HistogramEqualizationExtensions.cs index 01c14fc09..72962a3f9 100644 --- a/src/ImageSharp/Processing/HistogramEqualizationExtension.cs +++ b/src/ImageSharp/Processing/Extensions/HistogramEqualizationExtensions.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Defines extension that allow the adjustment of the contrast of an image via its histogram. /// - public static class HistogramEqualizationExtension + public static class HistogramEqualizationExtensions { /// /// Equalizes the histogram of an image to increases the contrast. diff --git a/src/ImageSharp/Processing/HueExtensions.cs b/src/ImageSharp/Processing/Extensions/HueExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/HueExtensions.cs rename to src/ImageSharp/Processing/Extensions/HueExtensions.cs diff --git a/src/ImageSharp/Processing/InvertExtensions.cs b/src/ImageSharp/Processing/Extensions/InvertExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/InvertExtensions.cs rename to src/ImageSharp/Processing/Extensions/InvertExtensions.cs diff --git a/src/ImageSharp/Processing/KodachromeExtensions.cs b/src/ImageSharp/Processing/Extensions/KodachromeExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/KodachromeExtensions.cs rename to src/ImageSharp/Processing/Extensions/KodachromeExtensions.cs diff --git a/src/ImageSharp/Processing/LomographExtensions.cs b/src/ImageSharp/Processing/Extensions/LomographExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/LomographExtensions.cs rename to src/ImageSharp/Processing/Extensions/LomographExtensions.cs diff --git a/src/ImageSharp/Processing/OilPaintExtensions.cs b/src/ImageSharp/Processing/Extensions/OilPaintExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/OilPaintExtensions.cs rename to src/ImageSharp/Processing/Extensions/OilPaintExtensions.cs diff --git a/src/ImageSharp/Processing/OpacityExtensions.cs b/src/ImageSharp/Processing/Extensions/OpacityExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/OpacityExtensions.cs rename to src/ImageSharp/Processing/Extensions/OpacityExtensions.cs diff --git a/src/ImageSharp/Processing/PadExtensions.cs b/src/ImageSharp/Processing/Extensions/PadExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/PadExtensions.cs rename to src/ImageSharp/Processing/Extensions/PadExtensions.cs diff --git a/src/ImageSharp/Processing/PixelateExtensions.cs b/src/ImageSharp/Processing/Extensions/PixelateExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/PixelateExtensions.cs rename to src/ImageSharp/Processing/Extensions/PixelateExtensions.cs diff --git a/src/ImageSharp/Processing/PolaroidExtensions.cs b/src/ImageSharp/Processing/Extensions/PolaroidExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/PolaroidExtensions.cs rename to src/ImageSharp/Processing/Extensions/PolaroidExtensions.cs diff --git a/src/ImageSharp/Processing/ProcessingExtensions.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/ProcessingExtensions.cs rename to src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs diff --git a/src/ImageSharp/Processing/QuantizeExtensions.cs b/src/ImageSharp/Processing/Extensions/QuantizeExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/QuantizeExtensions.cs rename to src/ImageSharp/Processing/Extensions/QuantizeExtensions.cs diff --git a/src/ImageSharp/Processing/ResizeExtensions.cs b/src/ImageSharp/Processing/Extensions/ResizeExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/ResizeExtensions.cs rename to src/ImageSharp/Processing/Extensions/ResizeExtensions.cs diff --git a/src/ImageSharp/Processing/RotateExtensions.cs b/src/ImageSharp/Processing/Extensions/RotateExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/RotateExtensions.cs rename to src/ImageSharp/Processing/Extensions/RotateExtensions.cs diff --git a/src/ImageSharp/Processing/RotateFlipExtensions.cs b/src/ImageSharp/Processing/Extensions/RotateFlipExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/RotateFlipExtensions.cs rename to src/ImageSharp/Processing/Extensions/RotateFlipExtensions.cs diff --git a/src/ImageSharp/Processing/SaturateExtensions.cs b/src/ImageSharp/Processing/Extensions/SaturateExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/SaturateExtensions.cs rename to src/ImageSharp/Processing/Extensions/SaturateExtensions.cs diff --git a/src/ImageSharp/Processing/SepiaExtensions.cs b/src/ImageSharp/Processing/Extensions/SepiaExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/SepiaExtensions.cs rename to src/ImageSharp/Processing/Extensions/SepiaExtensions.cs diff --git a/src/ImageSharp/Processing/SkewExtensions.cs b/src/ImageSharp/Processing/Extensions/SkewExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/SkewExtensions.cs rename to src/ImageSharp/Processing/Extensions/SkewExtensions.cs diff --git a/src/ImageSharp/Processing/TransformExtensions.cs b/src/ImageSharp/Processing/Extensions/TransformExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/TransformExtensions.cs rename to src/ImageSharp/Processing/Extensions/TransformExtensions.cs diff --git a/src/ImageSharp/Processing/VignetteExtensions.cs b/src/ImageSharp/Processing/Extensions/VignetteExtensions.cs similarity index 100% rename from src/ImageSharp/Processing/VignetteExtensions.cs rename to src/ImageSharp/Processing/Extensions/VignetteExtensions.cs From 27912844787879cf2b2ec8565ca4b1f8e5db8f72 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 11 May 2019 13:45:26 +0200 Subject: [PATCH 163/223] re-enable all target frameworks --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 3 +-- src/ImageSharp/ImageSharp.csproj | 3 +-- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index fdeb27a77..915915f6c 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -11,8 +11,7 @@ $(packageversion) 0.0.1 - - netstandard2.0 + netcoreapp2.1;netstandard1.3;netstandard2.0 7.3 true diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 4abe2f57a..d734648f4 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -11,8 +11,7 @@ $(packageversion) 0.0.1 - - netstandard2.0 + netcoreapp2.1;netstandard1.3;netstandard2.0;net472 true true diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index efdf89964..0b727f30c 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,7 +1,6 @@  - - netcoreapp2.1 + netcoreapp2.1;net462;net472 True latest full From e8695732b6c3367d30003cb2e563119312a58a36 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sat, 11 May 2019 13:52:18 +0200 Subject: [PATCH 164/223] Using tolerant comparer for the Bit8Gs image --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 3 +- .../Formats/Bmp/BmpEncoderTests.cs | 37 ++++++++++++++++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 9d9c7b624..0cbc4fca1 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -1022,7 +1022,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.bmpMetadata.InfoHeaderType = infoHeaderType; // We can only encode at these bit rates so far. - if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel16) + if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel8) + || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel16) || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24) || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel32)) { diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index f3d6e0fa8..1d489e69d 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -3,12 +3,11 @@ using System.IO; -using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using Xunit; using Xunit.Abstractions; @@ -128,11 +127,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [Theory] // WinBmpv3 is a 24 bits per pixel image [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] + [WithFile(F, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] public void Encode_24Bit_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); [Theory] [WithFile(WinBmpv3, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] + [WithFile(F, PixelTypes.Rgb24, BmpBitsPerPixel.Pixel24)] public void Encode_24Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); @@ -150,24 +151,48 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); [Theory] + [WithFile(WinBmpv5, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] - [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] public void Encode_8Bit_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: false); [Theory] + [WithFile(WinBmpv5, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] [WithFile(Bit8Palette4, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel8)] - [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] public void Encode_8Bit_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); + [Theory] + [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] + public void Encode_8BitGray_WithV3Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => + TestBmpEncoderCore( + provider, + bitsPerPixel, + supportTransparency: false, + ImageComparer.TolerantPercentage(0.01f)); + + [Theory] + [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] + public void Encode_8BitGray_WithV4Header_Works(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) + where TPixel : struct, IPixel => + TestBmpEncoderCore( + provider, + bitsPerPixel, + supportTransparency: true, + ImageComparer.TolerantPercentage(0.01f)); + [Theory] [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] [WithFile(Bit32Rgba, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] public void Encode_PreservesAlpha(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel) where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel, supportTransparency: true); - private static void TestBmpEncoderCore(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel, bool supportTransparency = true) + private static void TestBmpEncoderCore( + TestImageProvider provider, + BmpBitsPerPixel bitsPerPixel, + bool supportTransparency = true, + ImageComparer customComparer = null) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) @@ -181,7 +206,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp var encoder = new BmpEncoder { BitsPerPixel = bitsPerPixel, SupportTransparency = supportTransparency }; // Does DebugSave & load reference CompareToReferenceInput(): - image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder); + image.VerifyEncoder(provider, "bmp", bitsPerPixel, encoder, customComparer); } } } From d0466c4c15ece81714eac6e3ac3a96fdc3ad47a7 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 11 May 2019 13:57:21 +0200 Subject: [PATCH 165/223] More docs for Color, correct naming in ColorBuilder --- src/ImageSharp/Color/Color.cs | 8 +- .../PixelFormats/ColorBuilder{TPixel}.cs | 4 +- .../PixelFormats/NamedColors{TPixel}.cs | 284 +++++++++--------- 3 files changed, 151 insertions(+), 145 deletions(-) diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index 94b5dde2e..f2f8578d8 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -12,8 +12,14 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { /// - /// Represents a color value that is convertible to all implementations. + /// Represents a color value that is convertible to any type. /// + /// + /// The internal representation and layout of this structure is hidden by intention. + /// It's not serializable, and it should not be considered as part of a contract. + /// Unlike System.Drawing.Color, has to be converted to a specific pixel value + /// to query the color components. + /// public readonly partial struct Color : IEquatable { private readonly Rgba64 data; diff --git a/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs b/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs index 2572b3293..c1fb13e4d 100644 --- a/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The green intensity. /// The blue intensity. /// Returns a that represents the color defined by the provided RGB values with 100% opacity. - public static TPixel FromRGB(byte red, byte green, byte blue) => FromRGBA(red, green, blue, 255); + public static TPixel FromRgb(byte red, byte green, byte blue) => FromRgba(red, green, blue, 255); /// /// Creates a new representation from standard RGBA bytes. @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The blue intensity. /// The alpha intensity. /// Returns a that represents the color defined by the provided RGBA values. - public static TPixel FromRGBA(byte red, byte green, byte blue, byte alpha) + public static TPixel FromRgba(byte red, byte green, byte blue, byte alpha) { TPixel color = default; color.FromRgba32(new Rgba32(red, green, blue, alpha)); diff --git a/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs b/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs index 7e093de04..2138e2e2f 100644 --- a/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs @@ -22,712 +22,712 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Represents a matching the W3C definition that has an hex value of #F0F8FF. /// - public static readonly TPixel AliceBlue = ColorBuilder.FromRGBA(240, 248, 255, 255); + public static readonly TPixel AliceBlue = ColorBuilder.FromRgba(240, 248, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #FAEBD7. /// - public static readonly TPixel AntiqueWhite = ColorBuilder.FromRGBA(250, 235, 215, 255); + public static readonly TPixel AntiqueWhite = ColorBuilder.FromRgba(250, 235, 215, 255); /// /// Represents a matching the W3C definition that has an hex value of #00FFFF. /// - public static readonly TPixel Aqua = ColorBuilder.FromRGBA(0, 255, 255, 255); + public static readonly TPixel Aqua = ColorBuilder.FromRgba(0, 255, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #7FFFD4. /// - public static readonly TPixel Aquamarine = ColorBuilder.FromRGBA(127, 255, 212, 255); + public static readonly TPixel Aquamarine = ColorBuilder.FromRgba(127, 255, 212, 255); /// /// Represents a matching the W3C definition that has an hex value of #F0FFFF. /// - public static readonly TPixel Azure = ColorBuilder.FromRGBA(240, 255, 255, 255); + public static readonly TPixel Azure = ColorBuilder.FromRgba(240, 255, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #F5F5DC. /// - public static readonly TPixel Beige = ColorBuilder.FromRGBA(245, 245, 220, 255); + public static readonly TPixel Beige = ColorBuilder.FromRgba(245, 245, 220, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFE4C4. /// - public static readonly TPixel Bisque = ColorBuilder.FromRGBA(255, 228, 196, 255); + public static readonly TPixel Bisque = ColorBuilder.FromRgba(255, 228, 196, 255); /// /// Represents a matching the W3C definition that has an hex value of #000000. /// - public static readonly TPixel Black = ColorBuilder.FromRGBA(0, 0, 0, 255); + public static readonly TPixel Black = ColorBuilder.FromRgba(0, 0, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFEBCD. /// - public static readonly TPixel BlanchedAlmond = ColorBuilder.FromRGBA(255, 235, 205, 255); + public static readonly TPixel BlanchedAlmond = ColorBuilder.FromRgba(255, 235, 205, 255); /// /// Represents a matching the W3C definition that has an hex value of #0000FF. /// - public static readonly TPixel Blue = ColorBuilder.FromRGBA(0, 0, 255, 255); + public static readonly TPixel Blue = ColorBuilder.FromRgba(0, 0, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #8A2BE2. /// - public static readonly TPixel BlueViolet = ColorBuilder.FromRGBA(138, 43, 226, 255); + public static readonly TPixel BlueViolet = ColorBuilder.FromRgba(138, 43, 226, 255); /// /// Represents a matching the W3C definition that has an hex value of #A52A2A. /// - public static readonly TPixel Brown = ColorBuilder.FromRGBA(165, 42, 42, 255); + public static readonly TPixel Brown = ColorBuilder.FromRgba(165, 42, 42, 255); /// /// Represents a matching the W3C definition that has an hex value of #DEB887. /// - public static readonly TPixel BurlyWood = ColorBuilder.FromRGBA(222, 184, 135, 255); + public static readonly TPixel BurlyWood = ColorBuilder.FromRgba(222, 184, 135, 255); /// /// Represents a matching the W3C definition that has an hex value of #5F9EA0. /// - public static readonly TPixel CadetBlue = ColorBuilder.FromRGBA(95, 158, 160, 255); + public static readonly TPixel CadetBlue = ColorBuilder.FromRgba(95, 158, 160, 255); /// /// Represents a matching the W3C definition that has an hex value of #7FFF00. /// - public static readonly TPixel Chartreuse = ColorBuilder.FromRGBA(127, 255, 0, 255); + public static readonly TPixel Chartreuse = ColorBuilder.FromRgba(127, 255, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #D2691E. /// - public static readonly TPixel Chocolate = ColorBuilder.FromRGBA(210, 105, 30, 255); + public static readonly TPixel Chocolate = ColorBuilder.FromRgba(210, 105, 30, 255); /// /// Represents a matching the W3C definition that has an hex value of #FF7F50. /// - public static readonly TPixel Coral = ColorBuilder.FromRGBA(255, 127, 80, 255); + public static readonly TPixel Coral = ColorBuilder.FromRgba(255, 127, 80, 255); /// /// Represents a matching the W3C definition that has an hex value of #6495ED. /// - public static readonly TPixel CornflowerBlue = ColorBuilder.FromRGBA(100, 149, 237, 255); + public static readonly TPixel CornflowerBlue = ColorBuilder.FromRgba(100, 149, 237, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFF8DC. /// - public static readonly TPixel Cornsilk = ColorBuilder.FromRGBA(255, 248, 220, 255); + public static readonly TPixel Cornsilk = ColorBuilder.FromRgba(255, 248, 220, 255); /// /// Represents a matching the W3C definition that has an hex value of #DC143C. /// - public static readonly TPixel Crimson = ColorBuilder.FromRGBA(220, 20, 60, 255); + public static readonly TPixel Crimson = ColorBuilder.FromRgba(220, 20, 60, 255); /// /// Represents a matching the W3C definition that has an hex value of #00FFFF. /// - public static readonly TPixel Cyan = ColorBuilder.FromRGBA(0, 255, 255, 255); + public static readonly TPixel Cyan = ColorBuilder.FromRgba(0, 255, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #00008B. /// - public static readonly TPixel DarkBlue = ColorBuilder.FromRGBA(0, 0, 139, 255); + public static readonly TPixel DarkBlue = ColorBuilder.FromRgba(0, 0, 139, 255); /// /// Represents a matching the W3C definition that has an hex value of #008B8B. /// - public static readonly TPixel DarkCyan = ColorBuilder.FromRGBA(0, 139, 139, 255); + public static readonly TPixel DarkCyan = ColorBuilder.FromRgba(0, 139, 139, 255); /// /// Represents a matching the W3C definition that has an hex value of #B8860B. /// - public static readonly TPixel DarkGoldenrod = ColorBuilder.FromRGBA(184, 134, 11, 255); + public static readonly TPixel DarkGoldenrod = ColorBuilder.FromRgba(184, 134, 11, 255); /// /// Represents a matching the W3C definition that has an hex value of #A9A9A9. /// - public static readonly TPixel DarkGray = ColorBuilder.FromRGBA(169, 169, 169, 255); + public static readonly TPixel DarkGray = ColorBuilder.FromRgba(169, 169, 169, 255); /// /// Represents a matching the W3C definition that has an hex value of #006400. /// - public static readonly TPixel DarkGreen = ColorBuilder.FromRGBA(0, 100, 0, 255); + public static readonly TPixel DarkGreen = ColorBuilder.FromRgba(0, 100, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #BDB76B. /// - public static readonly TPixel DarkKhaki = ColorBuilder.FromRGBA(189, 183, 107, 255); + public static readonly TPixel DarkKhaki = ColorBuilder.FromRgba(189, 183, 107, 255); /// /// Represents a matching the W3C definition that has an hex value of #8B008B. /// - public static readonly TPixel DarkMagenta = ColorBuilder.FromRGBA(139, 0, 139, 255); + public static readonly TPixel DarkMagenta = ColorBuilder.FromRgba(139, 0, 139, 255); /// /// Represents a matching the W3C definition that has an hex value of #556B2F. /// - public static readonly TPixel DarkOliveGreen = ColorBuilder.FromRGBA(85, 107, 47, 255); + public static readonly TPixel DarkOliveGreen = ColorBuilder.FromRgba(85, 107, 47, 255); /// /// Represents a matching the W3C definition that has an hex value of #FF8C00. /// - public static readonly TPixel DarkOrange = ColorBuilder.FromRGBA(255, 140, 0, 255); + public static readonly TPixel DarkOrange = ColorBuilder.FromRgba(255, 140, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #9932CC. /// - public static readonly TPixel DarkOrchid = ColorBuilder.FromRGBA(153, 50, 204, 255); + public static readonly TPixel DarkOrchid = ColorBuilder.FromRgba(153, 50, 204, 255); /// /// Represents a matching the W3C definition that has an hex value of #8B0000. /// - public static readonly TPixel DarkRed = ColorBuilder.FromRGBA(139, 0, 0, 255); + public static readonly TPixel DarkRed = ColorBuilder.FromRgba(139, 0, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #E9967A. /// - public static readonly TPixel DarkSalmon = ColorBuilder.FromRGBA(233, 150, 122, 255); + public static readonly TPixel DarkSalmon = ColorBuilder.FromRgba(233, 150, 122, 255); /// /// Represents a matching the W3C definition that has an hex value of #8FBC8B. /// - public static readonly TPixel DarkSeaGreen = ColorBuilder.FromRGBA(143, 188, 139, 255); + public static readonly TPixel DarkSeaGreen = ColorBuilder.FromRgba(143, 188, 139, 255); /// /// Represents a matching the W3C definition that has an hex value of #483D8B. /// - public static readonly TPixel DarkSlateBlue = ColorBuilder.FromRGBA(72, 61, 139, 255); + public static readonly TPixel DarkSlateBlue = ColorBuilder.FromRgba(72, 61, 139, 255); /// /// Represents a matching the W3C definition that has an hex value of #2F4F4F. /// - public static readonly TPixel DarkSlateGray = ColorBuilder.FromRGBA(47, 79, 79, 255); + public static readonly TPixel DarkSlateGray = ColorBuilder.FromRgba(47, 79, 79, 255); /// /// Represents a matching the W3C definition that has an hex value of #00CED1. /// - public static readonly TPixel DarkTurquoise = ColorBuilder.FromRGBA(0, 206, 209, 255); + public static readonly TPixel DarkTurquoise = ColorBuilder.FromRgba(0, 206, 209, 255); /// /// Represents a matching the W3C definition that has an hex value of #9400D3. /// - public static readonly TPixel DarkViolet = ColorBuilder.FromRGBA(148, 0, 211, 255); + public static readonly TPixel DarkViolet = ColorBuilder.FromRgba(148, 0, 211, 255); /// /// Represents a matching the W3C definition that has an hex value of #FF1493. /// - public static readonly TPixel DeepPink = ColorBuilder.FromRGBA(255, 20, 147, 255); + public static readonly TPixel DeepPink = ColorBuilder.FromRgba(255, 20, 147, 255); /// /// Represents a matching the W3C definition that has an hex value of #00BFFF. /// - public static readonly TPixel DeepSkyBlue = ColorBuilder.FromRGBA(0, 191, 255, 255); + public static readonly TPixel DeepSkyBlue = ColorBuilder.FromRgba(0, 191, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #696969. /// - public static readonly TPixel DimGray = ColorBuilder.FromRGBA(105, 105, 105, 255); + public static readonly TPixel DimGray = ColorBuilder.FromRgba(105, 105, 105, 255); /// /// Represents a matching the W3C definition that has an hex value of #1E90FF. /// - public static readonly TPixel DodgerBlue = ColorBuilder.FromRGBA(30, 144, 255, 255); + public static readonly TPixel DodgerBlue = ColorBuilder.FromRgba(30, 144, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #B22222. /// - public static readonly TPixel Firebrick = ColorBuilder.FromRGBA(178, 34, 34, 255); + public static readonly TPixel Firebrick = ColorBuilder.FromRgba(178, 34, 34, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFFAF0. /// - public static readonly TPixel FloralWhite = ColorBuilder.FromRGBA(255, 250, 240, 255); + public static readonly TPixel FloralWhite = ColorBuilder.FromRgba(255, 250, 240, 255); /// /// Represents a matching the W3C definition that has an hex value of #228B22. /// - public static readonly TPixel ForestGreen = ColorBuilder.FromRGBA(34, 139, 34, 255); + public static readonly TPixel ForestGreen = ColorBuilder.FromRgba(34, 139, 34, 255); /// /// Represents a matching the W3C definition that has an hex value of #FF00FF. /// - public static readonly TPixel Fuchsia = ColorBuilder.FromRGBA(255, 0, 255, 255); + public static readonly TPixel Fuchsia = ColorBuilder.FromRgba(255, 0, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #DCDCDC. /// - public static readonly TPixel Gainsboro = ColorBuilder.FromRGBA(220, 220, 220, 255); + public static readonly TPixel Gainsboro = ColorBuilder.FromRgba(220, 220, 220, 255); /// /// Represents a matching the W3C definition that has an hex value of #F8F8FF. /// - public static readonly TPixel GhostWhite = ColorBuilder.FromRGBA(248, 248, 255, 255); + public static readonly TPixel GhostWhite = ColorBuilder.FromRgba(248, 248, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFD700. /// - public static readonly TPixel Gold = ColorBuilder.FromRGBA(255, 215, 0, 255); + public static readonly TPixel Gold = ColorBuilder.FromRgba(255, 215, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #DAA520. /// - public static readonly TPixel Goldenrod = ColorBuilder.FromRGBA(218, 165, 32, 255); + public static readonly TPixel Goldenrod = ColorBuilder.FromRgba(218, 165, 32, 255); /// /// Represents a matching the W3C definition that has an hex value of #808080. /// - public static readonly TPixel Gray = ColorBuilder.FromRGBA(128, 128, 128, 255); + public static readonly TPixel Gray = ColorBuilder.FromRgba(128, 128, 128, 255); /// /// Represents a matching the W3C definition that has an hex value of #008000. /// - public static readonly TPixel Green = ColorBuilder.FromRGBA(0, 128, 0, 255); + public static readonly TPixel Green = ColorBuilder.FromRgba(0, 128, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #ADFF2F. /// - public static readonly TPixel GreenYellow = ColorBuilder.FromRGBA(173, 255, 47, 255); + public static readonly TPixel GreenYellow = ColorBuilder.FromRgba(173, 255, 47, 255); /// /// Represents a matching the W3C definition that has an hex value of #F0FFF0. /// - public static readonly TPixel Honeydew = ColorBuilder.FromRGBA(240, 255, 240, 255); + public static readonly TPixel Honeydew = ColorBuilder.FromRgba(240, 255, 240, 255); /// /// Represents a matching the W3C definition that has an hex value of #FF69B4. /// - public static readonly TPixel HotPink = ColorBuilder.FromRGBA(255, 105, 180, 255); + public static readonly TPixel HotPink = ColorBuilder.FromRgba(255, 105, 180, 255); /// /// Represents a matching the W3C definition that has an hex value of #CD5C5C. /// - public static readonly TPixel IndianRed = ColorBuilder.FromRGBA(205, 92, 92, 255); + public static readonly TPixel IndianRed = ColorBuilder.FromRgba(205, 92, 92, 255); /// /// Represents a matching the W3C definition that has an hex value of #4B0082. /// - public static readonly TPixel Indigo = ColorBuilder.FromRGBA(75, 0, 130, 255); + public static readonly TPixel Indigo = ColorBuilder.FromRgba(75, 0, 130, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFFFF0. /// - public static readonly TPixel Ivory = ColorBuilder.FromRGBA(255, 255, 240, 255); + public static readonly TPixel Ivory = ColorBuilder.FromRgba(255, 255, 240, 255); /// /// Represents a matching the W3C definition that has an hex value of #F0E68C. /// - public static readonly TPixel Khaki = ColorBuilder.FromRGBA(240, 230, 140, 255); + public static readonly TPixel Khaki = ColorBuilder.FromRgba(240, 230, 140, 255); /// /// Represents a matching the W3C definition that has an hex value of #E6E6FA. /// - public static readonly TPixel Lavender = ColorBuilder.FromRGBA(230, 230, 250, 255); + public static readonly TPixel Lavender = ColorBuilder.FromRgba(230, 230, 250, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFF0F5. /// - public static readonly TPixel LavenderBlush = ColorBuilder.FromRGBA(255, 240, 245, 255); + public static readonly TPixel LavenderBlush = ColorBuilder.FromRgba(255, 240, 245, 255); /// /// Represents a matching the W3C definition that has an hex value of #7CFC00. /// - public static readonly TPixel LawnGreen = ColorBuilder.FromRGBA(124, 252, 0, 255); + public static readonly TPixel LawnGreen = ColorBuilder.FromRgba(124, 252, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFFACD. /// - public static readonly TPixel LemonChiffon = ColorBuilder.FromRGBA(255, 250, 205, 255); + public static readonly TPixel LemonChiffon = ColorBuilder.FromRgba(255, 250, 205, 255); /// /// Represents a matching the W3C definition that has an hex value of #ADD8E6. /// - public static readonly TPixel LightBlue = ColorBuilder.FromRGBA(173, 216, 230, 255); + public static readonly TPixel LightBlue = ColorBuilder.FromRgba(173, 216, 230, 255); /// /// Represents a matching the W3C definition that has an hex value of #F08080. /// - public static readonly TPixel LightCoral = ColorBuilder.FromRGBA(240, 128, 128, 255); + public static readonly TPixel LightCoral = ColorBuilder.FromRgba(240, 128, 128, 255); /// /// Represents a matching the W3C definition that has an hex value of #E0FFFF. /// - public static readonly TPixel LightCyan = ColorBuilder.FromRGBA(224, 255, 255, 255); + public static readonly TPixel LightCyan = ColorBuilder.FromRgba(224, 255, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #FAFAD2. /// - public static readonly TPixel LightGoldenrodYellow = ColorBuilder.FromRGBA(250, 250, 210, 255); + public static readonly TPixel LightGoldenrodYellow = ColorBuilder.FromRgba(250, 250, 210, 255); /// /// Represents a matching the W3C definition that has an hex value of #D3D3D3. /// - public static readonly TPixel LightGray = ColorBuilder.FromRGBA(211, 211, 211, 255); + public static readonly TPixel LightGray = ColorBuilder.FromRgba(211, 211, 211, 255); /// /// Represents a matching the W3C definition that has an hex value of #90EE90. /// - public static readonly TPixel LightGreen = ColorBuilder.FromRGBA(144, 238, 144, 255); + public static readonly TPixel LightGreen = ColorBuilder.FromRgba(144, 238, 144, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFB6C1. /// - public static readonly TPixel LightPink = ColorBuilder.FromRGBA(255, 182, 193, 255); + public static readonly TPixel LightPink = ColorBuilder.FromRgba(255, 182, 193, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFA07A. /// - public static readonly TPixel LightSalmon = ColorBuilder.FromRGBA(255, 160, 122, 255); + public static readonly TPixel LightSalmon = ColorBuilder.FromRgba(255, 160, 122, 255); /// /// Represents a matching the W3C definition that has an hex value of #20B2AA. /// - public static readonly TPixel LightSeaGreen = ColorBuilder.FromRGBA(32, 178, 170, 255); + public static readonly TPixel LightSeaGreen = ColorBuilder.FromRgba(32, 178, 170, 255); /// /// Represents a matching the W3C definition that has an hex value of #87CEFA. /// - public static readonly TPixel LightSkyBlue = ColorBuilder.FromRGBA(135, 206, 250, 255); + public static readonly TPixel LightSkyBlue = ColorBuilder.FromRgba(135, 206, 250, 255); /// /// Represents a matching the W3C definition that has an hex value of #778899. /// - public static readonly TPixel LightSlateGray = ColorBuilder.FromRGBA(119, 136, 153, 255); + public static readonly TPixel LightSlateGray = ColorBuilder.FromRgba(119, 136, 153, 255); /// /// Represents a matching the W3C definition that has an hex value of #B0C4DE. /// - public static readonly TPixel LightSteelBlue = ColorBuilder.FromRGBA(176, 196, 222, 255); + public static readonly TPixel LightSteelBlue = ColorBuilder.FromRgba(176, 196, 222, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFFFE0. /// - public static readonly TPixel LightYellow = ColorBuilder.FromRGBA(255, 255, 224, 255); + public static readonly TPixel LightYellow = ColorBuilder.FromRgba(255, 255, 224, 255); /// /// Represents a matching the W3C definition that has an hex value of #00FF00. /// - public static readonly TPixel Lime = ColorBuilder.FromRGBA(0, 255, 0, 255); + public static readonly TPixel Lime = ColorBuilder.FromRgba(0, 255, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #32CD32. /// - public static readonly TPixel LimeGreen = ColorBuilder.FromRGBA(50, 205, 50, 255); + public static readonly TPixel LimeGreen = ColorBuilder.FromRgba(50, 205, 50, 255); /// /// Represents a matching the W3C definition that has an hex value of #FAF0E6. /// - public static readonly TPixel Linen = ColorBuilder.FromRGBA(250, 240, 230, 255); + public static readonly TPixel Linen = ColorBuilder.FromRgba(250, 240, 230, 255); /// /// Represents a matching the W3C definition that has an hex value of #FF00FF. /// - public static readonly TPixel Magenta = ColorBuilder.FromRGBA(255, 0, 255, 255); + public static readonly TPixel Magenta = ColorBuilder.FromRgba(255, 0, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #800000. /// - public static readonly TPixel Maroon = ColorBuilder.FromRGBA(128, 0, 0, 255); + public static readonly TPixel Maroon = ColorBuilder.FromRgba(128, 0, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #66CDAA. /// - public static readonly TPixel MediumAquamarine = ColorBuilder.FromRGBA(102, 205, 170, 255); + public static readonly TPixel MediumAquamarine = ColorBuilder.FromRgba(102, 205, 170, 255); /// /// Represents a matching the W3C definition that has an hex value of #0000CD. /// - public static readonly TPixel MediumBlue = ColorBuilder.FromRGBA(0, 0, 205, 255); + public static readonly TPixel MediumBlue = ColorBuilder.FromRgba(0, 0, 205, 255); /// /// Represents a matching the W3C definition that has an hex value of #BA55D3. /// - public static readonly TPixel MediumOrchid = ColorBuilder.FromRGBA(186, 85, 211, 255); + public static readonly TPixel MediumOrchid = ColorBuilder.FromRgba(186, 85, 211, 255); /// /// Represents a matching the W3C definition that has an hex value of #9370DB. /// - public static readonly TPixel MediumPurple = ColorBuilder.FromRGBA(147, 112, 219, 255); + public static readonly TPixel MediumPurple = ColorBuilder.FromRgba(147, 112, 219, 255); /// /// Represents a matching the W3C definition that has an hex value of #3CB371. /// - public static readonly TPixel MediumSeaGreen = ColorBuilder.FromRGBA(60, 179, 113, 255); + public static readonly TPixel MediumSeaGreen = ColorBuilder.FromRgba(60, 179, 113, 255); /// /// Represents a matching the W3C definition that has an hex value of #7B68EE. /// - public static readonly TPixel MediumSlateBlue = ColorBuilder.FromRGBA(123, 104, 238, 255); + public static readonly TPixel MediumSlateBlue = ColorBuilder.FromRgba(123, 104, 238, 255); /// /// Represents a matching the W3C definition that has an hex value of #00FA9A. /// - public static readonly TPixel MediumSpringGreen = ColorBuilder.FromRGBA(0, 250, 154, 255); + public static readonly TPixel MediumSpringGreen = ColorBuilder.FromRgba(0, 250, 154, 255); /// /// Represents a matching the W3C definition that has an hex value of #48D1CC. /// - public static readonly TPixel MediumTurquoise = ColorBuilder.FromRGBA(72, 209, 204, 255); + public static readonly TPixel MediumTurquoise = ColorBuilder.FromRgba(72, 209, 204, 255); /// /// Represents a matching the W3C definition that has an hex value of #C71585. /// - public static readonly TPixel MediumVioletRed = ColorBuilder.FromRGBA(199, 21, 133, 255); + public static readonly TPixel MediumVioletRed = ColorBuilder.FromRgba(199, 21, 133, 255); /// /// Represents a matching the W3C definition that has an hex value of #191970. /// - public static readonly TPixel MidnightBlue = ColorBuilder.FromRGBA(25, 25, 112, 255); + public static readonly TPixel MidnightBlue = ColorBuilder.FromRgba(25, 25, 112, 255); /// /// Represents a matching the W3C definition that has an hex value of #F5FFFA. /// - public static readonly TPixel MintCream = ColorBuilder.FromRGBA(245, 255, 250, 255); + public static readonly TPixel MintCream = ColorBuilder.FromRgba(245, 255, 250, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFE4E1. /// - public static readonly TPixel MistyRose = ColorBuilder.FromRGBA(255, 228, 225, 255); + public static readonly TPixel MistyRose = ColorBuilder.FromRgba(255, 228, 225, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFE4B5. /// - public static readonly TPixel Moccasin = ColorBuilder.FromRGBA(255, 228, 181, 255); + public static readonly TPixel Moccasin = ColorBuilder.FromRgba(255, 228, 181, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFDEAD. /// - public static readonly TPixel NavajoWhite = ColorBuilder.FromRGBA(255, 222, 173, 255); + public static readonly TPixel NavajoWhite = ColorBuilder.FromRgba(255, 222, 173, 255); /// /// Represents a matching the W3C definition that has an hex value of #000080. /// - public static readonly TPixel Navy = ColorBuilder.FromRGBA(0, 0, 128, 255); + public static readonly TPixel Navy = ColorBuilder.FromRgba(0, 0, 128, 255); /// /// Represents a matching the W3C definition that has an hex value of #FDF5E6. /// - public static readonly TPixel OldLace = ColorBuilder.FromRGBA(253, 245, 230, 255); + public static readonly TPixel OldLace = ColorBuilder.FromRgba(253, 245, 230, 255); /// /// Represents a matching the W3C definition that has an hex value of #808000. /// - public static readonly TPixel Olive = ColorBuilder.FromRGBA(128, 128, 0, 255); + public static readonly TPixel Olive = ColorBuilder.FromRgba(128, 128, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #6B8E23. /// - public static readonly TPixel OliveDrab = ColorBuilder.FromRGBA(107, 142, 35, 255); + public static readonly TPixel OliveDrab = ColorBuilder.FromRgba(107, 142, 35, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFA500. /// - public static readonly TPixel Orange = ColorBuilder.FromRGBA(255, 165, 0, 255); + public static readonly TPixel Orange = ColorBuilder.FromRgba(255, 165, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #FF4500. /// - public static readonly TPixel OrangeRed = ColorBuilder.FromRGBA(255, 69, 0, 255); + public static readonly TPixel OrangeRed = ColorBuilder.FromRgba(255, 69, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #DA70D6. /// - public static readonly TPixel Orchid = ColorBuilder.FromRGBA(218, 112, 214, 255); + public static readonly TPixel Orchid = ColorBuilder.FromRgba(218, 112, 214, 255); /// /// Represents a matching the W3C definition that has an hex value of #EEE8AA. /// - public static readonly TPixel PaleGoldenrod = ColorBuilder.FromRGBA(238, 232, 170, 255); + public static readonly TPixel PaleGoldenrod = ColorBuilder.FromRgba(238, 232, 170, 255); /// /// Represents a matching the W3C definition that has an hex value of #98FB98. /// - public static readonly TPixel PaleGreen = ColorBuilder.FromRGBA(152, 251, 152, 255); + public static readonly TPixel PaleGreen = ColorBuilder.FromRgba(152, 251, 152, 255); /// /// Represents a matching the W3C definition that has an hex value of #AFEEEE. /// - public static readonly TPixel PaleTurquoise = ColorBuilder.FromRGBA(175, 238, 238, 255); + public static readonly TPixel PaleTurquoise = ColorBuilder.FromRgba(175, 238, 238, 255); /// /// Represents a matching the W3C definition that has an hex value of #DB7093. /// - public static readonly TPixel PaleVioletRed = ColorBuilder.FromRGBA(219, 112, 147, 255); + public static readonly TPixel PaleVioletRed = ColorBuilder.FromRgba(219, 112, 147, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFEFD5. /// - public static readonly TPixel PapayaWhip = ColorBuilder.FromRGBA(255, 239, 213, 255); + public static readonly TPixel PapayaWhip = ColorBuilder.FromRgba(255, 239, 213, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFDAB9. /// - public static readonly TPixel PeachPuff = ColorBuilder.FromRGBA(255, 218, 185, 255); + public static readonly TPixel PeachPuff = ColorBuilder.FromRgba(255, 218, 185, 255); /// /// Represents a matching the W3C definition that has an hex value of #CD853F. /// - public static readonly TPixel Peru = ColorBuilder.FromRGBA(205, 133, 63, 255); + public static readonly TPixel Peru = ColorBuilder.FromRgba(205, 133, 63, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFC0CB. /// - public static readonly TPixel Pink = ColorBuilder.FromRGBA(255, 192, 203, 255); + public static readonly TPixel Pink = ColorBuilder.FromRgba(255, 192, 203, 255); /// /// Represents a matching the W3C definition that has an hex value of #DDA0DD. /// - public static readonly TPixel Plum = ColorBuilder.FromRGBA(221, 160, 221, 255); + public static readonly TPixel Plum = ColorBuilder.FromRgba(221, 160, 221, 255); /// /// Represents a matching the W3C definition that has an hex value of #B0E0E6. /// - public static readonly TPixel PowderBlue = ColorBuilder.FromRGBA(176, 224, 230, 255); + public static readonly TPixel PowderBlue = ColorBuilder.FromRgba(176, 224, 230, 255); /// /// Represents a matching the W3C definition that has an hex value of #800080. /// - public static readonly TPixel Purple = ColorBuilder.FromRGBA(128, 0, 128, 255); + public static readonly TPixel Purple = ColorBuilder.FromRgba(128, 0, 128, 255); /// /// Represents a matching the W3C definition that has an hex value of #663399. /// - public static readonly TPixel RebeccaPurple = ColorBuilder.FromRGBA(102, 51, 153, 255); + public static readonly TPixel RebeccaPurple = ColorBuilder.FromRgba(102, 51, 153, 255); /// /// Represents a matching the W3C definition that has an hex value of #FF0000. /// - public static readonly TPixel Red = ColorBuilder.FromRGBA(255, 0, 0, 255); + public static readonly TPixel Red = ColorBuilder.FromRgba(255, 0, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #BC8F8F. /// - public static readonly TPixel RosyBrown = ColorBuilder.FromRGBA(188, 143, 143, 255); + public static readonly TPixel RosyBrown = ColorBuilder.FromRgba(188, 143, 143, 255); /// /// Represents a matching the W3C definition that has an hex value of #4169E1. /// - public static readonly TPixel RoyalBlue = ColorBuilder.FromRGBA(65, 105, 225, 255); + public static readonly TPixel RoyalBlue = ColorBuilder.FromRgba(65, 105, 225, 255); /// /// Represents a matching the W3C definition that has an hex value of #8B4513. /// - public static readonly TPixel SaddleBrown = ColorBuilder.FromRGBA(139, 69, 19, 255); + public static readonly TPixel SaddleBrown = ColorBuilder.FromRgba(139, 69, 19, 255); /// /// Represents a matching the W3C definition that has an hex value of #FA8072. /// - public static readonly TPixel Salmon = ColorBuilder.FromRGBA(250, 128, 114, 255); + public static readonly TPixel Salmon = ColorBuilder.FromRgba(250, 128, 114, 255); /// /// Represents a matching the W3C definition that has an hex value of #F4A460. /// - public static readonly TPixel SandyBrown = ColorBuilder.FromRGBA(244, 164, 96, 255); + public static readonly TPixel SandyBrown = ColorBuilder.FromRgba(244, 164, 96, 255); /// /// Represents a matching the W3C definition that has an hex value of #2E8B57. /// - public static readonly TPixel SeaGreen = ColorBuilder.FromRGBA(46, 139, 87, 255); + public static readonly TPixel SeaGreen = ColorBuilder.FromRgba(46, 139, 87, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFF5EE. /// - public static readonly TPixel SeaShell = ColorBuilder.FromRGBA(255, 245, 238, 255); + public static readonly TPixel SeaShell = ColorBuilder.FromRgba(255, 245, 238, 255); /// /// Represents a matching the W3C definition that has an hex value of #A0522D. /// - public static readonly TPixel Sienna = ColorBuilder.FromRGBA(160, 82, 45, 255); + public static readonly TPixel Sienna = ColorBuilder.FromRgba(160, 82, 45, 255); /// /// Represents a matching the W3C definition that has an hex value of #C0C0C0. /// - public static readonly TPixel Silver = ColorBuilder.FromRGBA(192, 192, 192, 255); + public static readonly TPixel Silver = ColorBuilder.FromRgba(192, 192, 192, 255); /// /// Represents a matching the W3C definition that has an hex value of #87CEEB. /// - public static readonly TPixel SkyBlue = ColorBuilder.FromRGBA(135, 206, 235, 255); + public static readonly TPixel SkyBlue = ColorBuilder.FromRgba(135, 206, 235, 255); /// /// Represents a matching the W3C definition that has an hex value of #6A5ACD. /// - public static readonly TPixel SlateBlue = ColorBuilder.FromRGBA(106, 90, 205, 255); + public static readonly TPixel SlateBlue = ColorBuilder.FromRgba(106, 90, 205, 255); /// /// Represents a matching the W3C definition that has an hex value of #708090. /// - public static readonly TPixel SlateGray = ColorBuilder.FromRGBA(112, 128, 144, 255); + public static readonly TPixel SlateGray = ColorBuilder.FromRgba(112, 128, 144, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFFAFA. /// - public static readonly TPixel Snow = ColorBuilder.FromRGBA(255, 250, 250, 255); + public static readonly TPixel Snow = ColorBuilder.FromRgba(255, 250, 250, 255); /// /// Represents a matching the W3C definition that has an hex value of #00FF7F. /// - public static readonly TPixel SpringGreen = ColorBuilder.FromRGBA(0, 255, 127, 255); + public static readonly TPixel SpringGreen = ColorBuilder.FromRgba(0, 255, 127, 255); /// /// Represents a matching the W3C definition that has an hex value of #4682B4. /// - public static readonly TPixel SteelBlue = ColorBuilder.FromRGBA(70, 130, 180, 255); + public static readonly TPixel SteelBlue = ColorBuilder.FromRgba(70, 130, 180, 255); /// /// Represents a matching the W3C definition that has an hex value of #D2B48C. /// - public static readonly TPixel Tan = ColorBuilder.FromRGBA(210, 180, 140, 255); + public static readonly TPixel Tan = ColorBuilder.FromRgba(210, 180, 140, 255); /// /// Represents a matching the W3C definition that has an hex value of #008080. /// - public static readonly TPixel Teal = ColorBuilder.FromRGBA(0, 128, 128, 255); + public static readonly TPixel Teal = ColorBuilder.FromRgba(0, 128, 128, 255); /// /// Represents a matching the W3C definition that has an hex value of #D8BFD8. /// - public static readonly TPixel Thistle = ColorBuilder.FromRGBA(216, 191, 216, 255); + public static readonly TPixel Thistle = ColorBuilder.FromRgba(216, 191, 216, 255); /// /// Represents a matching the W3C definition that has an hex value of #FF6347. /// - public static readonly TPixel Tomato = ColorBuilder.FromRGBA(255, 99, 71, 255); + public static readonly TPixel Tomato = ColorBuilder.FromRgba(255, 99, 71, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFFFFF. /// - public static readonly TPixel Transparent = ColorBuilder.FromRGBA(255, 255, 255, 0); + public static readonly TPixel Transparent = ColorBuilder.FromRgba(255, 255, 255, 0); /// /// Represents a matching the W3C definition that has an hex value of #40E0D0. /// - public static readonly TPixel Turquoise = ColorBuilder.FromRGBA(64, 224, 208, 255); + public static readonly TPixel Turquoise = ColorBuilder.FromRgba(64, 224, 208, 255); /// /// Represents a matching the W3C definition that has an hex value of #EE82EE. /// - public static readonly TPixel Violet = ColorBuilder.FromRGBA(238, 130, 238, 255); + public static readonly TPixel Violet = ColorBuilder.FromRgba(238, 130, 238, 255); /// /// Represents a matching the W3C definition that has an hex value of #F5DEB3. /// - public static readonly TPixel Wheat = ColorBuilder.FromRGBA(245, 222, 179, 255); + public static readonly TPixel Wheat = ColorBuilder.FromRgba(245, 222, 179, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFFFFF. /// - public static readonly TPixel White = ColorBuilder.FromRGBA(255, 255, 255, 255); + public static readonly TPixel White = ColorBuilder.FromRgba(255, 255, 255, 255); /// /// Represents a matching the W3C definition that has an hex value of #F5F5F5. /// - public static readonly TPixel WhiteSmoke = ColorBuilder.FromRGBA(245, 245, 245, 255); + public static readonly TPixel WhiteSmoke = ColorBuilder.FromRgba(245, 245, 245, 255); /// /// Represents a matching the W3C definition that has an hex value of #FFFF00. /// - public static readonly TPixel Yellow = ColorBuilder.FromRGBA(255, 255, 0, 255); + public static readonly TPixel Yellow = ColorBuilder.FromRgba(255, 255, 0, 255); /// /// Represents a matching the W3C definition that has an hex value of #9ACD32. /// - public static readonly TPixel YellowGreen = ColorBuilder.FromRGBA(154, 205, 50, 255); + public static readonly TPixel YellowGreen = ColorBuilder.FromRgba(154, 205, 50, 255); /// /// Gets a collection of web safe, colors as defined in the CSS Color Module Level 4. From 6741c280e3017cdb28199e4a00f977cc8540c06d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 11 May 2019 15:49:58 +0200 Subject: [PATCH 166/223] temporarily disable target frameworks --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 3 ++- src/ImageSharp/ImageSharp.csproj | 3 ++- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 915915f6c..fdeb27a77 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -11,7 +11,8 @@ $(packageversion) 0.0.1 - netcoreapp2.1;netstandard1.3;netstandard2.0 + + netstandard2.0 7.3 true diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index d734648f4..4abe2f57a 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -11,7 +11,8 @@ $(packageversion) 0.0.1 - netcoreapp2.1;netstandard1.3;netstandard2.0;net472 + + netstandard2.0 true true diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 0b727f30c..efdf89964 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,6 +1,7 @@  - netcoreapp2.1;net462;net472 + + netcoreapp2.1 True latest full From 7b8f9ef14f45e95aafb76f52dfe7fcda0e8339f7 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sat, 11 May 2019 16:27:51 +0200 Subject: [PATCH 167/223] Enabled dither again --- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index be82e2cab..8d0e8578d 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -304,7 +304,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp byte[] colorPalette = new byte[ColorPaletteSize8Bit]; #endif - var quantizer = new OctreeQuantizer(dither: false, maxColors: 256); + var quantizer = new OctreeQuantizer(dither: true, maxColors: 256); QuantizedFrame quantized = quantizer.CreateFrameQuantizer(this.configuration).QuantizeFrame(image); int idx = 0; From 7e8357c5392ccff9f7d5b64e15dd61d035e3fac6 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 11 May 2019 17:00:16 +0200 Subject: [PATCH 168/223] validating tests for: DrawPath, FillComplexPolygon --- .../ImageSharp.Tests/Drawing/DrawPathTests.cs | 133 +++++++----------- .../Drawing/FillComplexPolygonTests.cs | 62 ++++++++ ...tternTests.cs => FillPatternBrushTests.cs} | 6 +- .../Drawing/SolidComplexPolygonTests.cs | 109 -------------- .../Processors/Overlays/OverlayTestBase.cs | 3 +- .../TestUtilities/TestUtils.cs | 9 +- tests/Images/External | 2 +- 7 files changed, 125 insertions(+), 199 deletions(-) create mode 100644 tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs rename tests/ImageSharp.Tests/Drawing/{FillPatternTests.cs => FillPatternBrushTests.cs} (98%) delete mode 100644 tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs diff --git a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs index d2485f334..c638107b8 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs @@ -1,112 +1,79 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using SixLabors.Primitives; using SixLabors.Shapes; using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { - public class DrawPathTests : FileTestBase + [GroupOutput("Drawing")] + public class DrawPathTests { - [Fact] - public void ImageShouldBeOverlayedByPath() + public static readonly TheoryData DrawPathData = new TheoryData + { + { "White", 255, 1.5f }, + { "Red", 255, 3 }, + { "HotPink", 255, 5 }, + { "HotPink", 150, 5 }, + { "White", 255, 15 }, + }; + + [Theory] + [WithSolidFilledImages(nameof(DrawPathData), 300, 450, "Blue", PixelTypes.Rgba32)] + public void DrawPath(TestImageProvider provider, string colorName, byte alpha, float thickness) + where TPixel : struct, IPixel { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Path"); - using (var image = new Image(500, 500)) - { - var linerSegemnt = new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300)); - var bazierSegment = new CubicBezierLineSegment( - new Vector2(50, 300), - new Vector2(500, 500), - new Vector2(60, 10), - new Vector2(10, 400)); - - var p = new Path(linerSegemnt, bazierSegment); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(Rgba32.HotPink, 5, p)); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } - } - - - [Fact] - public void ImageShouldBeOverlayedPathWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Path"); - - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - var linerSegemnt = new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - ); - - var bazierSegment = new CubicBezierLineSegment(new Vector2(50, 300), + new Vector2(10, 10), + new Vector2(200, 150), + new Vector2(50, 300)); + var bazierSegment = new CubicBezierLineSegment( + new Vector2(50, 300), new Vector2(500, 500), new Vector2(60, 10), new Vector2(10, 400)); - var p = new Path(linerSegemnt, bazierSegment); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(color, 10, p)); - image.Save($"{path}/Opacity.png"); + var path = new Path(linerSegemnt, bazierSegment); - //shift background color towards forground color by the opacity amount - var mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); + Rgba32 rgba = TestUtils.GetColorByName(colorName); + rgba.A = alpha; + Color color = rgba; - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(mergedColor, sourcePixels[11, 11]); + FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; - Assert.Equal(mergedColor, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } + provider.RunValidatingProcessorTest( + x => x.Draw(color.ToPixel(), thickness, path), + testDetails, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); } - [Fact] - public void PathExtendingOffEdgeOfImageShouldNotBeCropped() + [Theory] + [WithSolidFilledImages(256, 256, "Black", PixelTypes.Rgba32)] + public void PathExtendingOffEdgeOfImageShouldNotBeCropped(TestImageProvider provider) + where TPixel : struct, IPixel { - - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Path"); - using (var image = new Image(256, 256)) - { - image.Mutate(x => x.Fill(Rgba32.Black)); - Pen pen = Pens.Solid(Rgba32.White, 5f); - - for (int i = 0; i < 300; i += 20) - { - image.Mutate( - x => x.DrawLines( - pen, - new SixLabors.Primitives.PointF[] { new Vector2(100, 2), new Vector2(-10, i) })); - } - - image.Save($"{path}/ClippedLines.png"); - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.White, sourcePixels[0, 90]); - } + Color color = Color.White; + Pen pen = Pens.Solid(color.ToPixel(), 5f); + + provider.RunValidatingProcessorTest( + x => + { + for (int i = 0; i < 300; i += 20) + { + PointF[] points = new PointF[] { new Vector2(100, 2), new Vector2(-10, i) }; + x.DrawLines(pen, points); + } + }, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs new file mode 100644 index 000000000..3887cb9a7 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs @@ -0,0 +1,62 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Shapes; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class FillComplexPolygonTests + { + [Theory] + [WithSolidFilledImages(300, 400, "Blue", PixelTypes.Rgba32, false, false)] + [WithSolidFilledImages(300, 400, "Blue", PixelTypes.Rgba32, true, false)] + [WithSolidFilledImages(300, 400, "Blue", PixelTypes.Rgba32, false, true)] + public void ComplexPolygon_SolidFill(TestImageProvider provider, bool overlap, bool transparent) + where TPixel :struct, IPixel + { + var simplePath = new Polygon(new LinearLineSegment( + new Vector2(10, 10), + new Vector2(200, 150), + new Vector2(50, 300))); + + var hole1 = new Polygon(new LinearLineSegment( + new Vector2(37, 85), + overlap ? new Vector2(130, 40) : new Vector2(93, 85), + new Vector2(65, 137))); + IPath clipped = simplePath.Clip(hole1); + + Rgba32 colorRgba = Rgba32.HotPink; + if (transparent) + { + colorRgba.A = 150; + } + + Color color = colorRgba; + + string testDetails = ""; + if (overlap) + { + testDetails += "_Overlap"; + } + + if (transparent) + { + testDetails += "_Transparent"; + } + + provider.RunValidatingProcessorTest( + x => x.Fill(color.ToPixel(), clipped), + testDetails, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + } +} diff --git a/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs b/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs similarity index 98% rename from tests/ImageSharp.Tests/Drawing/FillPatternTests.cs rename to tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs index b310c7afc..dcc689fe1 100644 --- a/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs @@ -12,11 +12,11 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { - public class FillPatternBrushTests : FileTestBase + public class FillPatternBrushTests { private void Test(string name, Rgba32 background, IBrush brush, Rgba32[,] expectedPattern) { - string path = TestEnvironment.CreateOutputDirectory("Fill", "PatternBrush"); + string path = TestEnvironment.CreateOutputDirectory("Drawing", "FillPatternBrushTests"); using (var image = new Image(20, 20)) { image.Mutate(x => x.Fill(background).Fill(brush)); @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing } } - image.Mutate(x => x.Resize(80, 80)); + image.Mutate(x => x.Resize(80, 80, KnownResamplers.NearestNeighbor)); image.Save($"{path}/{name}x4.png"); } } diff --git a/tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs deleted file mode 100644 index 0e997ad7e..000000000 --- a/tests/ImageSharp.Tests/Drawing/SolidComplexPolygonTests.cs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class SolidComplexPolygonTests : FileTestBase - { - [Fact] - public void ImageShouldBeOverlayedByPolygonOutline() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "ComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(93, 85), - new Vector2(65, 137))); - IPath clipped = simplePath.Clip(hole1); - // var clipped = new Rectangle(10, 10, 100, 100).Clip(new Rectangle(20, 0, 20, 20)); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Fill(Rgba32.HotPink, clipped)); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[20, 35]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[60, 100]); - } - } - - - [Fact] - public void ImageShouldBeOverlayedPolygonOutlineWithOverlap() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "ComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(130, 40), - new Vector2(65, 137))); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Fill(Rgba32.HotPink, simplePath.Clip(hole1))); - image.Save($"{path}/SimpleOverlapping.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[20, 35]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[60, 100]); - } - } - - [Fact] - public void ImageShouldBeOverlayedPolygonOutlineWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "ComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(93, 85), - new Vector2(65, 137))); - - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Fill(color, simplePath.Clip(hole1))); - image.Save($"{path}/Opacity.png"); - - //shift background color towards forground color by the opacity amount - var mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(mergedColor, sourcePixels[20, 35]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[60, 100]); - } - } - } -} diff --git a/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs b/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs index 788f7e1ad..eaad82f9a 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs @@ -27,8 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays where TPixel : struct, IPixel { provider.Utility.TestGroupName = this.GetType().Name; - var f = (FieldInfo)typeof(Color).GetMember(colorName)[0]; - Color color = (Color)f.GetValue(null); + Color color = TestUtils.GetColorByName(colorName); provider.RunValidatingProcessorTest(x => this.Apply(x, color), colorName, ValidatorComparer, appendPixelTypeToFileName: false); } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs index e51aa28d8..5db0c0828 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs @@ -141,8 +141,15 @@ namespace SixLabors.ImageSharp.Tests /// The pixel types internal static PixelTypes[] GetAllPixelTypes() => (PixelTypes[])Enum.GetValues(typeof(PixelTypes)); + internal static Color GetColorByName(string colorName) + { + var f = (FieldInfo)typeof(Color).GetMember(colorName)[0]; + return (Color)f.GetValue(null); + } + internal static TPixel GetPixelOfNamedColor(string colorName) - where TPixel : struct, IPixel => (TPixel)typeof(NamedColors).GetTypeInfo().GetField(colorName).GetValue(null); + where TPixel : struct, IPixel => + GetColorByName(colorName).ToPixel(); /// /// Utility for testing image processor extension methods: diff --git a/tests/Images/External b/tests/Images/External index c057090b4..d83843dee 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit c057090b4402120a83a8efe251aa5b691db9c0dc +Subproject commit d83843deedc43712f29f631aab090640b4f54946 From cf8005deb2ba98063af51414009f7e4aca2edc32 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 11 May 2019 23:53:27 +0200 Subject: [PATCH 169/223] validation in DrawImageTest --- .../ImageSharp.Tests/Drawing/DrawImageTest.cs | 198 ------------------ .../Drawing/DrawImageTests.cs | 174 +++++++++++++++ .../TestUtilities/TestImageExtensions.cs | 25 ++- tests/Images/External | 2 +- 4 files changed, 192 insertions(+), 207 deletions(-) delete mode 100644 tests/ImageSharp.Tests/Drawing/DrawImageTest.cs create mode 100644 tests/ImageSharp.Tests/Drawing/DrawImageTests.cs diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs deleted file mode 100644 index 54b04390e..000000000 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; -using SixLabors.Primitives; -using Xunit; - -namespace SixLabors.ImageSharp.Tests -{ - [GroupOutput("Drawing")] - public class DrawImageTest : FileTestBase - { - private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32; - - public static readonly string[] TestFiles = { - TestImages.Jpeg.Baseline.Calliphora, - TestImages.Bmp.Car, - TestImages.Png.Splash, - TestImages.Gif.Rings - }; - - [Theory] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Normal)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Multiply)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Add)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Subtract)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Screen)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Darken)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Lighten)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Overlay)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.HardLight)] - public void ImageShouldApplyDrawImage(TestImageProvider provider, PixelColorBlendingMode mode) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - using (var blend = Image.Load(TestFile.Create(TestImages.Bmp.Car).Bytes)) - { - blend.Mutate(x => x.Resize(image.Width / 2, image.Height / 2)); - image.Mutate(x => x.DrawImage(blend, new Point(image.Width / 4, image.Height / 4), mode, .75f)); - image.DebugSave(provider, new { mode }); - } - } - - [Theory] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Normal)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Multiply)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Add)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Subtract)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Screen)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Darken)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Lighten)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Overlay)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.HardLight)] - public void ImageBlendingMatchesSvgSpecExamples(TestImageProvider provider, PixelColorBlendingMode mode) - where TPixel : struct, IPixel - { - using (Image background = provider.GetImage()) - using (var source = Image.Load(TestFile.Create(TestImages.Png.Ducky).Bytes)) - { - background.Mutate(x => x.DrawImage(source, mode, 1F)); - VerifyImage(provider, mode, background); - } - } - - [Theory] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Normal)] - public void ImageShouldDrawTransformedImage(TestImageProvider provider, PixelColorBlendingMode mode) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - using (var blend = Image.Load(TestFile.Create(TestImages.Bmp.Car).Bytes)) - { - AffineTransformBuilder builder = new AffineTransformBuilder() - .AppendRotationDegrees(45F) - .AppendScale(new SizeF(.25F, .25F)) - .AppendTranslation(new PointF(10, 10)); - - // Apply a background color so we can see the translation. - blend.Mutate(x => x.Transform(builder)); - blend.Mutate(x => x.BackgroundColor(Color.HotPink)); - - // Lets center the matrix so we can tell whether any cut-off issues we may have belong to the drawing processor - var position = new Point((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); - image.Mutate(x => x.DrawImage(blend, position, mode, .75F)); - image.DebugSave(provider, new[] { "Transformed" }); - } - } - - [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] - public void ImageShouldHandleNegativeLocation(TestImageProvider provider) - { - using (Image background = provider.GetImage()) - using (var overlay = new Image(50, 50)) - { - overlay.Mutate(x => x.Fill(Rgba32.Black)); - - const int xy = -25; - Rgba32 backgroundPixel = background[0, 0]; - Rgba32 overlayPixel = overlay[Math.Abs(xy) + 1, Math.Abs(xy) + 1]; - - background.Mutate(x => x.DrawImage(overlay, new Point(xy, xy), PixelColorBlendingMode.Normal, 1F)); - - Assert.Equal(Rgba32.White, backgroundPixel); - Assert.Equal(overlayPixel, background[0, 0]); - - background.DebugSave(provider, testOutputDetails: "Negative"); - } - } - - [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] - public void ImageShouldHandlePositiveLocation(TestImageProvider provider) - { - using (Image background = provider.GetImage()) - using (var overlay = new Image(50, 50)) - { - overlay.Mutate(x => x.Fill(Rgba32.Black)); - - const int xy = 25; - Rgba32 backgroundPixel = background[xy - 1, xy - 1]; - Rgba32 overlayPixel = overlay[0, 0]; - - background.Mutate(x => x.DrawImage(overlay, new Point(xy, xy), PixelColorBlendingMode.Normal, 1F)); - - Assert.Equal(Rgba32.White, backgroundPixel); - Assert.Equal(overlayPixel, background[xy, xy]); - - background.DebugSave(provider, testOutputDetails: "Positive"); - } - } - [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] - public void ImageShouldHandlePositiveLocationTruncatedOverlay(TestImageProvider provider) - { - using (Image background = provider.GetImage()) - using (var overlay = new Image(50, 50)) - { - overlay.Mutate(x => x.Fill(Rgba32.Black)); - - const int xy = 75; - Rgba32 backgroundPixel = background[xy - 1, xy - 1]; - Rgba32 overlayPixel = overlay[0, 0]; - - background.Mutate(x => x.DrawImage(overlay, new Point(xy, xy), PixelColorBlendingMode.Normal, 1F)); - - Assert.Equal(Rgba32.White, backgroundPixel); - Assert.Equal(overlayPixel, background[xy, xy]); - - background.DebugSave(provider, testOutputDetails: "PositiveTruncated"); - } - } - - [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, -30)] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, -30)] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, 130)] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, 130)] - public void NonOverlappingImageThrows(TestImageProvider provider, int x, int y) - { - using (Image background = provider.GetImage()) - using (var overlay = new Image(Configuration.Default, 10, 10, Rgba32.Black)) - { - ImageProcessingException ex = Assert.Throws(Test); - - Assert.Contains("does not overlap", ex.ToString()); - - void Test() - { - background.Mutate(context => context.DrawImage(overlay, new Point(x, y), GraphicsOptions.Default)); - } - } - } - - private static void VerifyImage( - TestImageProvider provider, - PixelColorBlendingMode mode, - Image img) - where TPixel : struct, IPixel - { - img.DebugSave( - provider, - new { mode }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - - var comparer = ImageComparer.TolerantPercentage(0.01F, 3); - img.CompareFirstFrameToReferenceOutput(comparer, - provider, - new { mode }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs new file mode 100644 index 000000000..f4e9b7b45 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -0,0 +1,174 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.Primitives; +using SixLabors.Shapes; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class DrawImageTests + { + public static readonly TheoryData BlendingModes = new TheoryData + { + PixelColorBlendingMode.Normal, + PixelColorBlendingMode.Multiply, + PixelColorBlendingMode.Add, + PixelColorBlendingMode.Subtract, + PixelColorBlendingMode.Screen, + PixelColorBlendingMode.Darken, + PixelColorBlendingMode.Lighten, + PixelColorBlendingMode.Overlay, + PixelColorBlendingMode.HardLight, + }; + + [Theory] + [WithFile( TestImages.Png.Rainbow,nameof(BlendingModes), PixelTypes.Rgba32)] + public void ImageBlendingMatchesSvgSpecExamples(TestImageProvider provider, PixelColorBlendingMode mode) + where TPixel : struct, IPixel + { + using (Image background = provider.GetImage()) + using (var source = Image.Load(TestFile.Create(TestImages.Png.Ducky).Bytes)) + { + background.Mutate(x => x.DrawImage(source, mode, 1F)); + background.DebugSave( + provider, + new { mode = mode }, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + + var comparer = ImageComparer.TolerantPercentage(0.01F); + background.CompareToReferenceOutput(comparer, + provider, + new { mode = mode }, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + } + + [Theory] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 1f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Bgr24, TestImages.Png.Bike, PixelColorBlendingMode.Normal, 1f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 0.75f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 0.25f)] + + [WithTestPatternImages(400, 400, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Multiply, 0.5f)] + [WithTestPatternImages(400, 400, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Add, 0.5f)] + [WithTestPatternImages(400, 400, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Subtract, 0.5f)] + + [WithFile(TestImages.Png.Rgb48Bpp, PixelTypes.Rgba64, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 1f)] + [WithFile(TestImages.Png.Rgb48Bpp, PixelTypes.Rgba64, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 0.25f)] + public void WorksWithDifferentConfigurations( + TestImageProvider provider, + string brushImage, + PixelColorBlendingMode mode, + float opacity) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + using (var blend = Image.Load(TestFile.Create(brushImage).Bytes)) + { + Size size = new Size(image.Width * 3 / 4, image.Height *3/ 4); + Point position = new Point(image.Width / 8, image.Height / 8); + blend.Mutate(x => x.Resize(size.Width, size.Height, KnownResamplers.Bicubic)); + image.Mutate(x => x.DrawImage(blend, position, mode, opacity)); + FormattableString testInfo = $"{System.IO.Path.GetFileNameWithoutExtension(brushImage)}-{mode}-{opacity}"; + + PngEncoder encoder = new PngEncoder(); + + if (provider.PixelType == PixelTypes.Rgba64) + { + encoder.BitDepth = PngBitDepth.Bit16; + } + + image.DebugSave(provider, testInfo, encoder: encoder); + image.CompareToReferenceOutput(provider, testInfo); + } + } + + + [Theory] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 0, 0)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 25, 25)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 75, 50)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, -25, -30)] + public void WorksWithDifferentLocations(TestImageProvider provider, int x, int y) + { + using (Image background = provider.GetImage()) + using (var overlay = new Image(50, 50)) + { + overlay.Mutate(c => c.Fill(Rgba32.Black)); + + background.Mutate(c => c.DrawImage(overlay, new Point(x, y), PixelColorBlendingMode.Normal, 1F)); + + background.DebugSave( + provider, + testOutputDetails: $"{x}_{y}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + + background.CompareToReferenceOutput( + provider, + testOutputDetails: $"{x}_{y}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + } + + [Theory] + [WithFile(TestImages.Png.Splash, PixelTypes.Rgba32)] + public void DrawTransformed(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + using (var blend = Image.Load(TestFile.Create(TestImages.Bmp.Car).Bytes)) + { + AffineTransformBuilder builder = new AffineTransformBuilder() + .AppendRotationDegrees(45F) + .AppendScale(new SizeF(.25F, .25F)) + .AppendTranslation(new PointF(10, 10)); + + // Apply a background color so we can see the translation. + blend.Mutate(x => x.Transform(builder)); + blend.Mutate(x => x.BackgroundColor(Color.HotPink)); + + // Lets center the matrix so we can tell whether any cut-off issues we may have belong to the drawing processor + var position = new Point((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); + image.Mutate(x => x.DrawImage(blend, position, .75F)); + + image.DebugSave(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); + image.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); + } + } + + [Theory] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, -30)] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, -30)] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, 130, 130)] + [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32, -30, 130)] + public void NonOverlappingImageThrows(TestImageProvider provider, int x, int y) + { + using (Image background = provider.GetImage()) + using (var overlay = new Image(Configuration.Default, 10, 10, Rgba32.Black)) + { + ImageProcessingException ex = Assert.Throws(Test); + + Assert.Contains("does not overlap", ex.ToString()); + + void Test() + { + background.Mutate(context => context.DrawImage(overlay, new Point(x, y), GraphicsOptions.Default)); + } + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 6ca3ed6f9..c5aa1fb94 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -61,7 +61,8 @@ namespace SixLabors.ImageSharp.Tests FormattableString testOutputDetails, string extension = "png", bool appendPixelTypeToFileName = true, - bool appendSourceFileOrDescription = true) + bool appendSourceFileOrDescription = true, + IImageEncoder encoder = null) where TPixel : struct, IPixel { return image.DebugSave( @@ -69,7 +70,8 @@ namespace SixLabors.ImageSharp.Tests (object)testOutputDetails, extension, appendPixelTypeToFileName, - appendSourceFileOrDescription); + appendSourceFileOrDescription, + encoder); } /// @@ -82,13 +84,15 @@ namespace SixLabors.ImageSharp.Tests /// The extension /// A boolean indicating whether to append the pixel type to the output file name. /// A boolean indicating whether to append to the test output file name. + /// Custom encoder to use. public static Image DebugSave( this Image image, ITestImageProvider provider, object testOutputDetails = null, string extension = "png", bool appendPixelTypeToFileName = true, - bool appendSourceFileOrDescription = true) + bool appendSourceFileOrDescription = true, + IImageEncoder encoder = null) where TPixel : struct, IPixel { if (TestEnvironment.RunsOnCI) @@ -102,7 +106,8 @@ namespace SixLabors.ImageSharp.Tests extension, testOutputDetails: testOutputDetails, appendPixelTypeToFileName: appendPixelTypeToFileName, - appendSourceFileOrDescription: appendSourceFileOrDescription); + appendSourceFileOrDescription: appendSourceFileOrDescription, + encoder: encoder); return image; } @@ -255,6 +260,7 @@ namespace SixLabors.ImageSharp.Tests /// A boolean indicating whether we should debug save + compare against a grayscale image, smaller in size. /// A boolean indicating whether to append the pixel type to the output file name. /// A boolean indicating whether to append to the test output file name. + /// A custom decoder. /// public static Image CompareToReferenceOutput( this Image image, @@ -264,7 +270,8 @@ namespace SixLabors.ImageSharp.Tests string extension = "png", bool grayscale = false, bool appendPixelTypeToFileName = true, - bool appendSourceFileOrDescription = true) + bool appendSourceFileOrDescription = true, + IImageDecoder decoder = null) where TPixel : struct, IPixel { using (Image referenceImage = GetReferenceOutputImage( @@ -272,7 +279,8 @@ namespace SixLabors.ImageSharp.Tests testOutputDetails, extension, appendPixelTypeToFileName, - appendSourceFileOrDescription)) + appendSourceFileOrDescription, + decoder)) { comparer.VerifySimilarity(referenceImage, image); } @@ -356,7 +364,8 @@ namespace SixLabors.ImageSharp.Tests object testOutputDetails = null, string extension = "png", bool appendPixelTypeToFileName = true, - bool appendSourceFileOrDescription = true) + bool appendSourceFileOrDescription = true, + IImageDecoder decoder = null) where TPixel : struct, IPixel { string referenceOutputFile = provider.Utility.GetReferenceOutputFileName( @@ -370,7 +379,7 @@ namespace SixLabors.ImageSharp.Tests throw new System.IO.FileNotFoundException("Reference output file missing: " + referenceOutputFile, referenceOutputFile); } - IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(referenceOutputFile); + decoder = decoder ?? TestEnvironment.GetReferenceDecoder(referenceOutputFile); return Image.Load(referenceOutputFile, decoder); } diff --git a/tests/Images/External b/tests/Images/External index d83843dee..dc5afda9a 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit d83843deedc43712f29f631aab090640b4f54946 +Subproject commit dc5afda9a4ad69dc3526d49ceb1d27610064f2af From 5ab0ad2dffb202dd802b88c89b3c44af3c8ac1a8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 00:52:35 +0200 Subject: [PATCH 170/223] RecolorImageTests --- .../{BeziersTests.cs => DrawBezierTests.cs} | 10 ++-- .../Drawing/RecolorImageTest.cs | 48 ----------------- .../Drawing/RecolorImageTests.cs | 51 +++++++++++++++++++ tests/Images/External | 2 +- 4 files changed, 57 insertions(+), 54 deletions(-) rename tests/ImageSharp.Tests/Drawing/{BeziersTests.cs => DrawBezierTests.cs} (93%) delete mode 100644 tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs create mode 100644 tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs diff --git a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs similarity index 93% rename from tests/ImageSharp.Tests/Drawing/BeziersTests.cs rename to tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs index cc8f27f3a..d82221ca6 100644 --- a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs @@ -11,13 +11,13 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { - public class Beziers : FileTestBase + public class DrawBezierTests { [Fact] public void ImageShouldBeOverlayedByBezierLine() { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "BezierLine"); - using (var image = new Image(500, 500)) + string path = TestEnvironment.CreateOutputDirectory("Drawing", "DrawBezierTests"); + using (var image = new Image(350, 450)) { image.Mutate(x => x.BackgroundColor(Color.Blue)); image.Mutate( @@ -51,11 +51,11 @@ namespace SixLabors.ImageSharp.Tests.Drawing [Fact] public void ImageShouldBeOverlayedBezierLineWithOpacity() { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "BezierLine"); + string path = TestEnvironment.CreateOutputDirectory("Drawing", "DrawBezierTests"); var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - using (var image = new Image(500, 500)) + using (var image = new Image(350, 450)) { image.Mutate(x => x.BackgroundColor(Color.Blue)); image.Mutate( diff --git a/tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs b/tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs deleted file mode 100644 index b064d9c96..000000000 --- a/tests/ImageSharp.Tests/Drawing/RecolorImageTest.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Primitives; -using Xunit; - -namespace SixLabors.ImageSharp.Tests -{ - public class RecolorImageTest : FileTestBase - { - [Fact] - public void ImageShouldRecolorYellowToHotPink() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "RecolorImage"); - - var brush = new RecolorBrush(Rgba32.Yellow, Rgba32.HotPink, 0.2f); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateRgba32Image()) - { - image.Mutate(x => x.Fill(brush)); - image.Save($"{path}/{file.FileName}"); - } - } - } - - [Fact] - public void ImageShouldRecolorYellowToHotPinkInARectangle() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "RecolorImage"); - - var brush = new RecolorBrush(Rgba32.Yellow, Rgba32.HotPink, 0.2f); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateRgba32Image()) - { - int imageHeight = image.Height; - image.Mutate(x => x.Fill(brush, new Rectangle(0, imageHeight / 2 - imageHeight / 4, image.Width, imageHeight / 2))); - image.Save($"{path}/Shaped_{file.FileName}"); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs new file mode 100644 index 000000000..cb671a53d --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs @@ -0,0 +1,51 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Primitives; +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + [GroupOutput("Drawing")] + public class RecolorImageTests + { + [Theory] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, "Yellow", "Pink", 0.2f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Bgra32, "Yellow", "Pink", 0.5f)] + [WithTestPatternImages(100, 100, PixelTypes.Rgba32, "Red", "Blue", 0.2f)] + [WithTestPatternImages(100, 100, PixelTypes.Rgba32, "Red", "Blue", 0.6f)] + public void Recolor(TestImageProvider provider, string sourceColorName, string targetColorName, float threshold) + where TPixel : struct, IPixel + { + Color sourceColor = TestUtils.GetColorByName(sourceColorName); + Color targetColor = TestUtils.GetColorByName(targetColorName); + var brush = new RecolorBrush(sourceColor.ToPixel(), targetColor.ToPixel(), threshold); + + FormattableString testInfo = $"{sourceColorName}-{targetColorName}-{threshold}"; + provider.RunValidatingProcessorTest(x => x.Fill(brush), testInfo); + } + + [Theory] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Bgra32, "Yellow", "Pink", 0.5f)] + [WithTestPatternImages(100, 100, PixelTypes.Rgba32, "Red", "Blue", 0.2f)] + public void Recolor_InBox(TestImageProvider provider, string sourceColorName, string targetColorName, float threshold) + where TPixel : struct, IPixel + { + Color sourceColor = TestUtils.GetColorByName(sourceColorName); + Color targetColor = TestUtils.GetColorByName(targetColorName); + var brush = new RecolorBrush(sourceColor.ToPixel(), targetColor.ToPixel(), threshold); + + FormattableString testInfo = $"{sourceColorName}-{targetColorName}-{threshold}"; + provider.RunValidatingProcessorTest(x => + { + Size size = x.GetCurrentSize(); + var rectangle = new Rectangle(0, size.Height / 2 - size.Height / 4, size.Width, size.Height / 2); + x.Fill(brush, rectangle); + }, testInfo); + } + } +} \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index dc5afda9a..5036d47ec 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit dc5afda9a4ad69dc3526d49ceb1d27610064f2af +Subproject commit 5036d47ec2393d90efb6f3864d828e2e4381947f From 52fbbda7e1c624ade12a3c3e7131848248b579a8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 02:34:48 +0200 Subject: [PATCH 171/223] FillPolygonTests --- src/ImageSharp/Color/Color.Conversions.cs | 14 + src/ImageSharp/Color/Color.cs | 12 + tests/ImageSharp.Tests/Color/ColorTests.cs | 11 + .../Drawing/FillPolygonTests.cs | 155 +++++++++++ .../Drawing/RecolorImageTests.cs | 3 +- .../Drawing/SolidPolygonTests.cs | 240 ------------------ tests/Images/External | 2 +- 7 files changed, 195 insertions(+), 242 deletions(-) create mode 100644 tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs diff --git a/src/ImageSharp/Color/Color.Conversions.cs b/src/ImageSharp/Color/Color.Conversions.cs index 001aee5a4..20dca6770 100644 --- a/src/ImageSharp/Color/Color.Conversions.cs +++ b/src/ImageSharp/Color/Color.Conversions.cs @@ -117,6 +117,13 @@ namespace SixLabors.ImageSharp /// The . public static implicit operator Color(Bgr24 source) => new Color(source); + /// + /// Converts an to . + /// + /// The . + /// The . + public static explicit operator Color(Vector4 source) => new Color(source); + /// /// Converts a to . /// @@ -158,5 +165,12 @@ namespace SixLabors.ImageSharp /// The . /// The . public static implicit operator Bgr24(Color color) => color.data.ToBgr24(); + + /// + /// Converts a to . + /// + /// The . + /// The . + public static explicit operator Vector4(Color color) => color.data.ToVector4(); } } \ No newline at end of file diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index f2f8578d8..fe3503314 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -94,6 +94,18 @@ namespace SixLabors.ImageSharp return new Color(rgba); } + /// + /// Alters the alpha channel of the color, returning a new instance. + /// + /// The new value of alpha [0..1]. + /// The color having it's alpha channel altered. + public Color WithAlpha(float alpha) + { + Vector4 v = (Vector4)this; + v.W = alpha; + return new Color(v); + } + /// /// Gets the hexadecimal representation of the color instance in rrggbbaa form. /// diff --git a/tests/ImageSharp.Tests/Color/ColorTests.cs b/tests/ImageSharp.Tests/Color/ColorTests.cs index 729ef94e3..e9e22ccdd 100644 --- a/tests/ImageSharp.Tests/Color/ColorTests.cs +++ b/tests/ImageSharp.Tests/Color/ColorTests.cs @@ -13,6 +13,17 @@ namespace SixLabors.ImageSharp.Tests { public partial class ColorTests { + [Fact] + public void WithAlpha() + { + Color c1 = Color.FromRgba(111, 222, 55, 255); + Color c2 = c1.WithAlpha(0.5f); + + Rgba32 expected = new Rgba32(111, 222, 55, 128); + + Assert.Equal(expected, (Rgba32)c2); + } + [Fact] public void Equality_WhenTrue() { diff --git a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs new file mode 100644 index 000000000..43029e695 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs @@ -0,0 +1,155 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Shapes; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class FillPolygonTests + { + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 0.6f, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Bgr24, "Yellow", 1f, true)] + public void FillPolygon_Solid(TestImageProvider provider, string colorName, float alpha, bool antialias) + where TPixel : struct, IPixel + { + SixLabors.Primitives.PointF[] simplePath = + { + new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) + }; + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + + GraphicsOptions options = new GraphicsOptions(antialias); + + string aa = antialias ? "" : "_NoAntialias"; + FormattableString outputDetails = $"{colorName}_A{alpha}{aa}"; + + provider.RunValidatingProcessorTest( + c => c.FillPolygon(options, color.ToPixel(), simplePath), + outputDetails, + appendSourceFileOrDescription: false); + } + + [Theory] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32)] + public void FillPolygon_Concave(TestImageProvider provider) + where TPixel : struct, IPixel + { + var points = new SixLabors.Primitives.PointF[] + { + new Vector2(8, 8), + new Vector2(64, 8), + new Vector2(64, 64), + new Vector2(120, 64), + new Vector2(120, 120), + new Vector2(8, 120) + }; + + Color color = Color.LightGreen; + + provider.RunValidatingProcessorTest( + c => c.FillPolygon(color.ToPixel(), points), + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32)] + public void FillPolygon_Pattern(TestImageProvider provider) + where TPixel : struct, IPixel + { + SixLabors.Primitives.PointF[] simplePath = + { + new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) + }; + Color color = Color.Yellow; + + var brush = Brushes.Horizontal(color.ToPixel()); + + provider.RunValidatingProcessorTest( + c => c.FillPolygon(brush, simplePath), + appendSourceFileOrDescription: false); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, TestImages.Png.Ducky)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, TestImages.Bmp.Car)] + public void FillPolygon_ImageBrush(TestImageProvider provider, string brushImageName) + where TPixel : struct, IPixel + { + SixLabors.Primitives.PointF[] simplePath = + { + new Vector2(10, 10), new Vector2(200, 50), new Vector2(50, 200) + }; + + using (Image brushImage = Image.Load(TestFile.Create(brushImageName).Bytes)) + { + var brush = new ImageBrush(brushImage); + + provider.RunValidatingProcessorTest( + c => c.FillPolygon(brush, simplePath), + System.IO.Path.GetFileNameWithoutExtension(brushImageName), + appendSourceFileOrDescription: false); + } + } + + [Theory] + [WithBasicTestPatternImages(250, 250, PixelTypes.Rgba32)] + public void Fill_RectangularPolygon(TestImageProvider provider) + where TPixel : struct, IPixel + { + var polygon = new SixLabors.Shapes.RectangularPolygon(10, 10, 190, 140); + Color color = Color.White; + + provider.RunValidatingProcessorTest( + c => c.Fill(color.ToPixel(), polygon), + appendSourceFileOrDescription: false); + } + + [Theory] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 3, 50, 0f)] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 3, 60, 20f)] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 3, 60, -180f)] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 5, 70, 0f)] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32, 7, 80, -180f)] + public void Fill_RegularPolygon(TestImageProvider provider, int vertices, float radius, float angleDeg) + where TPixel : struct, IPixel + { + float angle = GeometryUtilities.DegreeToRadian(angleDeg); + var polygon = new RegularPolygon(100, 100, vertices, radius, angle); + Color color = Color.Yellow; + + FormattableString testOutput = $"V({vertices})_R({radius})_Ang({angleDeg})"; + provider.RunValidatingProcessorTest( + c => c.Fill(color.ToPixel(), polygon), + testOutput, + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); + } + + [Theory] + [WithBasicTestPatternImages(200, 200, PixelTypes.Rgba32)] + public void Fill_EllipsePolygon(TestImageProvider provider) + where TPixel : struct, IPixel + { + var polygon = new EllipsePolygon(100, 100, 80, 120); + Color color = Color.Azure; + + provider.RunValidatingProcessorTest( + c => c.Fill(color.ToPixel(), polygon), + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); + } + } +} diff --git a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs index cb671a53d..461ca700f 100644 --- a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs @@ -6,9 +6,10 @@ using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.Primitives; + using Xunit; -namespace SixLabors.ImageSharp.Tests +namespace SixLabors.ImageSharp.Tests.Drawing { [GroupOutput("Drawing")] public class RecolorImageTests diff --git a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs deleted file mode 100644 index 6a299aad7..000000000 --- a/tests/ImageSharp.Tests/Drawing/SolidPolygonTests.cs +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class SolidPolygonTests : FileTestBase - { - [Fact] - public void ImageShouldBeOverlayedByFilledPolygon() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - SixLabors.Primitives.PointF[] simplePath = { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.FillPolygon(new GraphicsOptions(true), Rgba32.HotPink, simplePath)); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[81, 145]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledPolygonWithPattern() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - var simplePath = new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - - using (var image = new Image(500, 500)) - { - image.Mutate( - x => x.FillPolygon(new GraphicsOptions(true), Brushes.Horizontal(Rgba32.HotPink), simplePath)); - image.Save($"{path}/Pattern.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[81, 145]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledPolygonNoAntialias() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - var simplePath = new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.FillPolygon( - new GraphicsOptions(false), - Rgba32.HotPink, - simplePath)); - image.Save($"{path}/Simple_NoAntialias.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.True(Rgba32.HotPink == sourcePixels[11, 11], "[11, 11] wrong"); - - Assert.True(Rgba32.HotPink == sourcePixels[199, 149], "[199, 149] wrong"); - - Assert.True(Rgba32.HotPink == sourcePixels[50, 50], "[50, 50] wrong"); - - Assert.True(Rgba32.Blue == sourcePixels[2, 2], "[2, 2] wrong"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledPolygonImage() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - var simplePath = new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - - using (Image brushImage = TestFile.Create(TestImages.Bmp.Car).CreateRgba32Image()) - using (var image = new Image(500, 500)) - { - var brush = new ImageBrush(brushImage); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.FillPolygon(brush, simplePath)); - image.Save($"{path}/Image.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledPolygonOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - var simplePath = new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.FillPolygon(color, simplePath)); - image.Save($"{path}/Opacity.png"); - - //shift background color towards forground color by the opacity amount - var mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledRectangle() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.Fill( - Rgba32.HotPink, - new SixLabors.Shapes.RectangularPolygon(10, 10, 190, 140))); - image.Save($"{path}/Rectangle.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[198, 10]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 50]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledTriangle() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - - using (var image = new Image(100, 100)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.Fill(Rgba32.HotPink, new RegularPolygon(50, 50, 3, 30))); - image.Save($"{path}/Triangle.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.Blue, sourcePixels[30, 65]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 50]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledSeptagon() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - - var config = Configuration.CreateDefaultInstance(); - config.MaxDegreeOfParallelism = 1; - using (var image = new Image(config, 100, 100)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Fill(Rgba32.HotPink, - new RegularPolygon(50, 50, 7, 30, -(float)Math.PI))); - image.Save($"{path}/Septagon.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByFilledEllipse() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - - var config = Configuration.CreateDefaultInstance(); - config.MaxDegreeOfParallelism = 1; - using (var image = new Image(config, 100, 100)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x - .Fill(Rgba32.HotPink, new EllipsePolygon(50, 50, 30, 50) - .Rotate((float)(Math.PI / 3)))); - image.Save($"{path}/ellipse.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedBySquareWithCornerClipped() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "FilledPolygons"); - - var config = Configuration.CreateDefaultInstance(); - config.MaxDegreeOfParallelism = 1; - using (var image = new Image(config, 200, 200)) - { - image.Mutate(x => x - .Fill(Rgba32.Blue) - .FillPolygon(Rgba32.HotPink, new SixLabors.Primitives.PointF[] - { - new Vector2( 8, 8 ), - new Vector2( 64, 8 ), - new Vector2( 64, 64 ), - new Vector2( 120, 64 ), - new Vector2( 120, 120 ), - new Vector2( 8, 120 ) - })); - image.Save($"{path}/clipped-corner.png"); - } - } - } -} diff --git a/tests/Images/External b/tests/Images/External index 5036d47ec..0edeb078b 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 5036d47ec2393d90efb6f3864d828e2e4381947f +Subproject commit 0edeb078b9d9f9c8be016ca514a3a625c4768bd6 From 680156ad0c4236fe79b707bd36ed513b015ba515 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 03:00:05 +0200 Subject: [PATCH 172/223] DrawPolygonTests, DrawLinesTests --- .../Drawing/DrawLinesTests.cs | 100 +++++++++ .../Drawing/DrawPolygonTests.cs | 43 ++++ tests/ImageSharp.Tests/Drawing/LineTests.cs | 193 ------------------ .../ImageSharp.Tests/Drawing/PolygonTests.cs | 102 --------- tests/Images/External | 2 +- 5 files changed, 144 insertions(+), 296 deletions(-) create mode 100644 tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs create mode 100644 tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/LineTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/PolygonTests.cs diff --git a/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs b/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs new file mode 100644 index 000000000..c225b921e --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs @@ -0,0 +1,100 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class DrawLinesTests + { + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 2.5, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 0.6f, 10, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 5, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Bgr24, "Yellow", 1f, 10, true)] + public void DrawLines_Simple(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + Pen pen = new Pen(color.ToPixel(), thickness); + + DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 5, false)] + public void DrawLines_Dash(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + Pen pen = Pens.Dash(color.ToPixel(), thickness); + + DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "LightGreen", 1f, 5, false)] + public void DrawLines_Dot(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + Pen pen = Pens.Dot(color.ToPixel(), thickness); + + DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "Yellow", 1f, 5, false)] + public void DrawLines_DashDot(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + Pen pen = Pens.DashDot(color.ToPixel(), thickness); + + DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); + } + + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "Black", 1f, 5, false)] + public void DrawLines_DashDotDot(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + Pen pen = Pens.DashDotDot(color.ToPixel(), thickness); + + DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); + } + + + private static void DrawLinesImpl( + TestImageProvider provider, + string colorName, + float alpha, + float thickness, + bool antialias, + Pen pen) + where TPixel : struct, IPixel + { + SixLabors.Primitives.PointF[] simplePath = { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; + + GraphicsOptions options = new GraphicsOptions(antialias); + + string aa = antialias ? "" : "_NoAntialias"; + FormattableString outputDetails = $"{colorName}_A({alpha})_T({thickness}){aa}"; + + provider.RunValidatingProcessorTest( + c => c.DrawLines(options, pen, simplePath), + outputDetails, + appendSourceFileOrDescription: false); + } + + } +} diff --git a/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs new file mode 100644 index 000000000..8a0f25667 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs @@ -0,0 +1,43 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; +using SixLabors.ImageSharp.Processing; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class DrawPolygonTests + { + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 2.5, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 0.6f, 10, true)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, "White", 1f, 5, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Bgr24, "Yellow", 1f, 10, true)] + public void DrawPolygon(TestImageProvider provider, string colorName, float alpha, float thickness, bool antialias) + where TPixel : struct, IPixel + { + SixLabors.Primitives.PointF[] simplePath = + { + new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) + }; + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); + + GraphicsOptions options = new GraphicsOptions(antialias); + + string aa = antialias ? "" : "_NoAntialias"; + FormattableString outputDetails = $"{colorName}_A({alpha})_T({thickness}){aa}"; + + provider.RunValidatingProcessorTest( + c => c.DrawPolygon(options, color.ToPixel(), thickness, simplePath), + outputDetails, + appendSourceFileOrDescription: false); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/LineTests.cs b/tests/ImageSharp.Tests/Drawing/LineTests.cs deleted file mode 100644 index 1cc0fd1a4..000000000 --- a/tests/ImageSharp.Tests/Drawing/LineTests.cs +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class LineTests : FileTestBase - { - [Fact] - public void ImageShouldBeOverlayedByPath() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.DrawLines( - Rgba32.HotPink, - 5, - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPath_NoAntialias() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.DrawLines( - new GraphicsOptions(false), - Rgba32.HotPink, - 5, - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - image.Save($"{path}/Simple_noantialias.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPathDashed() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.DrawLines(Pens.Dash(Rgba32.HotPink, 5), - new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - })); - image.Save($"{path}/Dashed.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPathDotted() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.DrawLines(Pens.Dot(Rgba32.HotPink, 5), - new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - })); - image.Save($"{path}/Dot.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPathDashDot() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.DrawLines(Pens.DashDot(Rgba32.HotPink, 5), - new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - })); - image.Save($"{path}/DashDot.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPathDashDotDot() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - var image = new Image(500, 500); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.DrawLines(Pens.DashDotDot(Rgba32.HotPink, 5), - new SixLabors.Primitives.PointF[] { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - })); - image.Save($"{path}/DashDotDot.png"); - } - - [Fact] - public void ImageShouldBeOverlayedPathWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - var image = new Image(500, 500); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.DrawLines( - color, - 10, - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - image.Save($"{path}/Opacity.png"); - - //shift background color towards forground color by the opacity amount - var mergedColor = - new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(mergedColor, sourcePixels[11, 11]); - - Assert.Equal(mergedColor, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } - - [Fact] - public void ImageShouldBeOverlayedByPathOutline() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines"); - - var image = new Image(500, 500); - - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.DrawLines( - Rgba32.HotPink, - 10, - new Vector2(10, 10), - new Vector2(200, 10), - new Vector2(200, 150), - new Vector2(10, 150))); - image.Save($"{path}/Rectangle.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[198, 10]); - - Assert.Equal(Rgba32.Blue, sourcePixels[10, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/PolygonTests.cs b/tests/ImageSharp.Tests/Drawing/PolygonTests.cs deleted file mode 100644 index febb39c20..000000000 --- a/tests/ImageSharp.Tests/Drawing/PolygonTests.cs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; -using SixLabors.ImageSharp.Processing; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class PolygonTests : FileTestBase - { - [Fact] - public void ImageShouldBeOverlayedByPolygonOutline() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Polygons"); - - using (Image image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.DrawPolygon( - Rgba32.HotPink, - 5, - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[9, 9]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - } - } - - [Fact] - public void ImageShouldBeOverlayedPolygonOutlineWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Polygons"); - PointF[] simplePath = { - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300) - }; - - Rgba32 color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (Image image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.DrawPolygon(color, 10, simplePath)); - image.Save($"{path}/Opacity.png"); - - //shift background color towards forground color by the opacity amount - Rgba32 mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(mergedColor, sourcePixels[9, 9]); - - Assert.Equal(mergedColor, sourcePixels[199, 149]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByRectangleOutline() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "Polygons"); - - using (Image image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate( - x => x.Draw(Rgba32.HotPink, 10, new Rectangle(10, 10, 190, 140))); - image.Save($"{path}/Rectangle.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[8, 8]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[198, 10]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[50, 50]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - } - } - } -} \ No newline at end of file diff --git a/tests/Images/External b/tests/Images/External index 0edeb078b..4fe9334aa 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 0edeb078b9d9f9c8be016ca514a3a625c4768bd6 +Subproject commit 4fe9334aa8898f67b6e3df94bc00867645c3e709 From 473fd02be7693f63ee5a77c3c44b52afd7fc59ee Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 03:22:21 +0200 Subject: [PATCH 173/223] DrawBeziersTests, DrawComplexPolygonTests --- .../Drawing/DrawBezierTests.cs | 102 +++------ .../Drawing/DrawComplexPolygonTests.cs | 70 ++++++ .../Drawing/LineComplexPolygonTests.cs | 201 ------------------ tests/Images/External | 2 +- 4 files changed, 100 insertions(+), 275 deletions(-) create mode 100644 tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs diff --git a/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs index d82221ca6..0f29728c9 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using SixLabors.ImageSharp.Memory; @@ -11,82 +12,37 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { + [GroupOutput("Drawing")] public class DrawBezierTests { - [Fact] - public void ImageShouldBeOverlayedByBezierLine() + public static readonly TheoryData DrawPathData = new TheoryData + { + { "White", 255, 1.5f }, + { "Red", 255, 3 }, + { "HotPink", 255, 5 }, + { "HotPink", 150, 5 }, + { "White", 255, 15 }, + }; + + [Theory] + [WithSolidFilledImages(nameof(DrawPathData), 300, 450, "Blue", PixelTypes.Rgba32)] + public void DrawBeziers(TestImageProvider provider, string colorName, byte alpha, float thickness) + where TPixel : struct, IPixel { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "DrawBezierTests"); - using (var image = new Image(350, 450)) - { - image.Mutate(x => x.BackgroundColor(Color.Blue)); - image.Mutate( - x => x.DrawBeziers( - Rgba32.HotPink, - 5, - new SixLabors.Primitives.PointF[] - { - new Vector2(10, 400), new Vector2(30, 10), new Vector2(240, 30), new Vector2(300, 400) - })); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - //top of curve - Assert.Equal(Rgba32.HotPink, sourcePixels[138, 115]); - - //start points - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 395]); - Assert.Equal(Rgba32.HotPink, sourcePixels[300, 395]); - - //curve points should not be never be set - Assert.Equal(Rgba32.Blue, sourcePixels[30, 10]); - Assert.Equal(Rgba32.Blue, sourcePixels[240, 30]); - - // inside shape should be empty - Assert.Equal(Rgba32.Blue, sourcePixels[200, 250]); - } - } - - - [Fact] - public void ImageShouldBeOverlayedBezierLineWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "DrawBezierTests"); - - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (var image = new Image(350, 450)) - { - image.Mutate(x => x.BackgroundColor(Color.Blue)); - image.Mutate( - x => x.DrawBeziers( - color, - 10, - new SixLabors.Primitives.PointF[] - { - new Vector2(10, 400), new Vector2(30, 10), new Vector2(240, 30), new Vector2(300, 400) - })); - image.Save($"{path}/Opacity.png"); - - //shift background color towards foreground color by the opacity amount - var mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - // top of curve - Assert.Equal(mergedColor, sourcePixels[138, 115]); - - // start points - Assert.Equal(mergedColor, sourcePixels[10, 395]); - Assert.Equal(mergedColor, sourcePixels[300, 395]); - - // curve points should not be never be set - Assert.Equal(Rgba32.Blue, sourcePixels[30, 10]); - Assert.Equal(Rgba32.Blue, sourcePixels[240, 30]); - - // inside shape should be empty - Assert.Equal(Rgba32.Blue, sourcePixels[200, 250]); - } + var points = new SixLabors.Primitives.PointF[] + { + new Vector2(10, 400), new Vector2(30, 10), new Vector2(240, 30), new Vector2(300, 400) + }; + Rgba32 rgba = TestUtils.GetColorByName(colorName); + rgba.A = alpha; + Color color = rgba; + + FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; + + provider.RunValidatingProcessorTest( x => x.DrawBeziers(color.ToPixel(), 5f, points), + testDetails, + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); } } } diff --git a/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs new file mode 100644 index 000000000..b6e105a19 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs @@ -0,0 +1,70 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Numerics; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Shapes; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Drawing +{ + [GroupOutput("Drawing")] + public class DrawComplexPolygonTests + { + [Theory] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, false, false, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, true, false, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, false, true, false)] + [WithBasicTestPatternImages(250, 350, PixelTypes.Rgba32, false, false, true)] + public void DrawComplexPolygon(TestImageProvider provider, bool overlap, bool transparent, bool dashed) + where TPixel :struct, IPixel + { + var simplePath = new Polygon(new LinearLineSegment( + new Vector2(10, 10), + new Vector2(200, 150), + new Vector2(50, 300))); + + var hole1 = new Polygon(new LinearLineSegment( + new Vector2(37, 85), + overlap ? new Vector2(130, 40) : new Vector2(93, 85), + new Vector2(65, 137))); + IPath clipped = simplePath.Clip(hole1); + + Rgba32 colorRgba = Rgba32.White; + if (transparent) + { + colorRgba.A = 150; + } + + Color color = colorRgba; + + string testDetails = ""; + if (overlap) + { + testDetails += "_Overlap"; + } + + if (transparent) + { + testDetails += "_Transparent"; + } + + if (dashed) + { + testDetails += "_Dashed"; + } + + Pen pen = dashed ? Pens.Dash(color.ToPixel(), 5f) : Pens.Solid(color.ToPixel(), 5f); + + provider.RunValidatingProcessorTest( + x => x.Draw(pen, clipped), + testDetails, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + } +} diff --git a/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs deleted file mode 100644 index 06961bec4..000000000 --- a/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Numerics; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Shapes; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Drawing -{ - public class LineComplexPolygonTests : FileTestBase - { - [Fact] - public void ImageShouldBeOverlayedByPolygonOutline() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "LineComplexPolygon"); - - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(93, 85), - new Vector2(65, 137))); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); - image.Save($"{path}/Simple.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 10]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[200, 150]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 300]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[37, 85]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[93, 85]); - - Assert.Equal(Rgba32.HotPink, sourcePixels[65, 137]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[57, 99]); - - //inside shape - Assert.Equal(Rgba32.Blue, sourcePixels[100, 192]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPolygonOutlineNoOverlapping() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "LineComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(207, 25), - new Vector2(263, 25), - new Vector2(235, 57))); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); - image.Save($"{path}/SimpleVanishHole.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 10]); - Assert.Equal(Rgba32.HotPink, sourcePixels[200, 150]); - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 300]); - - //Assert.Equal(Color.HotPink, sourcePixels[37, 85]); - - //Assert.Equal(Color.HotPink, sourcePixels[93, 85]); - - //Assert.Equal(Color.HotPink, sourcePixels[65, 137]); - - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[57, 99]); - - //inside shape - Assert.Equal(Rgba32.Blue, sourcePixels[100, 192]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPolygonOutlineOverlapping() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "LineComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(130, 40), - new Vector2(65, 137))); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(Rgba32.HotPink, 5, simplePath.Clip(hole1))); - image.Save($"{path}/SimpleOverlapping.png"); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 10]); - Assert.Equal(Rgba32.HotPink, sourcePixels[200, 150]); - Assert.Equal(Rgba32.HotPink, sourcePixels[50, 300]); - Assert.Equal(Rgba32.Blue, sourcePixels[130, 41]); - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[57, 99]); - - //inside shape - Assert.Equal(Rgba32.Blue, sourcePixels[100, 192]); - } - } - - [Fact] - public void ImageShouldBeOverlayedByPolygonOutlineDashed() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "LineComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(93, 85), - new Vector2(65, 137))); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(Pens.Dash(Rgba32.HotPink, 5), simplePath.Clip(hole1))); - image.Save($"{path}/Dashed.png"); - } - } - - [Fact] - public void ImageShouldBeOverlayedPolygonOutlineWithOpacity() - { - string path = TestEnvironment.CreateOutputDirectory("Drawing", "LineComplexPolygon"); - var simplePath = new Polygon(new LinearLineSegment( - new Vector2(10, 10), - new Vector2(200, 150), - new Vector2(50, 300))); - - var hole1 = new Polygon(new LinearLineSegment( - new Vector2(37, 85), - new Vector2(93, 85), - new Vector2(65, 137))); - var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150); - - using (var image = new Image(500, 500)) - { - image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); - image.Mutate(x => x.Draw(color, 5, simplePath.Clip(hole1))); - image.Save($"{path}/Opacity.png"); - - //shift background color towards forground color by the opacity amount - var mergedColor = new Rgba32( - Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f)); - - Buffer2D sourcePixels = image.GetRootFramePixelBuffer(); - Assert.Equal(mergedColor, sourcePixels[10, 10]); - Assert.Equal(mergedColor, sourcePixels[200, 150]); - Assert.Equal(mergedColor, sourcePixels[50, 300]); - Assert.Equal(mergedColor, sourcePixels[37, 85]); - Assert.Equal(mergedColor, sourcePixels[93, 85]); - Assert.Equal(mergedColor, sourcePixels[65, 137]); - Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]); - - //inside hole - Assert.Equal(Rgba32.Blue, sourcePixels[57, 99]); - - //inside shape - Assert.Equal(Rgba32.Blue, sourcePixels[100, 192]); - } - } - } -} diff --git a/tests/Images/External b/tests/Images/External index 4fe9334aa..55c250ab8 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 4fe9334aa8898f67b6e3df94bc00867645c3e709 +Subproject commit 55c250ab80f7f9fc26208b9b9d9590cbe8012446 From 552d885f0378ecbfb770cf859eb37b8534b2531d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 13:39:10 +0200 Subject: [PATCH 174/223] move implicit Color conversion to pixel types, add micro-optimizations --- ImageSharp.sln.DotSettings | 1 + src/ImageSharp/Color/Color.Conversions.cs | 133 ++++-------------- src/ImageSharp/Color/Color.cs | 39 ++++- .../PixelImplementations/Argb32.cs | 16 +++ .../PixelImplementations/Bgr24.cs | 16 +++ .../PixelImplementations/Bgra32.cs | 16 +++ .../PixelImplementations/Rgb24.cs | 16 +++ .../PixelImplementations/Rgba32.cs | 16 +++ .../PixelImplementations/Rgba64.cs | 23 +++ tests/ImageSharp.Tests/Color/ColorTests.cs | 2 + 10 files changed, 165 insertions(+), 113 deletions(-) diff --git a/ImageSharp.sln.DotSettings b/ImageSharp.sln.DotSettings index 526817242..ece3dddb3 100644 --- a/ImageSharp.sln.DotSettings +++ b/ImageSharp.sln.DotSettings @@ -388,5 +388,6 @@ True True True + True True \ No newline at end of file diff --git a/src/ImageSharp/Color/Color.Conversions.cs b/src/ImageSharp/Color/Color.Conversions.cs index 001aee5a4..a524b9db1 100644 --- a/src/ImageSharp/Color/Color.Conversions.cs +++ b/src/ImageSharp/Color/Color.Conversions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System.Numerics; +using System.Runtime.CompilerServices; using SixLabors.ImageSharp.PixelFormats; @@ -16,147 +17,67 @@ namespace SixLabors.ImageSharp /// Initializes a new instance of the struct. /// /// The containing the color information. - public Color(Rgba64 pixel) - { - this.data = pixel; - } + [MethodImpl(InliningOptions.ShortMethod)] + public Color(Rgba64 pixel) => this.data = pixel; /// /// Initializes a new instance of the struct. /// /// The containing the color information. - public Color(Rgba32 pixel) - { - this.data = new Rgba64(pixel); - } + [MethodImpl(InliningOptions.ShortMethod)] + public Color(Rgba32 pixel) => this.data = new Rgba64(pixel); /// /// Initializes a new instance of the struct. /// /// The containing the color information. - public Color(Argb32 pixel) - { - this.data = new Rgba64(pixel); - } + [MethodImpl(InliningOptions.ShortMethod)] + public Color(Argb32 pixel) => this.data = new Rgba64(pixel); /// /// Initializes a new instance of the struct. /// /// The containing the color information. - public Color(Bgra32 pixel) - { - this.data = new Rgba64(pixel); - } + [MethodImpl(InliningOptions.ShortMethod)] + public Color(Bgra32 pixel) => this.data = new Rgba64(pixel); /// /// Initializes a new instance of the struct. /// /// The containing the color information. - public Color(Rgb24 pixel) - { - this.data = new Rgba64(pixel); - } + [MethodImpl(InliningOptions.ShortMethod)] + public Color(Rgb24 pixel) => this.data = new Rgba64(pixel); /// /// Initializes a new instance of the struct. /// /// The containing the color information. - public Color(Bgr24 pixel) - { - this.data = new Rgba64(pixel); - } + [MethodImpl(InliningOptions.ShortMethod)] + public Color(Bgr24 pixel) => this.data = new Rgba64(pixel); /// /// Initializes a new instance of the struct. /// /// The containing the color information. - public Color(Vector4 vector) - { - this.data = new Rgba64(vector); - } + [MethodImpl(InliningOptions.ShortMethod)] + public Color(Vector4 vector) => this.data = new Rgba64(vector); - /// - /// Converts an to . - /// - /// The . - /// The . - public static implicit operator Color(Rgba64 source) => new Color(source); - - /// - /// Converts an to . - /// - /// The . - /// The . - public static implicit operator Color(Rgba32 source) => new Color(source); - - /// - /// Converts an to . - /// - /// The . - /// The . - public static implicit operator Color(Bgra32 source) => new Color(source); - - /// - /// Converts an to . - /// - /// The . - /// The . - public static implicit operator Color(Argb32 source) => new Color(source); - - /// - /// Converts an to . - /// - /// The . - /// The . - public static implicit operator Color(Rgb24 source) => new Color(source); - - /// - /// Converts an to . - /// - /// The . - /// The . - public static implicit operator Color(Bgr24 source) => new Color(source); + [MethodImpl(InliningOptions.ShortMethod)] + internal Rgba64 ToRgba64() => this.data; - /// - /// Converts a to . - /// - /// The . - /// The . - public static implicit operator Rgba64(Color color) => color.data; + [MethodImpl(InliningOptions.ShortMethod)] + internal Rgba32 ToRgba32() => this.data.ToRgba32(); - /// - /// Converts a to . - /// - /// The . - /// The . - public static implicit operator Rgba32(Color color) => color.data.ToRgba32(); + [MethodImpl(InliningOptions.ShortMethod)] + internal Bgra32 ToBgra32() => this.data.ToBgra32(); - /// - /// Converts a to . - /// - /// The . - /// The . - public static implicit operator Bgra32(Color color) => color.data.ToBgra32(); + [MethodImpl(InliningOptions.ShortMethod)] + internal Argb32 ToArgb32() => this.data.ToArgb32(); - /// - /// Converts a to . - /// - /// The . - /// The . - public static implicit operator Argb32(Color color) => color.data.ToArgb32(); + [MethodImpl(InliningOptions.ShortMethod)] + internal Rgb24 ToRgb24() => this.data.ToRgb24(); - /// - /// Converts a to . - /// - /// The . - /// The . - public static implicit operator Rgb24(Color color) => color.data.ToRgb24(); - - /// - /// Converts a to . - /// - /// The . - /// The . - public static implicit operator Bgr24(Color color) => color.data.ToBgr24(); + [MethodImpl(InliningOptions.ShortMethod)] + internal Bgr24 ToBgr24() => this.data.ToBgr24(); } } \ No newline at end of file diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index f2f8578d8..e4640ff63 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -5,6 +5,7 @@ using System; using System.Buffers.Binary; using System.Globalization; using System.Numerics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.PixelFormats; @@ -24,6 +25,26 @@ namespace SixLabors.ImageSharp { private readonly Rgba64 data; + [MethodImpl(InliningOptions.ShortMethod)] + private Color(byte r, byte g, byte b, byte a) + { + this.data = new Rgba64( + ImageMaths.UpscaleFrom8BitTo16Bit(r), + ImageMaths.UpscaleFrom8BitTo16Bit(g), + ImageMaths.UpscaleFrom8BitTo16Bit(b), + ImageMaths.UpscaleFrom8BitTo16Bit(a)); + } + + [MethodImpl(InliningOptions.ShortMethod)] + private Color(byte r, byte g, byte b) + { + this.data = new Rgba64( + ImageMaths.UpscaleFrom8BitTo16Bit(r), + ImageMaths.UpscaleFrom8BitTo16Bit(g), + ImageMaths.UpscaleFrom8BitTo16Bit(b), + ushort.MaxValue); + } + /// /// Checks whether two structures are equal. /// @@ -33,6 +54,7 @@ namespace SixLabors.ImageSharp /// True if the parameter is equal to the parameter; /// otherwise, false. /// + [MethodImpl(InliningOptions.ShortMethod)] public static bool operator ==(Color left, Color right) { return left.Equals(right); @@ -47,6 +69,7 @@ namespace SixLabors.ImageSharp /// True if the parameter is not equal to the parameter; /// otherwise, false. /// + [MethodImpl(InliningOptions.ShortMethod)] public static bool operator !=(Color left, Color right) { return !left.Equals(right); @@ -60,7 +83,8 @@ namespace SixLabors.ImageSharp /// The blue component (0-255). /// The alpha component (0-255). /// The . - public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(new Rgba32(r, g, b, a)); + [MethodImpl(InliningOptions.ShortMethod)] + public static Color FromRgba(byte r, byte g, byte b, byte a) => new Color(r, g, b, a); /// /// Creates a from RGB bytes. @@ -69,7 +93,8 @@ namespace SixLabors.ImageSharp /// The green component (0-255). /// The blue component (0-255). /// The . - public static Color FromRgb(byte r, byte g, byte b) => FromRgba(r, g, b, 255); + [MethodImpl(InliningOptions.ShortMethod)] + public static Color FromRgb(byte r, byte g, byte b) => new Color(r, g, b); /// /// Creates a new instance from the string representing a color in hexadecimal form. @@ -98,6 +123,7 @@ namespace SixLabors.ImageSharp /// Gets the hexadecimal representation of the color instance in rrggbbaa form. /// /// A hexadecimal string representation of the value. + [MethodImpl(InliningOptions.ShortMethod)] public string ToHex() => this.data.ToRgba32().ToHex(); /// @@ -109,6 +135,7 @@ namespace SixLabors.ImageSharp /// /// The pixel type to convert to. /// The pixel value. + [MethodImpl(InliningOptions.ShortMethod)] public TPixel ToPixel() where TPixel : struct, IPixel { @@ -118,6 +145,7 @@ namespace SixLabors.ImageSharp } /// + [MethodImpl(InliningOptions.ShortMethod)] public bool Equals(Color other) { return this.data.PackedValue == other.data.PackedValue; @@ -126,15 +154,11 @@ namespace SixLabors.ImageSharp /// public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) - { - return false; - } - return obj is Color other && this.Equals(other); } /// + [MethodImpl(InliningOptions.ShortMethod)] public override int GetHashCode() { return this.data.PackedValue.GetHashCode(); @@ -143,6 +167,7 @@ namespace SixLabors.ImageSharp /// /// Bulk convert a span of to a span of a specified pixel type. /// + [MethodImpl(InliningOptions.ShortMethod)] internal static void ToPixel( Configuration configuration, ReadOnlySpan source, diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs index 075df01cd..8981c8745 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs @@ -142,6 +142,22 @@ namespace SixLabors.ImageSharp.PixelFormats set => this.Argb = value; } + /// + /// Converts an to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Color(Argb32 source) => new Color(source); + + /// + /// Converts a to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Argb32(Color color) => color.ToArgb32(); + /// /// Compares two objects for equality. /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs index 3ba6436a0..a0b059dfc 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs @@ -50,6 +50,22 @@ namespace SixLabors.ImageSharp.PixelFormats this.B = b; } + /// + /// Converts an to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Color(Bgr24 source) => new Color(source); + + /// + /// Converts a to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Bgr24(Color color) => color.ToBgr24(); + /// /// Compares two objects for equality. /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs index 758be8043..ea7a96188 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs @@ -98,6 +98,22 @@ namespace SixLabors.ImageSharp.PixelFormats set => this.Bgra = value; } + /// + /// Converts an to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Color(Bgra32 source) => new Color(source); + + /// + /// Converts a to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Bgra32(Color color) => color.ToBgra32(); + /// /// Compares two objects for equality. /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs index 1255f66d1..469dbbad4 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs @@ -53,6 +53,22 @@ namespace SixLabors.ImageSharp.PixelFormats this.B = b; } + /// + /// Converts an to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Color(Rgb24 source) => new Color(source); + + /// + /// Converts a to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Rgb24(Color color) => color.ToRgb24(); + /// /// Allows the implicit conversion of an instance of to a /// . diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs index 7367c4463..c58d17ef4 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs @@ -169,6 +169,22 @@ namespace SixLabors.ImageSharp.PixelFormats set => this.Rgba = value; } + /// + /// Converts an to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Color(Rgba32 source) => new Color(source); + + /// + /// Converts a to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Rgba32(Color color) => color.ToRgba32(); + /// /// Allows the implicit conversion of an instance of to a /// . diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs index cf9d4a552..978d9b015 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs @@ -46,6 +46,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// The green component. /// The blue component. /// The alpha component. + [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(ushort r, ushort g, ushort b, ushort a) { this.R = r; @@ -58,6 +59,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Initializes a new instance of the struct. /// /// A structure of 4 bytes in RGBA byte order. + [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Rgba32 source) { this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); @@ -70,6 +72,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Initializes a new instance of the struct. /// /// A structure of 4 bytes in BGRA byte order. + [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Bgra32 source) { this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); @@ -82,6 +85,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Initializes a new instance of the struct. /// /// A structure of 4 bytes in ARGB byte order. + [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Argb32 source) { this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); @@ -94,6 +98,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Initializes a new instance of the struct. /// /// A structure of 3 bytes in RGB byte order. + [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Rgb24 source) { this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); @@ -106,6 +111,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Initializes a new instance of the struct. /// /// A structure of 3 bytes in BGR byte order. + [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Bgr24 source) { this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); @@ -118,6 +124,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Initializes a new instance of the struct. /// /// The . + [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Vector4 vector) { vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max; @@ -149,6 +156,22 @@ namespace SixLabors.ImageSharp.PixelFormats set => Unsafe.As(ref this) = value; } + /// + /// Converts an to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Color(Rgba64 source) => new Color(source); + + /// + /// Converts a to . + /// + /// The . + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static implicit operator Rgba64(Color color) => color.ToPixel(); + /// /// Compares two objects for equality. /// diff --git a/tests/ImageSharp.Tests/Color/ColorTests.cs b/tests/ImageSharp.Tests/Color/ColorTests.cs index 729ef94e3..b2559d1d1 100644 --- a/tests/ImageSharp.Tests/Color/ColorTests.cs +++ b/tests/ImageSharp.Tests/Color/ColorTests.cs @@ -38,6 +38,8 @@ namespace SixLabors.ImageSharp.Tests Assert.False(c1 == c2); Assert.True(c1 != c2); + + Assert.False(c1.Equals(null)); } [Fact] From a910005db0c2862d81d9b203d666c25d9e458dc9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 13:44:53 +0200 Subject: [PATCH 175/223] fix merge issues --- src/ImageSharp/Color/Color.Conversions.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ImageSharp/Color/Color.Conversions.cs b/src/ImageSharp/Color/Color.Conversions.cs index 3123d89e9..16d673d85 100644 --- a/src/ImageSharp/Color/Color.Conversions.cs +++ b/src/ImageSharp/Color/Color.Conversions.cs @@ -62,12 +62,19 @@ namespace SixLabors.ImageSharp [MethodImpl(InliningOptions.ShortMethod)] public Color(Vector4 vector) => this.data = new Rgba64(vector); - [MethodImpl(InliningOptions.ShortMethod)] + /// + /// Converts a to . + /// + /// The . + /// The . + public static explicit operator Vector4(Color color) => color.data.ToVector4(); + /// /// Converts an to . /// /// The . /// The . + [MethodImpl(InliningOptions.ShortMethod)] public static explicit operator Color(Vector4 source) => new Color(source); [MethodImpl(InliningOptions.ShortMethod)] @@ -84,12 +91,5 @@ namespace SixLabors.ImageSharp [MethodImpl(InliningOptions.ShortMethod)] internal Bgr24 ToBgr24() => this.data.ToBgr24(); - - /// - /// Converts a to . - /// - /// The . - /// The . - public static explicit operator Vector4(Color color) => color.data.ToVector4(); } } \ No newline at end of file From 21f221ec29aedb13d0679d2bc7b71332c557c944 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 14:37:02 +0200 Subject: [PATCH 176/223] DrawImageTests: add tolerance to make all test configurations happy --- tests/ImageSharp.Tests/Drawing/DrawImageTests.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index f4e9b7b45..70879e6fe 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -91,7 +91,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing } image.DebugSave(provider, testInfo, encoder: encoder); - image.CompareToReferenceOutput(provider, testInfo); + image.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), + provider, + testInfo); } } @@ -146,7 +148,10 @@ namespace SixLabors.ImageSharp.Tests.Drawing image.Mutate(x => x.DrawImage(blend, position, .75F)); image.DebugSave(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); - image.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); + image.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.002f), + provider, + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); } } From b1d29476d10eb9ddac35811cd687870ec41ed319 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sun, 12 May 2019 18:38:22 +0200 Subject: [PATCH 177/223] Review changes --- src/ImageSharp/Formats/Bmp/BmpEncoder.cs | 7 +++ src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 61 ++++++++++--------- .../Formats/Bmp/IBmpEncoderOptions.cs | 9 ++- 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs index f3eb9282c..612675c33 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs @@ -4,6 +4,7 @@ using System.IO; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Quantization; namespace SixLabors.ImageSharp.Formats.Bmp { @@ -25,6 +26,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public bool SupportTransparency { get; set; } + /// + /// Gets or sets the quantizer for reducing the color count for 8-Bit images. + /// Defaults to OctreeQuantizer. + /// + public IQuantizer Quantizer { get; set; } + /// public void Encode(Image image, Stream stream) where TPixel : struct, IPixel diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 8d0e8578d..90ea673d3 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; using System.IO; using SixLabors.ImageSharp.Advanced; @@ -62,6 +63,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// private readonly bool writeV4Header; + /// + /// The quantizer for reducing the color count for 8-Bit images. + /// + private readonly IQuantizer quantizer; + /// /// Initializes a new instance of the class. /// @@ -72,6 +78,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.memoryAllocator = memoryAllocator; this.bitsPerPixel = options.BitsPerPixel; this.writeV4Header = options.SupportTransparency; + this.quantizer = options.Quantizer ?? new OctreeQuantizer(dither: true, maxColors: 256); } /// @@ -298,39 +305,35 @@ namespace SixLabors.ImageSharp.Formats.Bmp private void Write8Bit(Stream stream, ImageFrame image) where TPixel : struct, IPixel { -#if NETCOREAPP2_1 - Span colorPalette = stackalloc byte[ColorPaletteSize8Bit]; -#else - byte[] colorPalette = new byte[ColorPaletteSize8Bit]; -#endif - - var quantizer = new OctreeQuantizer(dither: true, maxColors: 256); - QuantizedFrame quantized = quantizer.CreateFrameQuantizer(this.configuration).QuantizeFrame(image); - - int idx = 0; - var color = default(Rgba32); - foreach (TPixel quantizedColor in quantized.Palette) + using (IMemoryOwner colorPaletteBuffer = this.memoryAllocator.AllocateManagedByteBuffer(ColorPaletteSize8Bit, AllocationOptions.Clean)) + using (QuantizedFrame quantized = this.quantizer.CreateFrameQuantizer(this.configuration, 256).QuantizeFrame(image)) { - quantizedColor.ToRgba32(ref color); - colorPalette[idx] = color.B; - colorPalette[idx + 1] = color.G; - colorPalette[idx + 2] = color.R; - - // Padding byte, always 0 - colorPalette[idx + 3] = 0; - idx += 4; - } - - stream.Write(colorPalette, 0, ColorPaletteSize8Bit); + Span colorPalette = colorPaletteBuffer.GetSpan(); + int idx = 0; + var color = default(Rgba32); + foreach (TPixel quantizedColor in quantized.Palette) + { + quantizedColor.ToRgba32(ref color); + colorPalette[idx] = color.B; + colorPalette[idx + 1] = color.G; + colorPalette[idx + 2] = color.R; + + // Padding byte, always 0 + colorPalette[idx + 3] = 0; + idx += 4; + } - for (int y = image.Height - 1; y >= 0; y--) - { - Span pixelSpan = quantized.GetRowSpan(y); - stream.Write(pixelSpan); + stream.Write(colorPalette); - for (int i = 0; i < this.padding; i++) + for (int y = image.Height - 1; y >= 0; y--) { - stream.WriteByte(0); + Span pixelSpan = quantized.GetRowSpan(y); + stream.Write(pixelSpan); + + for (int i = 0; i < this.padding; i++) + { + stream.WriteByte(0); + } } } } diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs index 92ff09270..59ad929df 100644 --- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs +++ b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs @@ -1,10 +1,12 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.Processing.Processors.Quantization; + namespace SixLabors.ImageSharp.Formats.Bmp { /// - /// Configuration options for use during bmp encoding + /// Configuration options for use during bmp encoding. /// internal interface IBmpEncoderOptions { @@ -20,5 +22,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Instead a bitmap version 4 info header will be written with the BITFIELDS compression. /// bool SupportTransparency { get; } + + /// + /// Gets the quantizer for reducing the color count for 8-Bit images. + /// + IQuantizer Quantizer { get; } } } \ No newline at end of file From 2bff82367c3b7e597a7532db6ad6612063409473 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 20:39:01 +0200 Subject: [PATCH 178/223] started the refactor --- .../Processing/DrawingHelpers.cs | 19 ++++++++++++ src/ImageSharp.Drawing/Processing/IBrush.cs | 9 ++++-- src/ImageSharp.Drawing/Processing/IPen.cs | 16 +++------- .../Processing/PatternBrush{TPixel}.cs | 30 +++++++++++-------- .../Processing/SolidBrush{TPixel}.cs | 18 +++++------ src/ImageSharp/Color/Color.Conversions.cs | 3 ++ 6 files changed, 59 insertions(+), 36 deletions(-) create mode 100644 src/ImageSharp.Drawing/Processing/DrawingHelpers.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs b/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs new file mode 100644 index 000000000..314b65f7e --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs @@ -0,0 +1,19 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; + +namespace SixLabors.ImageSharp.Processing +{ + internal static class DrawingHelpers + { + public static DenseMatrix ToPixelMatrix(this DenseMatrix colorMatrix, Configuration configuration) + where TPixel : struct, IPixel + { + DenseMatrix result = new DenseMatrix(colorMatrix.Columns, colorMatrix.Rows); + Color.ToPixel(configuration, colorMatrix.Span, result.Span); + return result; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/IBrush.cs b/src/ImageSharp.Drawing/Processing/IBrush.cs index a3c94a1b5..aa8c25b95 100644 --- a/src/ImageSharp.Drawing/Processing/IBrush.cs +++ b/src/ImageSharp.Drawing/Processing/IBrush.cs @@ -14,8 +14,7 @@ namespace SixLabors.ImageSharp.Processing /// A brush is a simple class that will return an that will perform the /// logic for converting a pixel location to a . /// - public interface IBrush - where TPixel : struct, IPixel + public interface IBrush { /// /// Creates the applicator for this brush. @@ -30,6 +29,10 @@ namespace SixLabors.ImageSharp.Processing /// The when being applied to things like shapes would usually be the /// bounding box of the shape not necessarily the bounds of the whole image /// - BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options); + BrushApplicator CreateApplicator( + ImageFrame source, + RectangleF region, + GraphicsOptions options) + where TPixel : struct, IPixel; } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/IPen.cs b/src/ImageSharp.Drawing/Processing/IPen.cs index 6f63dcfd0..b9e359d60 100644 --- a/src/ImageSharp.Drawing/Processing/IPen.cs +++ b/src/ImageSharp.Drawing/Processing/IPen.cs @@ -7,23 +7,15 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing { /// - /// Interface representing a Pen + /// Interface representing the pattern and size of the stroke to apply with a Pen. /// - /// The type of the color. - public interface IPen : IPen - where TPixel : struct, IPixel + public interface IPen { /// /// Gets the stroke fill. /// - IBrush StrokeFill { get; } - } - - /// - /// Interface representing the pattern and size of the stroke to apply with a Pen. - /// - public interface IPen - { + IBrush StrokeFill { get; } + /// /// Gets the width to apply to the stroke /// diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs index 20161b517..249383f3b 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs @@ -35,13 +35,12 @@ namespace SixLabors.ImageSharp.Processing /// /// /// The pixel format. - public class PatternBrush : IBrush - where TPixel : struct, IPixel + public class PatternBrush : IBrush { /// /// The pattern. /// - private readonly DenseMatrix pattern; + private readonly DenseMatrix pattern; private readonly DenseMatrix patternVector; /// @@ -50,7 +49,7 @@ namespace SixLabors.ImageSharp.Processing /// Color of the fore. /// Color of the back. /// The pattern. - public PatternBrush(TPixel foreColor, TPixel backColor, bool[,] pattern) + public PatternBrush(Color foreColor, Color backColor, bool[,] pattern) : this(foreColor, backColor, new DenseMatrix(pattern)) { } @@ -61,11 +60,11 @@ namespace SixLabors.ImageSharp.Processing /// Color of the fore. /// Color of the back. /// The pattern. - internal PatternBrush(TPixel foreColor, TPixel backColor, in DenseMatrix pattern) + internal PatternBrush(Color foreColor, Color backColor, in DenseMatrix pattern) { var foreColorVector = foreColor.ToVector4(); var backColorVector = backColor.ToVector4(); - this.pattern = new DenseMatrix(pattern.Columns, pattern.Rows); + this.pattern = new DenseMatrix(pattern.Columns, pattern.Rows); this.patternVector = new DenseMatrix(pattern.Columns, pattern.Rows); for (int i = 0; i < pattern.Data.Length; i++) { @@ -86,19 +85,25 @@ namespace SixLabors.ImageSharp.Processing /// Initializes a new instance of the class. /// /// The brush. - internal PatternBrush(PatternBrush brush) + internal PatternBrush(PatternBrush brush) { this.pattern = brush.pattern; this.patternVector = brush.patternVector; } /// - public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) => new PatternBrushApplicator(source, this.pattern, this.patternVector, options); + public BrushApplicator CreateApplicator( + ImageFrame source, + RectangleF region, + GraphicsOptions options) + where TPixel : struct, IPixel => + new PatternBrushApplicator(source, this.pattern, this.patternVector, options); /// /// The pattern brush applicator. /// - private class PatternBrushApplicator : BrushApplicator + private class PatternBrushApplicator : BrushApplicator + where TPixel : struct, IPixel { /// /// The pattern. @@ -107,16 +112,17 @@ namespace SixLabors.ImageSharp.Processing private readonly DenseMatrix patternVector; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The source image. /// The pattern. /// The patternVector. /// The options - public PatternBrushApplicator(ImageFrame source, in DenseMatrix pattern, DenseMatrix patternVector, GraphicsOptions options) + public PatternBrushApplicator(ImageFrame source, in DenseMatrix pattern, DenseMatrix patternVector, GraphicsOptions options) : base(source, options) { - this.pattern = pattern; + this.pattern = new DenseMatrix(pattern.Columns, pattern.Rows); + Color.ToPixel(source.Configuration, pattern.Data, this.pattern.Data); this.patternVector = patternVector; } diff --git a/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs index 20a6833c4..75ca5aa7e 100644 --- a/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs @@ -15,20 +15,18 @@ namespace SixLabors.ImageSharp.Processing /// /// Provides an implementation of a solid brush for painting solid color areas. /// - /// The pixel format. - public class SolidBrush : IBrush - where TPixel : struct, IPixel + public class SolidBrush : IBrush { /// /// The color to paint. /// - private readonly TPixel color; + private readonly Color color; /// /// Initializes a new instance of the class. /// /// The color. - public SolidBrush(TPixel color) + public SolidBrush(Color color) { this.color = color; } @@ -39,18 +37,20 @@ namespace SixLabors.ImageSharp.Processing /// /// The color. /// - public TPixel Color => this.color; + public Color Color => this.color; /// - public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) + public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) + where TPixel : struct, IPixel { - return new SolidBrushApplicator(source, this.color, options); + return new SolidBrushApplicator(source, this.color.ToPixel(), options); } /// /// The solid brush applicator. /// - private class SolidBrushApplicator : BrushApplicator + private class SolidBrushApplicator : BrushApplicator + where TPixel : struct, IPixel { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Color/Color.Conversions.cs b/src/ImageSharp/Color/Color.Conversions.cs index 16d673d85..a6e0717f4 100644 --- a/src/ImageSharp/Color/Color.Conversions.cs +++ b/src/ImageSharp/Color/Color.Conversions.cs @@ -91,5 +91,8 @@ namespace SixLabors.ImageSharp [MethodImpl(InliningOptions.ShortMethod)] internal Bgr24 ToBgr24() => this.data.ToBgr24(); + + [MethodImpl(InliningOptions.ShortMethod)] + internal Vector4 ToVector4() => this.data.ToVector4(); } } \ No newline at end of file From 73f9116a46b5931003339e729e92758b55e353a2 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 21:08:19 +0200 Subject: [PATCH 179/223] Pen, Brush & Processors refactored --- src/ImageSharp.Drawing/Processing/Brushes.cs | 120 ++++----- .../Processing/DrawBezierExtensions.cs | 44 ++-- .../Processing/ImageBrush{TPixel}.cs | 28 +-- .../Processing/PatternBrush{TPixel}.cs | 11 +- src/ImageSharp.Drawing/Processing/Pens.cs | 50 +--- .../Processing/Pen{TPixel}.cs | 18 +- .../Processors/Drawing/FillProcessor.cs | 57 +++-- .../Processors/Drawing/FillRegionProcessor.cs | 63 +++-- .../Processors/Text/DrawTextProcessor.cs | 55 ++++- .../Processing/RecolorBrush{TPixel}.cs | 29 ++- src/ImageSharp/GraphicsOptions.cs | 231 +++++++++--------- 11 files changed, 356 insertions(+), 350 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/Brushes.cs b/src/ImageSharp.Drawing/Processing/Brushes.cs index c5e7a3e9f..bd73e1f1b 100644 --- a/src/ImageSharp.Drawing/Processing/Brushes.cs +++ b/src/ImageSharp.Drawing/Processing/Brushes.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing /// /// A collection of methods for creating generic brushes. /// - /// A New + /// A New public static class Brushes { /// @@ -94,163 +94,131 @@ namespace SixLabors.ImageSharp.Processing /// Create as brush that will paint a solid color /// /// The color. - /// The pixel format. - /// A New - public static SolidBrush Solid(TPixel color) - where TPixel : struct, IPixel - => new SolidBrush(color); + /// A New + public static SolidBrush Solid(Color color) => new SolidBrush(color); /// /// Create as brush that will paint a Percent10 Hatch Pattern with the specified colors /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush Percent10(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, Percent10Pattern); + /// A New + public static PatternBrush Percent10(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, Percent10Pattern); /// /// Create as brush that will paint a Percent10 Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush Percent10(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, Percent10Pattern); + /// A New + public static PatternBrush Percent10(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, Percent10Pattern); /// /// Create as brush that will paint a Percent20 Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush Percent20(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, Percent20Pattern); + /// A New + public static PatternBrush Percent20(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, Percent20Pattern); /// /// Create as brush that will paint a Percent20 Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush Percent20(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, Percent20Pattern); + /// A New + public static PatternBrush Percent20(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, Percent20Pattern); /// /// Create as brush that will paint a Horizontal Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush Horizontal(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, HorizontalPattern); + /// A New + public static PatternBrush Horizontal(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, HorizontalPattern); /// /// Create as brush that will paint a Horizontal Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush Horizontal(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, HorizontalPattern); + /// A New + public static PatternBrush Horizontal(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, HorizontalPattern); /// /// Create as brush that will paint a Min Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush Min(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, MinPattern); + /// A New + public static PatternBrush Min(Color foreColor) => new PatternBrush(foreColor, Color.Transparent, MinPattern); /// /// Create as brush that will paint a Min Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush Min(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, MinPattern); + /// A New + public static PatternBrush Min(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, MinPattern); /// /// Create as brush that will paint a Vertical Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush Vertical(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, VerticalPattern); + /// A New + public static PatternBrush Vertical(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, VerticalPattern); /// /// Create as brush that will paint a Vertical Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush Vertical(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, VerticalPattern); + /// A New + public static PatternBrush Vertical(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, VerticalPattern); /// /// Create as brush that will paint a Forward Diagonal Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush ForwardDiagonal(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, ForwardDiagonalPattern); + /// A New + public static PatternBrush ForwardDiagonal(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, ForwardDiagonalPattern); /// /// Create as brush that will paint a Forward Diagonal Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush ForwardDiagonal(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, ForwardDiagonalPattern); + /// A New + public static PatternBrush ForwardDiagonal(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, ForwardDiagonalPattern); /// /// Create as brush that will paint a Backward Diagonal Hatch Pattern with the specified foreground color and a /// transparent background. /// /// Color of the foreground. - /// The pixel format. - /// A New - public static PatternBrush BackwardDiagonal(TPixel foreColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, NamedColors.Transparent, BackwardDiagonalPattern); + /// A New + public static PatternBrush BackwardDiagonal(Color foreColor) => + new PatternBrush(foreColor, Color.Transparent, BackwardDiagonalPattern); /// /// Create as brush that will paint a Backward Diagonal Hatch Pattern with the specified colors /// /// Color of the foreground. /// Color of the background. - /// The pixel format. - /// A New - public static PatternBrush BackwardDiagonal(TPixel foreColor, TPixel backColor) - where TPixel : struct, IPixel - => new PatternBrush(foreColor, backColor, BackwardDiagonalPattern); + /// A New + public static PatternBrush BackwardDiagonal(Color foreColor, Color backColor) => + new PatternBrush(foreColor, backColor, BackwardDiagonalPattern); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs index 782f5d4d7..991c01293 100644 --- a/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs @@ -15,80 +15,80 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The type of the color. + /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, params PointF[] points) + + => source.Draw(options, new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The type of the color. + /// The image this method extends. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IBrush brush, float thickness, params PointF[] points) + + => source.Draw(new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The type of the color. + /// The image this method extends. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawBeziers(new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, TPixel color, float thickness, params PointF[] points) + + => source.DrawBeziers(new SolidBrush(color), thickness, points); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The type of the color. + /// The image this method extends. /// The options. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawBeziers(options, new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, params PointF[] points) + + => source.DrawBeziers(options, new SolidBrush(color), thickness, points); /// /// Draws the provided points as an open Bezier path with the supplied pen /// - /// The type of the color. + /// The image this method extends. /// The options. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IPen pen, params PointF[] points) - where TPixel : struct, IPixel + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IPen pen, params PointF[] points) + => source.Draw(options, pen, new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path with the supplied pen /// - /// The type of the color. + /// The image this method extends. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IPen pen, params PointF[] points) - where TPixel : struct, IPixel + public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IPen pen, params PointF[] points) + => source.Draw(pen, new Path(new CubicBezierLineSegment(points))); } } diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs index cfb3b2ea4..d5ec1123d 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs @@ -15,40 +15,38 @@ namespace SixLabors.ImageSharp.Processing /// Provides an implementation of an image brush for painting images within areas. /// /// The pixel format. - public class ImageBrush : IBrush - where TPixel : struct, IPixel + public class ImageBrush : IBrush { /// /// The image to paint. /// - private readonly ImageFrame image; + private readonly Image image; /// /// Initializes a new instance of the class. /// /// The image. - public ImageBrush(ImageFrame image) + public ImageBrush(Image image) { this.image = image; } - /// - /// Initializes a new instance of the class. - /// - /// The image. - public ImageBrush(Image image) - : this(image.Frames.RootFrame) + /// + public BrushApplicator CreateApplicator( + ImageFrame source, + RectangleF region, + GraphicsOptions options) + where TPixel : struct, IPixel { + Image specificImage = (Image)this.image; + return new ImageBrushApplicator(source, specificImage.Frames.RootFrame, region, options); } - /// - public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) - => new ImageBrushApplicator(source, this.image, region, options); - /// /// The image brush applicator. /// - private class ImageBrushApplicator : BrushApplicator + private class ImageBrushApplicator : BrushApplicator + where TPixel : struct, IPixel { /// /// The source image. diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs index 249383f3b..0e6675672 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs @@ -97,7 +97,11 @@ namespace SixLabors.ImageSharp.Processing RectangleF region, GraphicsOptions options) where TPixel : struct, IPixel => - new PatternBrushApplicator(source, this.pattern, this.patternVector, options); + new PatternBrushApplicator( + source, + this.pattern.ToPixelMatrix(source.Configuration), + this.patternVector, + options); /// /// The pattern brush applicator. @@ -118,11 +122,10 @@ namespace SixLabors.ImageSharp.Processing /// The pattern. /// The patternVector. /// The options - public PatternBrushApplicator(ImageFrame source, in DenseMatrix pattern, DenseMatrix patternVector, GraphicsOptions options) + public PatternBrushApplicator(ImageFrame source, in DenseMatrix pattern, DenseMatrix patternVector, GraphicsOptions options) : base(source, options) { - this.pattern = new DenseMatrix(pattern.Columns, pattern.Rows); - Color.ToPixel(source.Configuration, pattern.Data, this.pattern.Data); + this.pattern = pattern; this.patternVector = patternVector; } diff --git a/src/ImageSharp.Drawing/Processing/Pens.cs b/src/ImageSharp.Drawing/Processing/Pens.cs index 90253a3cb..4b8f478c9 100644 --- a/src/ImageSharp.Drawing/Processing/Pens.cs +++ b/src/ImageSharp.Drawing/Processing/Pens.cs @@ -21,109 +21,79 @@ namespace SixLabors.ImageSharp.Processing /// /// The color. /// The width. - /// The type of the color. /// The Pen - public static Pen Solid(TPixel color, float width) - where TPixel : struct, IPixel - => new Pen(color, width); + public static Pen Solid(Color color, float width) => new Pen(color, width); /// /// Create a solid pen with out any drawing patterns /// /// The brush. /// The width. - /// The type of the color. /// The Pen - public static Pen Solid(IBrush brush, float width) - where TPixel : struct, IPixel - => new Pen(brush, width); + public static Pen Solid(IBrush brush, float width) => new Pen(brush, width); /// /// Create a pen with a 'Dash' drawing patterns /// /// The color. /// The width. - /// The type of the color. /// The Pen - public static Pen Dash(TPixel color, float width) - where TPixel : struct, IPixel - => new Pen(color, width, DashedPattern); + public static Pen Dash(Color color, float width) => new Pen(color, width, DashedPattern); /// /// Create a pen with a 'Dash' drawing patterns /// /// The brush. /// The width. - /// The type of the color. /// The Pen - public static Pen Dash(IBrush brush, float width) - where TPixel : struct, IPixel - => new Pen(brush, width, DashedPattern); + public static Pen Dash(IBrush brush, float width) => new Pen(brush, width, DashedPattern); /// /// Create a pen with a 'Dot' drawing patterns /// /// The color. /// The width. - /// The type of the color. /// The Pen - public static Pen Dot(TPixel color, float width) - where TPixel : struct, IPixel - => new Pen(color, width, DottedPattern); + public static Pen Dot(Color color, float width) => new Pen(color, width, DottedPattern); /// /// Create a pen with a 'Dot' drawing patterns /// /// The brush. /// The width. - /// The type of the color. /// The Pen - public static Pen Dot(IBrush brush, float width) - where TPixel : struct, IPixel - => new Pen(brush, width, DottedPattern); + public static Pen Dot(IBrush brush, float width) => new Pen(brush, width, DottedPattern); /// /// Create a pen with a 'Dash Dot' drawing patterns /// /// The color. /// The width. - /// The type of the color. /// The Pen - public static Pen DashDot(TPixel color, float width) - where TPixel : struct, IPixel - => new Pen(color, width, DashDotPattern); + public static Pen DashDot(Color color, float width) => new Pen(color, width, DashDotPattern); /// /// Create a pen with a 'Dash Dot' drawing patterns /// /// The brush. /// The width. - /// The type of the color. /// The Pen - public static Pen DashDot(IBrush brush, float width) - where TPixel : struct, IPixel - => new Pen(brush, width, DashDotPattern); + public static Pen DashDot(IBrush brush, float width) => new Pen(brush, width, DashDotPattern); /// /// Create a pen with a 'Dash Dot Dot' drawing patterns /// /// The color. /// The width. - /// The type of the color. /// The Pen - public static Pen DashDotDot(TPixel color, float width) - where TPixel : struct, IPixel - => new Pen(color, width, DashDotDotPattern); + public static Pen DashDotDot(Color color, float width) => new Pen(color, width, DashDotDotPattern); /// /// Create a pen with a 'Dash Dot Dot' drawing patterns /// /// The brush. /// The width. - /// The type of the color. /// The Pen - public static Pen DashDotDot(IBrush brush, float width) - where TPixel : struct, IPixel - => new Pen(brush, width, DashDotDotPattern); + public static Pen DashDotDot(IBrush brush, float width) => new Pen(brush, width, DashDotDotPattern); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs index 26c21a0e5..922394946 100644 --- a/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs @@ -9,7 +9,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Provides a pen that can apply a pattern to a line with a set brush and thickness /// - /// The type of the color. /// /// The pattern will be in to the form of new float[]{ 1f, 2f, 0.5f} this will be /// converted into a pattern that is 3.5 times longer that the width with 3 sections @@ -18,8 +17,7 @@ namespace SixLabors.ImageSharp.Processing /// section 3 will be width/2 long and will be filled /// the the pattern will immediately repeat without gap. /// - public class Pen : IPen - where TPixel : struct, IPixel + public class Pen : IPen { private readonly float[] pattern; @@ -29,8 +27,8 @@ namespace SixLabors.ImageSharp.Processing /// The color. /// The width. /// The pattern. - public Pen(TPixel color, float width, float[] pattern) - : this(new SolidBrush(color), width, pattern) + public Pen(Color color, float width, float[] pattern) + : this(new SolidBrush(color), width, pattern) { } @@ -40,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing /// The brush. /// The width. /// The pattern. - public Pen(IBrush brush, float width, float[] pattern) + public Pen(IBrush brush, float width, float[] pattern) { this.StrokeFill = brush; this.StrokeWidth = width; @@ -52,8 +50,8 @@ namespace SixLabors.ImageSharp.Processing /// /// The color. /// The width. - public Pen(TPixel color, float width) - : this(new SolidBrush(color), width) + public Pen(Color color, float width) + : this(new SolidBrush(color), width) { } @@ -62,13 +60,13 @@ namespace SixLabors.ImageSharp.Processing /// /// The brush. /// The width. - public Pen(IBrush brush, float width) + public Pen(IBrush brush, float width) : this(brush, width, Pens.EmptyPattern) { } /// - public IBrush StrokeFill { get; } + public IBrush StrokeFill { get; } /// public float StrokeWidth { get; } diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs index ed6c86951..8ea1c48cc 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs @@ -13,6 +13,26 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { + public class FillProcessor : IImageProcessor + { + public FillProcessor(IBrush brush, GraphicsOptions options) + { + this.Brush = brush; + this.Options = options; + } + + public IBrush Brush { get; } + + public GraphicsOptions Options { get; } + + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + return new FillProcessor(this); + } + } + /// /// Using the brush as a source of pixels colors blends the brush color with source. /// @@ -20,21 +40,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing internal class FillProcessor : ImageProcessor where TPixel : struct, IPixel { - /// - /// The brush. - /// - private readonly IBrush brush; - private readonly GraphicsOptions options; - - /// - /// Initializes a new instance of the class. - /// - /// The brush to source pixel colors from. - /// The options - public FillProcessor(IBrush brush, GraphicsOptions options) + private readonly FillProcessor definition; + + public FillProcessor(FillProcessor definition) { - this.brush = brush; - this.options = options; + this.definition = definition; } /// @@ -55,11 +65,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + IBrush brush = this.definition.Brush; + GraphicsOptions options = this.definition.Options; + // If there's no reason for blending, then avoid it. - if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) + if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) { ParallelExecutionSettings parallelSettings = configuration.GetParallelSettings().MultiplyMinimumPixelsPerTask(4); + TPixel colorPixel = solidBrush.Color.ToPixel(); + ParallelHelper.IterateRows( workingRect, parallelSettings, @@ -67,7 +82,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing { for (int y = rows.Min; y < rows.Max; y++) { - source.GetPixelRowSpan(y).Slice(minX, width).Fill(solidBrush.Color); + source.GetPixelRowSpan(y).Slice(minX, width).Fill(colorPixel); } }); } @@ -85,10 +100,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width)) - using (BrushApplicator applicator = this.brush.CreateApplicator( + using (BrushApplicator applicator = brush.CreateApplicator( source, sourceRectangle, - this.options)) + options)) { amount.GetSpan().Fill(1f); @@ -109,16 +124,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } } - private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) + private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) { - solidBrush = this.brush as SolidBrush; + solidBrush = this.definition.Brush as SolidBrush; if (solidBrush == null) { return false; } - return this.options.IsOpaqueColorWithoutBlending(solidBrush.Color); + return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); } } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs index 550c021ca..3653102ef 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs @@ -13,24 +13,15 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { - /// - /// Using a brush and a shape fills shape with contents of brush the - /// - /// The type of the color. - /// - internal class FillRegionProcessor : ImageProcessor - where TPixel : struct, IPixel + public class FillRegionProcessor : IImageProcessor { - private const float AntialiasFactor = 1f; - private const int DrawPadding = 1; - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The details how to fill the region of interest. /// The region of interest to be filled. /// The configuration options. - public FillRegionProcessor(IBrush brush, Region region, GraphicsOptions options) + public FillRegionProcessor(IBrush brush, Region region, GraphicsOptions options) { this.Region = region; this.Brush = brush; @@ -40,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing /// /// Gets the brush. /// - public IBrush Brush { get; } + public IBrush Brush { get; } /// /// Gets the region that this processor applies to. @@ -55,10 +46,35 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing /// public GraphicsOptions Options { get; } + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + return new FillRegionProcessor(this); + } + } + + /// + /// Using a brush and a shape fills shape with contents of brush the + /// + /// The type of the color. + /// + internal class FillRegionProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly FillRegionProcessor definition; + + public FillRegionProcessor(FillRegionProcessor definition) + { + this.definition = definition; + } + /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) { - Region region = this.Region; + GraphicsOptions options = this.definition.Options; + IBrush brush = this.definition.Brush; + Region region = this.definition.Region; Rectangle rect = region.Bounds; // Align start/end positions. @@ -84,17 +100,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing // and this can cause missed fills when not using antialiasing.so we offset the pixel grid by 0.5 in the x & y direction thus causing the# // region to align with the pixel grid. float offset = 0.5f; - if (this.Options.Antialias) + if (options.Antialias) { offset = 0f; // we are antialiasing skip offsetting as real antialiasing should take care of offset. - subpixelCount = this.Options.AntialiasSubpixelDepth; + subpixelCount = options.AntialiasSubpixelDepth; if (subpixelCount < 4) { subpixelCount = 4; } } - using (BrushApplicator applicator = this.Brush.CreateApplicator(source, rect, this.Options)) + using (BrushApplicator applicator = brush.CreateApplicator(source, rect, options)) { int scanlineWidth = maxX - minX; using (IMemoryOwner bBuffer = source.MemoryAllocator.Allocate(maxIntersections)) @@ -107,7 +123,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing Span buffer = bBuffer.GetSpan(); Span scanline = bScanline.GetSpan(); - bool isSolidBrushWithoutBlending = this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush); + bool isSolidBrushWithoutBlending = this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush); + TPixel solidBrushColor = isSolidBrushWithoutBlending ? solidBrush.Color.ToPixel() : default; for (int y = minY; y < maxY; y++) { @@ -168,7 +185,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing if (scanlineDirty) { - if (!this.Options.Antialias) + if (!options.Antialias) { bool hasOnes = false; bool hasZeros = false; @@ -190,7 +207,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing { if (hasOnes) { - source.GetPixelRowSpan(y).Slice(minX, scanlineWidth).Fill(solidBrush.Color); + source.GetPixelRowSpan(y).Slice(minX, scanlineWidth).Fill(solidBrushColor); } continue; @@ -204,16 +221,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } } - private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) + private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) { - solidBrush = this.Brush as SolidBrush; + solidBrush = this.definition.Brush as SolidBrush; if (solidBrush == null) { return false; } - return this.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); + return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); } } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs index 266d842bf..016cf56de 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs @@ -15,17 +15,10 @@ using SixLabors.Shapes; namespace SixLabors.ImageSharp.Processing.Processors.Text { - /// - /// Using the brush as a source of pixels colors blends the brush color with source. - /// - /// The pixel format. - internal class DrawTextProcessor : ImageProcessor - where TPixel : struct, IPixel + public class DrawTextProcessor : IImageProcessor { - private CachingGlyphRenderer textRenderer; - /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The options /// The text we want to render @@ -33,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text /// The brush to source pixel colors from. /// The pen to outline text with. /// The location on the image to start drawing the text from. - public DrawTextProcessor(TextGraphicsOptions options, string text, Font font, IBrush brush, IPen pen, PointF location) + public DrawTextProcessor(TextGraphicsOptions options, string text, Font font, IBrush brush, IPen pen, PointF location) { Guard.NotNull(text, nameof(text)); Guard.NotNull(font, nameof(font)); @@ -54,7 +47,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text /// /// Gets the brush. /// - public IBrush Brush { get; } + public IBrush Brush { get; } /// /// Gets the options @@ -69,7 +62,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text /// /// Gets the pen used for outlining the text, if Null then we will not outline /// - public IPen Pen { get; } + public IPen Pen { get; } /// /// Gets the font used to render the text. @@ -81,6 +74,42 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text /// public PointF Location { get; } + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + throw new NotImplementedException(); + } + } + + /// + /// Using the brush as a source of pixels colors blends the brush color with source. + /// + /// The pixel format. + internal class DrawTextProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private CachingGlyphRenderer textRenderer; + + private readonly DrawTextProcessor definition; + + public DrawTextProcessor(DrawTextProcessor definition) + { + this.definition = definition; + } + + private TextGraphicsOptions Options => this.definition.Options; + + private Font Font => this.definition.Font; + + private PointF Location => this.definition.Location; + + private string Text => this.definition.Text; + + private IPen Pen => this.definition.Pen; + + private IBrush Brush => this.definition.Brush; + protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) { base.BeforeImageApply(source, sourceRectangle); @@ -115,7 +144,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text Draw(this.textRenderer.FillOperations, this.Brush); Draw(this.textRenderer.OutlineOperations, this.Pen?.StrokeFill); - void Draw(List operations, IBrush brush) + void Draw(List operations, IBrush brush) { if (operations?.Count > 0) { diff --git a/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs index 09a1ff71f..ff098dce7 100644 --- a/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs @@ -16,16 +16,15 @@ namespace SixLabors.ImageSharp.Processing /// Provides an implementation of a brush that can recolor an image /// /// The pixel format. - public class RecolorBrush : IBrush - where TPixel : struct, IPixel + public class RecolorBrush : IBrush { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Color of the source. /// Color of the target. /// The threshold as a value between 0 and 1. - public RecolorBrush(TPixel sourceColor, TPixel targetColor, float threshold) + public RecolorBrush(Color sourceColor, Color targetColor, float threshold) { this.SourceColor = sourceColor; this.Threshold = threshold; @@ -43,23 +42,33 @@ namespace SixLabors.ImageSharp.Processing /// /// The color of the source. /// - public TPixel SourceColor { get; } + public Color SourceColor { get; } /// /// Gets the target color. /// - public TPixel TargetColor { get; } + public Color TargetColor { get; } /// - public BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) + public BrushApplicator CreateApplicator( + ImageFrame source, + RectangleF region, + GraphicsOptions options) + where TPixel : struct, IPixel { - return new RecolorBrushApplicator(source, this.SourceColor, this.TargetColor, this.Threshold, options); + return new RecolorBrushApplicator( + source, + this.SourceColor.ToPixel(), + this.TargetColor.ToPixel(), + this.Threshold, + options); } /// /// The recolor brush applicator. /// - private class RecolorBrushApplicator : BrushApplicator + private class RecolorBrushApplicator : BrushApplicator + where TPixel : struct, IPixel { /// /// The source color. @@ -79,7 +88,7 @@ namespace SixLabors.ImageSharp.Processing private readonly TPixel targetColorPixel; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The source image. /// Color of the source. diff --git a/src/ImageSharp/GraphicsOptions.cs b/src/ImageSharp/GraphicsOptions.cs index 2d20c1773..537418de2 100644 --- a/src/ImageSharp/GraphicsOptions.cs +++ b/src/ImageSharp/GraphicsOptions.cs @@ -1,141 +1,141 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp -{ - /// - /// Options for influencing the drawing functions. - /// - public struct GraphicsOptions - { - /// - /// Represents the default . - /// - public static readonly GraphicsOptions Default = new GraphicsOptions(true); - - private float? blendPercentage; - - private int? antialiasSubpixelDepth; - - private bool? antialias; - +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + /// + /// Options for influencing the drawing functions. + /// + public struct GraphicsOptions + { + /// + /// Represents the default . + /// + public static readonly GraphicsOptions Default = new GraphicsOptions(true); + + private float? blendPercentage; + + private int? antialiasSubpixelDepth; + + private bool? antialias; + private PixelColorBlendingMode colorBlendingMode; - private PixelAlphaCompositionMode alphaCompositionMode; - - /// - /// Initializes a new instance of the struct. - /// - /// If set to true [enable antialiasing]. - public GraphicsOptions(bool enableAntialiasing) - { + private PixelAlphaCompositionMode alphaCompositionMode; + + /// + /// Initializes a new instance of the struct. + /// + /// If set to true [enable antialiasing]. + public GraphicsOptions(bool enableAntialiasing) + { this.colorBlendingMode = PixelColorBlendingMode.Normal; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = 1; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; + this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = 1; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; } - /// - /// Initializes a new instance of the struct. - /// + /// + /// Initializes a new instance of the struct. + /// /// If set to true [enable antialiasing]. - /// blending percentage to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, float opacity) + /// blending percentage to apply to the drawing operation + public GraphicsOptions(bool enableAntialiasing, float opacity) { Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - + this.colorBlendingMode = PixelColorBlendingMode.Normal; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; + this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = opacity; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; } - /// - /// Initializes a new instance of the struct. - /// + /// + /// Initializes a new instance of the struct. + /// /// If set to true [enable antialiasing]. /// blending percentage to apply to the drawing operation - /// color blending mode to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, float opacity) + /// color blending mode to apply to the drawing operation + public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, float opacity) { Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - + this.colorBlendingMode = blending; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; + this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = opacity; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; } - /// - /// Initializes a new instance of the struct. - /// + /// + /// Initializes a new instance of the struct. + /// /// If set to true [enable antialiasing]. /// blending percentage to apply to the drawing operation /// color blending mode to apply to the drawing operation - /// alpha composition mode to apply to the drawing operation - public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, PixelAlphaCompositionMode composition, float opacity) + /// alpha composition mode to apply to the drawing operation + public GraphicsOptions(bool enableAntialiasing, PixelColorBlendingMode blending, PixelAlphaCompositionMode composition, float opacity) { Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - + this.colorBlendingMode = blending; - this.alphaCompositionMode = composition; - this.blendPercentage = opacity; - this.antialiasSubpixelDepth = 16; - this.antialias = enableAntialiasing; - } - - /// - /// Gets or sets a value indicating whether antialiasing should be applied. - /// - public bool Antialias - { - get => this.antialias ?? true; - set => this.antialias = value; - } - - /// - /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. - /// - public int AntialiasSubpixelDepth - { - get => this.antialiasSubpixelDepth ?? 16; - set => this.antialiasSubpixelDepth = value; - } - - /// - /// Gets or sets a value indicating the blending percentage to apply to the drawing operation - /// - public float BlendPercentage - { - get => (this.blendPercentage ?? 1).Clamp(0, 1); - set => this.blendPercentage = value; - } - - // In the future we could expose a PixelBlender directly on here - // or some forms of PixelBlender factory for each pixel type. Will need - // some API thought post V1. - - /// - /// Gets or sets a value indicating the color blending mode to apply to the drawing operation - /// - public PixelColorBlendingMode ColorBlendingMode - { - get => this.colorBlendingMode; - set => this.colorBlendingMode = value; + this.alphaCompositionMode = composition; + this.blendPercentage = opacity; + this.antialiasSubpixelDepth = 16; + this.antialias = enableAntialiasing; } - /// - /// Gets or sets a value indicating the alpha composition mode to apply to the drawing operation - /// - public PixelAlphaCompositionMode AlphaCompositionMode - { - get => this.alphaCompositionMode; - set => this.alphaCompositionMode = value; + /// + /// Gets or sets a value indicating whether antialiasing should be applied. + /// + public bool Antialias + { + get => this.antialias ?? true; + set => this.antialias = value; + } + + /// + /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. + /// + public int AntialiasSubpixelDepth + { + get => this.antialiasSubpixelDepth ?? 16; + set => this.antialiasSubpixelDepth = value; + } + + /// + /// Gets or sets a value indicating the blending percentage to apply to the drawing operation + /// + public float BlendPercentage + { + get => (this.blendPercentage ?? 1).Clamp(0, 1); + set => this.blendPercentage = value; + } + + // In the future we could expose a PixelBlender directly on here + // or some forms of PixelBlender factory for each pixel type. Will need + // some API thought post V1. + + /// + /// Gets or sets a value indicating the color blending mode to apply to the drawing operation + /// + public PixelColorBlendingMode ColorBlendingMode + { + get => this.colorBlendingMode; + set => this.colorBlendingMode = value; + } + + /// + /// Gets or sets a value indicating the alpha composition mode to apply to the drawing operation + /// + public PixelAlphaCompositionMode AlphaCompositionMode + { + get => this.alphaCompositionMode; + set => this.alphaCompositionMode = value; } /// @@ -149,8 +149,7 @@ namespace SixLabors.ImageSharp /// filling with a solid color, the blending can be avoided by a plain color replacement. /// This method can be useful for such processors to select the fast path. /// - internal bool IsOpaqueColorWithoutBlending(TPixel color) - where TPixel : struct, IPixel + internal bool IsOpaqueColorWithoutBlending(Color color) { if (this.ColorBlendingMode != PixelColorBlendingMode.Normal) { @@ -174,6 +173,6 @@ namespace SixLabors.ImageSharp } return true; - } - } + } + } } \ No newline at end of file From b902e6c99c0bee7f54666c618c699526c353940e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 21:27:04 +0200 Subject: [PATCH 180/223] ImageSharp.Drawing compiles --- .../Processing/ColorStop{TPixel}.cs | 10 +- .../Processing/DrawBezierExtensions.cs | 61 +++++++----- .../Processing/DrawLineExtensions.cs | 61 +++++++----- .../DrawPathCollectionExtensions.cs | 57 ++++++----- .../Processing/DrawPathExtensions.cs | 44 ++++----- .../Processing/DrawPolygonExtensions.cs | 61 +++++++----- .../Processing/DrawRectangleExtensions.cs | 58 +++++++----- .../Processing/DrawTextExtensions.cs | 94 ++++++++++++------- .../EllipticGradientBrush{TPixel}.cs | 21 ++--- .../Processing/FillPathBuilderExtensions.cs | 36 ++++--- .../FillPathCollectionExtensions.cs | 36 ++++--- .../Processing/FillPathExtensions.cs | 28 +++--- .../Processing/FillPolygonExtensions.cs | 38 ++++---- .../Processing/FillRectangleExtensions.cs | 34 +++---- .../Processing/FillRegionExtensions.cs | 52 +++++----- .../Processing/GradientBrushBase{TPixel}.cs | 38 ++++---- .../Processing/LinearGradientBrush{TPixel}.cs | 19 ++-- .../Processing/PatternBrush{TPixel}.cs | 7 +- .../Processing/RadialGradientBrush{TPixel}.cs | 22 ++--- src/ImageSharp/GraphicsOptions.cs | 1 - 20 files changed, 442 insertions(+), 336 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs index 7fd0ba7cd..aee559469 100644 --- a/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs @@ -10,17 +10,15 @@ namespace SixLabors.ImageSharp.Processing /// /// A struct that defines a single color stop. /// - /// The pixel format. [DebuggerDisplay("ColorStop({Ratio} -> {Color}")] - public struct ColorStop - where TPixel : struct, IPixel + public readonly struct ColorStop { /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// Where should it be? 0 is at the start, 1 at the end of the Gradient. /// What color should be used at that point? - public ColorStop(float ratio, TPixel color) + public ColorStop(float ratio, in Color color) { this.Ratio = ratio; this.Color = color; @@ -34,6 +32,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets the color to be used. /// - public TPixel Color { get; } + public Color Color { get; } } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs index 991c01293..85addd5f2 100644 --- a/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs @@ -15,80 +15,93 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, params PointF[] points) - - => source.Draw(options, new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(options, new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The image this method extends. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IBrush brush, float thickness, params PointF[] points) - - => source.Draw(new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(new Pen(brush, thickness), new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The image this method extends. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, TPixel color, float thickness, params PointF[] points) - - => source.DrawBeziers(new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + Color color, + float thickness, + params PointF[] points) => + source.DrawBeziers(new SolidBrush(color), thickness, points); /// /// Draws the provided points as an open Bezier path at the provided thickness with the supplied brush /// - /// The image this method extends. /// The options. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, params PointF[] points) - - => source.DrawBeziers(options, new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + params PointF[] points) => + source.DrawBeziers(options, new SolidBrush(color), thickness, points); /// /// Draws the provided points as an open Bezier path with the supplied pen /// - /// The image this method extends. /// The options. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, GraphicsOptions options, IPen pen, params PointF[] points) - - => source.Draw(options, pen, new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + params PointF[] points) => + source.Draw(options, pen, new Path(new CubicBezierLineSegment(points))); /// /// Draws the provided points as an open Bezier path with the supplied pen /// - /// The image this method extends. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawBeziers(this IImageProcessingContext source, IPen pen, params PointF[] points) - - => source.Draw(pen, new Path(new CubicBezierLineSegment(points))); + public static IImageProcessingContext DrawBeziers( + this IImageProcessingContext source, + IPen pen, + params PointF[] points) => + source.Draw(pen, new Path(new CubicBezierLineSegment(points))); } } diff --git a/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs index 9084b30ef..b7b419be6 100644 --- a/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs @@ -15,80 +15,93 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), new Path(new LinearLineSegment(points))); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(options, new Pen(brush, thickness), new Path(new LinearLineSegment(points))); /// /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush /// - /// The type of the color. /// The image this method extends. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), new Path(new LinearLineSegment(points))); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(new Pen(brush, thickness), new Path(new LinearLineSegment(points))); /// /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush /// - /// The type of the color. /// The image this method extends. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawLines(new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + Color color, + float thickness, + params PointF[] points) => + source.DrawLines(new SolidBrush(color), thickness, points); /// /// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The thickness. /// The points. /// The .> - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawLines(options, new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + params PointF[] points) => + source.DrawLines(options, new SolidBrush(color), thickness, points); /// /// Draws the provided Points as an open Linear path with the supplied pen /// - /// The type of the color. /// The image this method extends. /// The options. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, GraphicsOptions options, IPen pen, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(options, pen, new Path(new LinearLineSegment(points))); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + params PointF[] points) => + source.Draw(options, pen, new Path(new LinearLineSegment(points))); /// /// Draws the provided Points as an open Linear path with the supplied pen /// - /// The type of the color. /// The image this method extends. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawLines(this IImageProcessingContext source, IPen pen, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(pen, new Path(new LinearLineSegment(points))); + public static IImageProcessingContext DrawLines( + this IImageProcessingContext source, + IPen pen, + params PointF[] points) => + source.Draw(pen, new Path(new LinearLineSegment(points))); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs index 0d3abf297..79b4fd0a8 100644 --- a/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs @@ -14,14 +14,16 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the outline of the polygon with the provided pen. /// - /// The type of the color. /// The image this method extends. /// The options. /// The pen. /// The paths. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, IPathCollection paths) - where TPixel : struct, IPixel + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + IPathCollection paths) { foreach (IPath path in paths) { @@ -34,67 +36,76 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the outline of the polygon with the provided pen. /// - /// The type of the color. /// The image this method extends. /// The pen. /// The paths. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPathCollection paths) - where TPixel : struct, IPixel - => source.Draw(GraphicsOptions.Default, pen, paths); + public static IImageProcessingContext + Draw(this IImageProcessingContext source, IPen pen, IPathCollection paths) => + source.Draw(GraphicsOptions.Default, pen, paths); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The shapes. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, IPathCollection paths) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), paths); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + IPathCollection paths) => + source.Draw(options, new Pen(brush, thickness), paths); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The thickness. /// The paths. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IBrush brush, float thickness, IPathCollection paths) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), paths); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + IBrush brush, + float thickness, + IPathCollection paths) => + source.Draw(new Pen(brush, thickness), paths); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The thickness. /// The paths. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, IPathCollection paths) - where TPixel : struct, IPixel - => source.Draw(options, new SolidBrush(color), thickness, paths); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + IPathCollection paths) => + source.Draw(options, new SolidBrush(color), thickness, paths); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The color. /// The thickness. /// The paths. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, TPixel color, float thickness, IPathCollection paths) - where TPixel : struct, IPixel - => source.Draw(new SolidBrush(color), thickness, paths); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + Color color, + float thickness, + IPathCollection paths) => + source.Draw(new SolidBrush(color), thickness, paths); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs index 4dbe942f2..f231f1baa 100644 --- a/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs @@ -15,80 +15,80 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the outline of the polygon with the provided pen. /// - /// The type of the color. + /// The image this method extends. /// The options. /// The pen. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, IPath path) - where TPixel : struct, IPixel + public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, IPath path) + => source.Fill(options, pen.StrokeFill, new ShapePath(path, pen)); /// /// Draws the outline of the polygon with the provided pen. /// - /// The type of the color. + /// The image this method extends. /// The pen. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPath path) - where TPixel : struct, IPixel + public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPath path) + => source.Draw(GraphicsOptions.Default, pen, path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. + /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, IPath path) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), path); + public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, IPath path) + + => source.Draw(options, new Pen(brush, thickness), path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. + /// The image this method extends. /// The brush. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IBrush brush, float thickness, IPath path) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), path); + public static IImageProcessingContext Draw(this IImageProcessingContext source, IBrush brush, float thickness, IPath path) + + => source.Draw(new Pen(brush, thickness), path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. + /// The image this method extends. /// The options. /// The color. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, IPath path) - where TPixel : struct, IPixel - => source.Draw(options, new SolidBrush(color), thickness, path); + public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, Color color, float thickness, IPath path) + + => source.Draw(options, new SolidBrush(color), thickness, path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The type of the color. + /// The image this method extends. /// The color. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, TPixel color, float thickness, IPath path) - where TPixel : struct, IPixel - => source.Draw(new SolidBrush(color), thickness, path); + public static IImageProcessingContext Draw(this IImageProcessingContext source, Color color, float thickness, IPath path) + + => source.Draw(new SolidBrush(color), thickness, path); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs index 4dcfe00aa..324e05e87 100644 --- a/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs @@ -15,80 +15,93 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(options, new Pen(brush, thickness), new Polygon(new LinearLineSegment(points))); /// /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, IBrush brush, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + IBrush brush, + float thickness, + params PointF[] points) => + source.Draw(new Pen(brush, thickness), new Polygon(new LinearLineSegment(points))); /// /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawPolygon(new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + Color color, + float thickness, + params PointF[] points) => + source.DrawPolygon(new SolidBrush(color), thickness, points); /// /// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The thickness. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, params PointF[] points) - where TPixel : struct, IPixel - => source.DrawPolygon(options, new SolidBrush(color), thickness, points); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + params PointF[] points) => + source.DrawPolygon(options, new SolidBrush(color), thickness, points); /// /// Draws the provided Points as a closed Linear Polygon with the provided Pen. /// - /// The type of the color. /// The image this method extends. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, IPen pen, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(GraphicsOptions.Default, pen, new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + IPen pen, + params PointF[] points) => + source.Draw(GraphicsOptions.Default, pen, new Polygon(new LinearLineSegment(points))); /// /// Draws the provided Points as a closed Linear Polygon with the provided Pen. /// - /// The type of the color. /// The image this method extends. /// The options. /// The pen. /// The points. /// The . - public static IImageProcessingContext DrawPolygon(this IImageProcessingContext source, GraphicsOptions options, IPen pen, params PointF[] points) - where TPixel : struct, IPixel - => source.Draw(options, pen, new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext DrawPolygon( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + params PointF[] points) => + source.Draw(options, pen, new Polygon(new LinearLineSegment(points))); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs index 918fb1e73..d0a6c8ccd 100644 --- a/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs @@ -15,80 +15,90 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the outline of the rectangle with the provided pen. /// - /// The type of the color. /// The image this method extends. /// The options. /// The pen. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(options, pen, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + RectangleF shape) => + source.Draw(options, pen, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); /// /// Draws the outline of the rectangle with the provided pen. /// - /// The type of the color. /// The image this method extends. /// The pen. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(GraphicsOptions.Default, pen, shape); + public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, RectangleF shape) => + source.Draw(GraphicsOptions.Default, pen, shape); /// /// Draws the outline of the rectangle with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(options, new Pen(brush, thickness), shape); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + RectangleF shape) => + source.Draw(options, new Pen(brush, thickness), shape); /// /// Draws the outline of the rectangle with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IBrush brush, float thickness, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(new Pen(brush, thickness), shape); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + IBrush brush, + float thickness, + RectangleF shape) => + source.Draw(new Pen(brush, thickness), shape); /// /// Draws the outline of the rectangle with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, TPixel color, float thickness, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(options, new SolidBrush(color), thickness, shape); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + RectangleF shape) => + source.Draw(options, new SolidBrush(color), thickness, shape); /// /// Draws the outline of the rectangle with the provided brush at the provided thickness. /// - /// The type of the color. /// The image this method extends. /// The color. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, TPixel color, float thickness, RectangleF shape) - where TPixel : struct, IPixel - => source.Draw(new SolidBrush(color), thickness, shape); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + Color color, + float thickness, + RectangleF shape) => + source.Draw(new SolidBrush(color), thickness, shape); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs index 46061ce9b..163a676bb 100644 --- a/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs @@ -16,7 +16,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the text onto the the image filled via the brush. /// - /// The type of the color. /// The image this method extends. /// The text. /// The font. @@ -25,14 +24,17 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, string text, Font font, TPixel color, PointF location) - where TPixel : struct, IPixel - => source.DrawText(TextGraphicsOptions.Default, text, font, color, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + string text, + Font font, + Color color, + PointF location) => + source.DrawText(TextGraphicsOptions.Default, text, font, color, location); /// /// Draws the text onto the the image filled via the brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The text. @@ -42,14 +44,18 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, TextGraphicsOptions options, string text, Font font, TPixel color, PointF location) - where TPixel : struct, IPixel - => source.DrawText(options, text, font, Brushes.Solid(color), null, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + TextGraphicsOptions options, + string text, + Font font, + Color color, + PointF location) => + source.DrawText(options, text, font, Brushes.Solid(color), null, location); /// /// Draws the text onto the the image filled via the brush. /// - /// The type of the color. /// The image this method extends. /// The text. /// The font. @@ -58,14 +64,17 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, string text, Font font, IBrush brush, PointF location) - where TPixel : struct, IPixel - => source.DrawText(TextGraphicsOptions.Default, text, font, brush, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + string text, + Font font, + IBrush brush, + PointF location) => + source.DrawText(TextGraphicsOptions.Default, text, font, brush, location); /// /// Draws the text onto the the image filled via the brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The text. @@ -75,14 +84,18 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, TextGraphicsOptions options, string text, Font font, IBrush brush, PointF location) - where TPixel : struct, IPixel - => source.DrawText(options, text, font, brush, null, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + TextGraphicsOptions options, + string text, + Font font, + IBrush brush, + PointF location) => + source.DrawText(options, text, font, brush, null, location); /// /// Draws the text onto the the image outlined via the pen. /// - /// The type of the color. /// The image this method extends. /// The text. /// The font. @@ -91,14 +104,17 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, string text, Font font, IPen pen, PointF location) - where TPixel : struct, IPixel - => source.DrawText(TextGraphicsOptions.Default, text, font, pen, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + string text, + Font font, + IPen pen, + PointF location) => + source.DrawText(TextGraphicsOptions.Default, text, font, pen, location); /// /// Draws the text onto the the image outlined via the pen. /// - /// The type of the color. /// The image this method extends. /// The options. /// The text. @@ -108,14 +124,18 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, TextGraphicsOptions options, string text, Font font, IPen pen, PointF location) - where TPixel : struct, IPixel - => source.DrawText(options, text, font, null, pen, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + TextGraphicsOptions options, + string text, + Font font, + IPen pen, + PointF location) => + source.DrawText(options, text, font, null, pen, location); /// /// Draws the text onto the the image filled via the brush then outlined via the pen. /// - /// The type of the color. /// The image this method extends. /// The text. /// The font. @@ -125,14 +145,18 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, string text, Font font, IBrush brush, IPen pen, PointF location) - where TPixel : struct, IPixel - => source.DrawText(TextGraphicsOptions.Default, text, font, brush, pen, location); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + string text, + Font font, + IBrush brush, + IPen pen, + PointF location) => + source.DrawText(TextGraphicsOptions.Default, text, font, brush, pen, location); /// /// Draws the text using the default resolution of 72dpi onto the the image filled via the brush then outlined via the pen. /// - /// The type of the color. /// The image this method extends. /// The options. /// The text. @@ -143,8 +167,14 @@ namespace SixLabors.ImageSharp.Processing /// /// The . /// - public static IImageProcessingContext DrawText(this IImageProcessingContext source, TextGraphicsOptions options, string text, Font font, IBrush brush, IPen pen, PointF location) - where TPixel : struct, IPixel - => source.ApplyProcessor(new DrawTextProcessor(options, text, font, brush, pen, location)); + public static IImageProcessingContext DrawText( + this IImageProcessingContext source, + TextGraphicsOptions options, + string text, + Font font, + IBrush brush, + IPen pen, + PointF location) => + source.ApplyProcessor(new DrawTextProcessor(options, text, font, brush, pen, location)); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs index 64901c8e8..4a8ce44db 100644 --- a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs @@ -14,9 +14,7 @@ namespace SixLabors.ImageSharp.Processing /// a point on the longest extension of the ellipse and /// the ratio between longest and shortest extension. /// - /// The Pixel format that is used. - public sealed class EllipticGradientBrush : GradientBrushBase - where TPixel : struct, IPixel + public sealed class EllipticGradientBrush : GradientBrushBase { private readonly PointF center; @@ -24,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing private readonly float axisRatio; - /// + /// /// The center of the elliptical gradient and 0 for the color stops. /// The end point of the reference axis of the ellipse. /// @@ -39,7 +37,7 @@ namespace SixLabors.ImageSharp.Processing PointF referenceAxisEnd, float axisRatio, GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) + params ColorStop[] colorStops) : base(repetitionMode, colorStops) { this.center = center; @@ -47,12 +45,12 @@ namespace SixLabors.ImageSharp.Processing this.axisRatio = axisRatio; } - /// - public override BrushApplicator CreateApplicator( + /// + public override BrushApplicator CreateApplicator( ImageFrame source, RectangleF region, GraphicsOptions options) => - new RadialGradientBrushApplicator( + new RadialGradientBrushApplicator( source, options, this.center, @@ -62,7 +60,8 @@ namespace SixLabors.ImageSharp.Processing this.RepetitionMode); /// - private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase + private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase + where TPixel : struct, IPixel { private readonly PointF center; @@ -85,7 +84,7 @@ namespace SixLabors.ImageSharp.Processing private readonly float referenceRadiusSquared; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target image /// The options @@ -102,7 +101,7 @@ namespace SixLabors.ImageSharp.Processing PointF center, PointF referenceAxisEnd, float axisRatio, - ColorStop[] colorStops, + ColorStop[] colorStops, GradientRepetitionMode repetitionMode) : base(target, options, colorStops, repetitionMode) { diff --git a/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs index ff4de3ff8..ca7eab93f 100644 --- a/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs @@ -15,14 +15,16 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The graphics options. /// The brush. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, Action path) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + Action path) { var pb = new PathBuilder(); path(pb); @@ -33,38 +35,42 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Action path) - where TPixel : struct, IPixel - => source.Fill(GraphicsOptions.Default, brush, path); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + IBrush brush, + Action path) => + source.Fill(GraphicsOptions.Default, brush, path); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, TPixel color, Action path) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), path); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + Action path) => + source.Fill(options, new SolidBrush(color), path); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color, Action path) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), path); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + Color color, + Action path) => + source.Fill(new SolidBrush(color), path); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs index da2dd35b6..d750ff455 100644 --- a/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs @@ -14,14 +14,16 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The graphics options. /// The brush. /// The shapes. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, IPathCollection paths) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + IPathCollection paths) { foreach (IPath s in paths) { @@ -34,38 +36,42 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The paths. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPathCollection paths) - where TPixel : struct, IPixel - => source.Fill(GraphicsOptions.Default, brush, paths); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + IBrush brush, + IPathCollection paths) => + source.Fill(GraphicsOptions.Default, brush, paths); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The paths. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, TPixel color, IPathCollection paths) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), paths); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + IPathCollection paths) => + source.Fill(options, new SolidBrush(color), paths); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The color. /// The paths. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color, IPathCollection paths) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), paths); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + Color color, + IPathCollection paths) => + source.Fill(new SolidBrush(color), paths); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs index da1062111..7cf67612a 100644 --- a/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs @@ -15,51 +15,51 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The graphics options. /// The brush. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, IPath path) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, IPath path) + => source.Fill(options, brush, new ShapeRegion(path)); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The brush. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPath path) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPath path) + => source.Fill(GraphicsOptions.Default, brush, new ShapeRegion(path)); /// /// Flood fills the image in the shape of the provided polygon with the specified brush.. /// - /// The type of the color. + /// The image this method extends. /// The options. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, TPixel color, IPath path) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), path); + public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, Color color, IPath path) + + => source.Fill(options, new SolidBrush(color), path); /// /// Flood fills the image in the shape of the provided polygon with the specified brush.. /// - /// The type of the color. + /// The image this method extends. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color, IPath path) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), path); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, IPath path) + + => source.Fill(new SolidBrush(color), path); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs index 970ca2264..8150c7381 100644 --- a/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs @@ -15,51 +15,57 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of a Linear polygon described by the points /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The points. /// The . - public static IImageProcessingContext FillPolygon(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, params PointF[] points) - where TPixel : struct, IPixel - => source.Fill(options, brush, new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext FillPolygon( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + params PointF[] points) => + source.Fill(options, brush, new Polygon(new LinearLineSegment(points))); /// /// Flood fills the image in the shape of a Linear polygon described by the points /// - /// The type of the color. /// The image this method extends. /// The brush. /// The points. /// The . - public static IImageProcessingContext FillPolygon(this IImageProcessingContext source, IBrush brush, params PointF[] points) - where TPixel : struct, IPixel - => source.Fill(brush, new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext FillPolygon( + this IImageProcessingContext source, + IBrush brush, + params PointF[] points) => + source.Fill(brush, new Polygon(new LinearLineSegment(points))); /// /// Flood fills the image in the shape of a Linear polygon described by the points /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The points. /// The . - public static IImageProcessingContext FillPolygon(this IImageProcessingContext source, GraphicsOptions options, TPixel color, params PointF[] points) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext FillPolygon( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + params PointF[] points) => + source.Fill(options, new SolidBrush(color), new Polygon(new LinearLineSegment(points))); /// /// Flood fills the image in the shape of a Linear polygon described by the points /// - /// The type of the color. /// The image this method extends. /// The color. /// The points. /// The . - public static IImageProcessingContext FillPolygon(this IImageProcessingContext source, TPixel color, params PointF[] points) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), new Polygon(new LinearLineSegment(points))); + public static IImageProcessingContext FillPolygon( + this IImageProcessingContext source, + Color color, + params PointF[] points) => + source.Fill(new SolidBrush(color), new Polygon(new LinearLineSegment(points))); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs index 26bf214f7..ad512015e 100644 --- a/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs @@ -15,51 +15,53 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided rectangle with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The brush. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, RectangleF shape) - where TPixel : struct, IPixel - => source.Fill(options, brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + RectangleF shape) => + source.Fill(options, brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); /// /// Flood fills the image in the shape of the provided rectangle with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The brush. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, RectangleF shape) - where TPixel : struct, IPixel - => source.Fill(brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); + public static IImageProcessingContext + Fill(this IImageProcessingContext source, IBrush brush, RectangleF shape) => + source.Fill(brush, new RectangularPolygon(shape.X, shape.Y, shape.Width, shape.Height)); /// /// Flood fills the image in the shape of the provided rectangle with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The options. /// The color. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, TPixel color, RectangleF shape) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), shape); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + RectangleF shape) => + source.Fill(options, new SolidBrush(color), shape); /// /// Flood fills the image in the shape of the provided rectangle with the specified brush. /// - /// The type of the color. /// The image this method extends. /// The color. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color, RectangleF shape) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), shape); + public static IImageProcessingContext + Fill(this IImageProcessingContext source, Color color, RectangleF shape) => + source.Fill(new SolidBrush(color), shape); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs b/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs index e566d0323..457ad98b0 100644 --- a/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs @@ -15,85 +15,85 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The details how to fill the region of interest. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) + => source.Fill(GraphicsOptions.Default, brush); /// /// Flood fills the image with the specified color. /// - /// The type of the color. + /// The image this method extends. /// The color. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color) + + => source.Fill(new SolidBrush(color)); /// /// Flood fills the image with in the region with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The brush. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Region region) - where TPixel : struct, IPixel + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Region region) + => source.Fill(GraphicsOptions.Default, brush, region); /// /// Flood fills the image with in the region with the specified color. /// - /// The type of the color. + /// The image this method extends. /// The options. /// The color. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, TPixel color, Region region) - where TPixel : struct, IPixel - => source.Fill(options, new SolidBrush(color), region); + public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, Color color, Region region) + + => source.Fill(options, new SolidBrush(color), region); /// /// Flood fills the image with in the region with the specified color. /// - /// The type of the color. + /// The image this method extends. /// The color. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, TPixel color, Region region) - where TPixel : struct, IPixel - => source.Fill(new SolidBrush(color), region); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, Region region) + + => source.Fill(new SolidBrush(color), region); /// /// Flood fills the image with in the region with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The graphics options. /// The brush. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, Region region) - where TPixel : struct, IPixel - => source.ApplyProcessor(new FillRegionProcessor(brush, region, options)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, Region region) + + => source.ApplyProcessor(new FillRegionProcessor(brush, region, options)); /// /// Flood fills the image with the specified brush. /// - /// The type of the color. + /// The image this method extends. /// The graphics options. /// The details how to fill the region of interest. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush) - where TPixel : struct, IPixel - => source.ApplyProcessor(new FillProcessor(brush, options)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush) + + => source.ApplyProcessor(new FillProcessor(brush, options)); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs index 2dfae9e8f..a877ea96c 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs @@ -13,16 +13,14 @@ namespace SixLabors.ImageSharp.Processing /// /// Base class for Gradient brushes /// - /// The pixel format - public abstract class GradientBrushBase : IBrush - where TPixel : struct, IPixel + public abstract class GradientBrushBase : IBrush { - /// + /// /// Defines how the colors are repeated beyond the interval [0..1] /// The gradient colors. protected GradientBrushBase( GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) + params ColorStop[] colorStops) { this.RepetitionMode = repetitionMode; this.ColorStops = colorStops; @@ -36,25 +34,27 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets the list of color stops for this gradient. /// - protected ColorStop[] ColorStops { get; } + protected ColorStop[] ColorStops { get; } - /// - public abstract BrushApplicator CreateApplicator( + /// + public abstract BrushApplicator CreateApplicator( ImageFrame source, RectangleF region, - GraphicsOptions options); + GraphicsOptions options) + where TPixel : struct, IPixel; /// /// Base class for gradient brush applicators /// - protected abstract class GradientBrushApplicatorBase : BrushApplicator + protected abstract class GradientBrushApplicatorBase : BrushApplicator + where TPixel : struct, IPixel { - private readonly ColorStop[] colorStops; + private readonly ColorStop[] colorStops; private readonly GradientRepetitionMode repetitionMode; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target. /// The options. @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Processing protected GradientBrushApplicatorBase( ImageFrame target, GraphicsOptions options, - ColorStop[] colorStops, + ColorStop[] colorStops, GradientRepetitionMode repetitionMode) : base(target, options) { @@ -111,11 +111,11 @@ namespace SixLabors.ImageSharp.Processing throw new ArgumentOutOfRangeException(); } - (ColorStop from, ColorStop to) = this.GetGradientSegment(positionOnCompleteGradient); + (ColorStop from, ColorStop to) = this.GetGradientSegment(positionOnCompleteGradient); if (from.Color.Equals(to.Color)) { - return from.Color; + return from.Color.ToPixel(); } else { @@ -150,14 +150,14 @@ namespace SixLabors.ImageSharp.Processing /// protected abstract float PositionOnGradient(float x, float y); - private (ColorStop from, ColorStop to) GetGradientSegment( + private (ColorStop from, ColorStop to) GetGradientSegment( float positionOnCompleteGradient) { - ColorStop localGradientFrom = this.colorStops[0]; - ColorStop localGradientTo = default; + ColorStop localGradientFrom = this.colorStops[0]; + ColorStop localGradientTo = default; // TODO: ensure colorStops has at least 2 items (technically 1 would be okay, but that's no gradient) - foreach (ColorStop colorStop in this.colorStops) + foreach (ColorStop colorStop in this.colorStops) { localGradientTo = colorStop; diff --git a/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs index efdc852f2..1a6f8d79a 100644 --- a/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs @@ -14,15 +14,15 @@ namespace SixLabors.ImageSharp.Processing /// - a set of colors in relative distances to each other. /// /// The pixel format - public sealed class LinearGradientBrush : GradientBrushBase - where TPixel : struct, IPixel + public sealed class LinearGradientBrush : GradientBrushBase + { private readonly PointF p1; private readonly PointF p2; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Start point /// End point @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Processing PointF p1, PointF p2, GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) + params ColorStop[] colorStops) : base(repetitionMode, colorStops) { this.p1 = p1; @@ -40,13 +40,14 @@ namespace SixLabors.ImageSharp.Processing } /// - public override BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) - => new LinearGradientBrushApplicator(source, this.p1, this.p2, this.ColorStops, this.RepetitionMode, options); + public override BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) + => new LinearGradientBrushApplicator(source, this.p1, this.p2, this.ColorStops, this.RepetitionMode, options); /// /// The linear gradient brush applicator. /// - private sealed class LinearGradientBrushApplicator : GradientBrushApplicatorBase + private sealed class LinearGradientBrushApplicator : GradientBrushApplicatorBase + where TPixel : struct, IPixel { private readonly PointF start; @@ -83,7 +84,7 @@ namespace SixLabors.ImageSharp.Processing private readonly float length; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The source /// start point of the gradient @@ -95,7 +96,7 @@ namespace SixLabors.ImageSharp.Processing ImageFrame source, PointF start, PointF end, - ColorStop[] colorStops, + ColorStop[] colorStops, GradientRepetitionMode repetitionMode, GraphicsOptions options) : base(source, options, colorStops, repetitionMode) diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs index 0e6675672..21690055e 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs @@ -34,7 +34,6 @@ namespace SixLabors.ImageSharp.Processing /// 0 /// /// - /// The pixel format. public class PatternBrush : IBrush { /// @@ -44,7 +43,7 @@ namespace SixLabors.ImageSharp.Processing private readonly DenseMatrix patternVector; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Color of the fore. /// Color of the back. @@ -55,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Color of the fore. /// Color of the back. @@ -85,7 +84,7 @@ namespace SixLabors.ImageSharp.Processing /// Initializes a new instance of the class. /// /// The brush. - internal PatternBrush(PatternBrush brush) + internal PatternBrush(PatternBrush brush) { this.pattern = brush.pattern; this.patternVector = brush.patternVector; diff --git a/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs index d33d09993..84a97e7d1 100644 --- a/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs @@ -11,15 +11,14 @@ namespace SixLabors.ImageSharp.Processing /// /// A Circular Gradient Brush, defined by center point and radius. /// - /// The pixel format. - public sealed class RadialGradientBrush : GradientBrushBase - where TPixel : struct, IPixel + public sealed class RadialGradientBrush : GradientBrushBase + { private readonly PointF center; private readonly float radius; - /// + /// /// The center of the circular gradient and 0 for the color stops. /// The radius of the circular gradient and 1 for the color stops. /// Defines how the colors in the gradient are repeated. @@ -28,19 +27,19 @@ namespace SixLabors.ImageSharp.Processing PointF center, float radius, GradientRepetitionMode repetitionMode, - params ColorStop[] colorStops) + params ColorStop[] colorStops) : base(repetitionMode, colorStops) { this.center = center; this.radius = radius; } - /// - public override BrushApplicator CreateApplicator( + /// + public override BrushApplicator CreateApplicator( ImageFrame source, RectangleF region, GraphicsOptions options) => - new RadialGradientBrushApplicator( + new RadialGradientBrushApplicator( source, options, this.center, @@ -49,14 +48,15 @@ namespace SixLabors.ImageSharp.Processing this.RepetitionMode); /// - private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase + private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase + where TPixel : struct, IPixel { private readonly PointF center; private readonly float radius; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target image /// The options. @@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Processing GraphicsOptions options, PointF center, float radius, - ColorStop[] colorStops, + ColorStop[] colorStops, GradientRepetitionMode repetitionMode) : base(target, options, colorStops, repetitionMode) { diff --git a/src/ImageSharp/GraphicsOptions.cs b/src/ImageSharp/GraphicsOptions.cs index 537418de2..4d5bf6d51 100644 --- a/src/ImageSharp/GraphicsOptions.cs +++ b/src/ImageSharp/GraphicsOptions.cs @@ -141,7 +141,6 @@ namespace SixLabors.ImageSharp /// /// Evaluates if a given SOURCE color can completely replace a BACKDROP color given the current blending and composition settings. /// - /// The pixel format /// the color /// true if the color can be considered opaque /// From 8271ef18c9225e7ece42561413accf10d63dc09c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 21:52:33 +0200 Subject: [PATCH 181/223] everything builds --- .../Drawing/DrawBeziers.cs | 2 +- .../Drawing/DrawLines.cs | 2 +- .../Drawing/DrawPolygon.cs | 2 +- .../ImageSharp.Benchmarks/Drawing/DrawText.cs | 4 +- .../Drawing/DrawTextOutline.cs | 23 +++- .../Drawing/DrawBezierTests.cs | 2 +- .../Drawing/DrawComplexPolygonTests.cs | 2 +- .../Drawing/DrawLinesTests.cs | 12 +- .../ImageSharp.Tests/Drawing/DrawPathTests.cs | 4 +- .../Drawing/DrawPolygonTests.cs | 2 +- .../Drawing/FillComplexPolygonTests.cs | 2 +- .../Drawing/FillEllipticGradientBrushTest.cs | 36 +++--- .../Drawing/FillLinearGradientBrushTests.cs | 104 +++++++++--------- .../Drawing/FillPatternBrushTests.cs | 2 +- .../Drawing/FillPolygonTests.cs | 12 +- .../Drawing/FillRadialGradientBrushTests.cs | 14 +-- .../Drawing/FillRegionProcessorTests.cs | 11 +- .../Drawing/FillSolidBrushTests.cs | 22 ++-- .../Drawing/Paths/DrawPathCollection.cs | 16 +-- .../Drawing/Paths/FillPath.cs | 16 +-- .../Drawing/Paths/FillPathCollection.cs | 16 +-- .../Drawing/Paths/FillPolygon.cs | 16 +-- .../Drawing/Paths/FillRectangle.cs | 16 +-- .../Drawing/RecolorImageTests.cs | 4 +- .../Drawing/SolidBezierTests.cs | 2 +- .../Drawing/SolidFillBlendedShapesTests.cs | 26 ++--- .../ImageSharp.Tests/Drawing/Text/DrawText.cs | 70 ++++++------ .../Drawing/Text/DrawTextOnImageTests.cs | 12 +- tests/ImageSharp.Tests/Issues/Issue412.cs | 6 +- .../ImageProviders/SolidProvider.cs | 3 +- .../TestUtilities/TestImageExtensions.cs | 14 +++ 31 files changed, 248 insertions(+), 227 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs index 0a343864d..8999afaed 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawBeziers.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Benchmarks graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) { graphics.DrawBeziers(pen, new[] { new PointF(10, 500), diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs index 00942cc36..408e87f9e 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawLines.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Benchmarks graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) { graphics.DrawLines(pen, new[] { new PointF(10, 10), diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs index dcaf4bae6..2b4cff8cb 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawPolygon.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) { graphics.DrawPolygon(pen, new[] { new PointF(10, 10), diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs index 8c840d8c3..28f410e7d 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Benchmarks using (var image = new Image(800, 800)) { var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); - image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10)))); + image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10)))); } } @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Benchmarks image.Mutate(x => DrawTextOldVersion(x, new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10))); } - IImageProcessingContext DrawTextOldVersion(IImageProcessingContext source, TextGraphicsOptions options, string text, SixLabors.Fonts.Font font, IBrush brush, IPen pen, SixLabors.Primitives.PointF location) + IImageProcessingContext DrawTextOldVersion(IImageProcessingContext source, TextGraphicsOptions options, string text, SixLabors.Fonts.Font font, IBrush brush, IPen pen, SixLabors.Primitives.PointF location) where TPixel : struct, IPixel { float dpiX = 72; diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs index ee17adbb5..658590e2d 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Benchmarks { graphics.InterpolationMode = InterpolationMode.Default; graphics.SmoothingMode = SmoothingMode.AntiAlias; - using (var pen = new Pen(System.Drawing.Color.HotPink, 10)) + using (var pen = new System.Drawing.Pen(System.Drawing.Color.HotPink, 10)) using (var font = new Font("Arial", 12, GraphicsUnit.Point)) using (var gp = new GraphicsPath()) { @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Benchmarks using (var image = new Image(800, 800)) { var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); - image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, null, Processing.Pens.Solid(Rgba32.HotPink, 10), new SixLabors.Primitives.PointF(10, 10)))); + image.Mutate(x => x.ApplyProcessor(new DrawTextProcessor(new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, null, Processing.Pens.Solid(Rgba32.HotPink, 10), new SixLabors.Primitives.PointF(10, 10)))); } } @@ -53,10 +53,25 @@ namespace SixLabors.ImageSharp.Benchmarks using (var image = new Image(800, 800)) { var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); - image.Mutate(x => DrawTextOldVersion(x, new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, null, Processing.Pens.Solid(Rgba32.HotPink, 10), new SixLabors.Primitives.PointF(10, 10))); + image.Mutate( + x => DrawTextOldVersion( + x, + new TextGraphicsOptions(true) { WrapTextWidth = 780 }, + TextToRender, + font, + null, + Processing.Pens.Solid(Rgba32.HotPink, 10), + new SixLabors.Primitives.PointF(10, 10))); } - IImageProcessingContext DrawTextOldVersion(IImageProcessingContext source, TextGraphicsOptions options, string text, SixLabors.Fonts.Font font, IBrush brush, IPen pen, SixLabors.Primitives.PointF location) + IImageProcessingContext DrawTextOldVersion( + IImageProcessingContext source, + TextGraphicsOptions options, + string text, + SixLabors.Fonts.Font font, + IBrush brush, + IPen pen, + SixLabors.Primitives.PointF location) where TPixel : struct, IPixel { var style = new SixLabors.Fonts.RendererOptions(font, options.DpiX, options.DpiY, location) diff --git a/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs index 0f29728c9..4ccc7fd35 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawBezierTests.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; - provider.RunValidatingProcessorTest( x => x.DrawBeziers(color.ToPixel(), 5f, points), + provider.RunValidatingProcessorTest( x => x.DrawBeziers(color, 5f, points), testDetails, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); diff --git a/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs index b6e105a19..f28f3345f 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawComplexPolygonTests.cs @@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing testDetails += "_Dashed"; } - Pen pen = dashed ? Pens.Dash(color.ToPixel(), 5f) : Pens.Solid(color.ToPixel(), 5f); + Pen pen = dashed ? Pens.Dash(color, 5f) : Pens.Solid(color, 5f); provider.RunValidatingProcessorTest( x => x.Draw(pen, clipped), diff --git a/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs b/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs index c225b921e..12eb150b1 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawLinesTests.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = new Pen(color.ToPixel(), thickness); + Pen pen = new Pen(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.Dash(color.ToPixel(), thickness); + Pen pen = Pens.Dash(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.Dot(color.ToPixel(), thickness); + Pen pen = Pens.Dot(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.DashDot(color.ToPixel(), thickness); + Pen pen = Pens.DashDot(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha); - Pen pen = Pens.DashDotDot(color.ToPixel(), thickness); + Pen pen = Pens.DashDotDot(color, thickness); DrawLinesImpl(provider, colorName, alpha, thickness, antialias, pen); } @@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing float alpha, float thickness, bool antialias, - Pen pen) + Pen pen) where TPixel : struct, IPixel { SixLabors.Primitives.PointF[] simplePath = { new Vector2(10, 10), new Vector2(200, 150), new Vector2(50, 300) }; diff --git a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs index c638107b8..5e9743c31 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; provider.RunValidatingProcessorTest( - x => x.Draw(color.ToPixel(), thickness, path), + x => x.Draw(color, thickness, path), testDetails, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); @@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing where TPixel : struct, IPixel { Color color = Color.White; - Pen pen = Pens.Solid(color.ToPixel(), 5f); + Pen pen = Pens.Solid(color, 5f); provider.RunValidatingProcessorTest( x => diff --git a/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs index 8a0f25667..b7c54fdbd 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawPolygonTests.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing FormattableString outputDetails = $"{colorName}_A({alpha})_T({thickness}){aa}"; provider.RunValidatingProcessorTest( - c => c.DrawPolygon(options, color.ToPixel(), thickness, simplePath), + c => c.DrawPolygon(options, color, thickness, simplePath), outputDetails, appendSourceFileOrDescription: false); } diff --git a/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs index 3887cb9a7..d6c85cd1d 100644 --- a/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillComplexPolygonTests.cs @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing } provider.RunValidatingProcessorTest( - x => x.Fill(color.ToPixel(), clipped), + x => x.Fill(color, clipped), testDetails, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); diff --git a/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs b/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs index fa4d4a709..c61f770c9 100644 --- a/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs +++ b/tests/ImageSharp.Tests/Drawing/FillEllipticGradientBrushTest.cs @@ -23,18 +23,18 @@ namespace SixLabors.ImageSharp.Tests.Drawing TestImageProvider provider) where TPixel : struct, IPixel { - TPixel red = NamedColors.Red; + Color red = Color.Red; using (Image image = provider.GetImage()) { var unicolorLinearGradientBrush = - new EllipticGradientBrush( + new EllipticGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(10, 0), 1.0f, GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, red)); + new ColorStop(0, red), + new ColorStop(1, red)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); @@ -58,22 +58,22 @@ namespace SixLabors.ImageSharp.Tests.Drawing float ratio) where TPixel : struct, IPixel { - TPixel yellow = NamedColors.Yellow; - TPixel red = NamedColors.Red; - TPixel black = NamedColors.Black; + Color yellow = Color.Yellow; + Color red = Color.Red; + Color black = Color.Black; provider.VerifyOperation( TolerantComparer, image => { - var unicolorLinearGradientBrush = new EllipticGradientBrush( + var unicolorLinearGradientBrush = new EllipticGradientBrush( new SixLabors.Primitives.Point(image.Width / 2, image.Height / 2), new SixLabors.Primitives.Point(image.Width / 2, (image.Width * 2) / 3), ratio, GradientRepetitionMode.None, - new ColorStop(0, yellow), - new ColorStop(1, red), - new ColorStop(1, black)); + new ColorStop(0, yellow), + new ColorStop(1, red), + new ColorStop(1, black)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); }, @@ -114,9 +114,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing TolerantComparer, image => { - TPixel yellow = NamedColors.Yellow; - TPixel red = NamedColors.Red; - TPixel black = NamedColors.Black; + Color yellow = Color.Yellow; + Color red = Color.Red; + Color black = Color.Black; var center = new SixLabors.Primitives.Point(image.Width / 2, image.Height / 2); @@ -128,14 +128,14 @@ namespace SixLabors.ImageSharp.Tests.Drawing int axisX = center.X + (int)-(offsetY * sin); int axisY = center.Y + (int)(offsetY * cos); - var unicolorLinearGradientBrush = new EllipticGradientBrush( + var unicolorLinearGradientBrush = new EllipticGradientBrush( center, new SixLabors.Primitives.Point(axisX, axisY), ratio, GradientRepetitionMode.None, - new ColorStop(0, yellow), - new ColorStop(1, red), - new ColorStop(1, black)); + new ColorStop(0, yellow), + new ColorStop(1, red), + new ColorStop(1, black)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); }, diff --git a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs index 0f4a98a24..5d1442e79 100644 --- a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs @@ -29,14 +29,14 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (Image image = provider.GetImage()) { - TPixel red = NamedColors.Red; + Color red = Color.Red; - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(10, 0), GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, red)); + new ColorStop(0, red), + new ColorStop(1, red)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); @@ -58,12 +58,12 @@ namespace SixLabors.ImageSharp.Tests.Drawing TolerantComparer, image => { - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(image.Width, 0), GradientRepetitionMode.None, - new ColorStop(0, NamedColors.Blue), - new ColorStop(1, NamedColors.Yellow)); + new ColorStop(0, Color.Blue), + new ColorStop(1, Color.Yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); }, @@ -79,15 +79,15 @@ namespace SixLabors.ImageSharp.Tests.Drawing TolerantComparer, image => { - TPixel red = NamedColors.Red; - TPixel yellow = NamedColors.Yellow; + Color red = Color.Red; + Color yellow = Color.Yellow; - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(image.Width, 0), GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); }, @@ -109,15 +109,15 @@ namespace SixLabors.ImageSharp.Tests.Drawing TolerantComparer, image => { - TPixel red = NamedColors.Red; - TPixel yellow = NamedColors.Yellow; + Color red = Color.Red; + Color yellow = Color.Yellow; - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(image.Width / 10, 0), repetitionMode, - new ColorStop(0, red), - new ColorStop(1, yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); }, @@ -140,26 +140,26 @@ namespace SixLabors.ImageSharp.Tests.Drawing // ensure the input data is valid Assert.True(pattern.Length > 0); - TPixel black = NamedColors.Black; - TPixel white = NamedColors.White; + Color black = Color.Black; + Color white = Color.White; // create the input pattern: 0, followed by each of the arguments twice, followed by 1.0 - toggling black and white. - ColorStop[] colorStops = - Enumerable.Repeat(new ColorStop(0, black), 1) + ColorStop[] colorStops = + Enumerable.Repeat(new ColorStop(0, black), 1) .Concat( pattern .SelectMany((f, index) => new[] { - new ColorStop(f, index % 2 == 0 ? black : white), - new ColorStop(f, index % 2 == 0 ? white : black) + new ColorStop(f, index % 2 == 0 ? black : white), + new ColorStop(f, index % 2 == 0 ? white : black) })) - .Concat(Enumerable.Repeat(new ColorStop(1, pattern.Length % 2 == 0 ? black : white), 1)) + .Concat(Enumerable.Repeat(new ColorStop(1, pattern.Length % 2 == 0 ? black : white), 1)) .ToArray(); using (Image image = provider.GetImage()) { var unicolorLinearGradientBrush = - new LinearGradientBrush( + new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(image.Width, 0), GradientRepetitionMode.None, @@ -196,15 +196,15 @@ namespace SixLabors.ImageSharp.Tests.Drawing provider.VerifyOperation( image => { - TPixel red = NamedColors.Red; - TPixel yellow = NamedColors.Yellow; + Color red = Color.Red; + Color yellow = Color.Yellow; - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(0, 0), new SixLabors.Primitives.Point(0, image.Height), GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); @@ -254,16 +254,16 @@ namespace SixLabors.ImageSharp.Tests.Drawing int endX = image.Height - startX - 1; int endY = image.Width - startY - 1; - TPixel red = NamedColors.Red; - TPixel yellow = NamedColors.Yellow; + Color red = Color.Red; + Color yellow = Color.Yellow; var unicolorLinearGradientBrush = - new LinearGradientBrush( + new LinearGradientBrush( new SixLabors.Primitives.Point(startX, startY), new SixLabors.Primitives.Point(endX, endY), GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, yellow)); + new ColorStop(0, red), + new ColorStop(1, yellow)); image.Mutate(x => x.Fill(unicolorLinearGradientBrush)); image.DebugSave( @@ -310,22 +310,21 @@ namespace SixLabors.ImageSharp.Tests.Drawing int[] stopColorCodes) where TPixel : struct, IPixel { - TPixel[] colors = + Color[] colors = { - NamedColors.Navy, NamedColors.LightGreen, NamedColors.Yellow, - NamedColors.Red + Color.Navy, Color.LightGreen, Color.Yellow, + Color.Red }; var coloringVariant = new StringBuilder(); - var colorStops = new ColorStop[stopPositions.Length]; + var colorStops = new ColorStop[stopPositions.Length]; for (int i = 0; i < stopPositions.Length; i++) { - TPixel color = colors[stopColorCodes[i % colors.Length]]; + Color color = colors[stopColorCodes[i % colors.Length]]; float position = stopPositions[i]; - colorStops[i] = new ColorStop(position, color); - Rgba32 rgba = default; - color.ToRgba32(ref rgba); + colorStops[i] = new ColorStop(position, color); + Rgba32 rgba = color; coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position); } @@ -334,7 +333,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing provider.VerifyOperation( image => { - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(startX, startY), new SixLabors.Primitives.Point(endX, endY), GradientRepetitionMode.None, @@ -357,22 +356,21 @@ namespace SixLabors.ImageSharp.Tests.Drawing int[] stopColorCodes) where TPixel : struct, IPixel { - TPixel[] colors = + Color[] colors = { - NamedColors.Black, NamedColors.Blue, NamedColors.Red, - NamedColors.White, NamedColors.Lime + Color.Black, Color.Blue, Color.Red, + Color.White, Color.Lime }; var coloringVariant = new StringBuilder(); - var colorStops = new ColorStop[stopPositions.Length]; + var colorStops = new ColorStop[stopPositions.Length]; for (int i = 0; i < stopPositions.Length; i++) { - TPixel color = colors[stopColorCodes[i % colors.Length]]; + Color color = colors[stopColorCodes[i % colors.Length]]; float position = stopPositions[i]; - colorStops[i] = new ColorStop(position, color); - Rgba32 rgba = default; - color.ToRgba32(ref rgba); + colorStops[i] = new ColorStop(position, color); + Rgba32 rgba = color; coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position); } @@ -381,7 +379,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing provider.VerifyOperation( image => { - var unicolorLinearGradientBrush = new LinearGradientBrush( + var unicolorLinearGradientBrush = new LinearGradientBrush( new SixLabors.Primitives.Point(startX, startY), new SixLabors.Primitives.Point(endX, endY), GradientRepetitionMode.None, diff --git a/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs index dcc689fe1..647f28510 100644 --- a/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillPatternBrushTests.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { public class FillPatternBrushTests { - private void Test(string name, Rgba32 background, IBrush brush, Rgba32[,] expectedPattern) + private void Test(string name, Rgba32 background, IBrush brush, Rgba32[,] expectedPattern) { string path = TestEnvironment.CreateOutputDirectory("Drawing", "FillPatternBrushTests"); using (var image = new Image(20, 20)) diff --git a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs index 43029e695..f84d2b31c 100644 --- a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing FormattableString outputDetails = $"{colorName}_A{alpha}{aa}"; provider.RunValidatingProcessorTest( - c => c.FillPolygon(options, color.ToPixel(), simplePath), + c => c.FillPolygon(options, color, simplePath), outputDetails, appendSourceFileOrDescription: false); } @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing Color color = Color.LightGreen; provider.RunValidatingProcessorTest( - c => c.FillPolygon(color.ToPixel(), points), + c => c.FillPolygon(color, points), appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); } @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing }; Color color = Color.Yellow; - var brush = Brushes.Horizontal(color.ToPixel()); + var brush = Brushes.Horizontal(color); provider.RunValidatingProcessorTest( c => c.FillPolygon(brush, simplePath), @@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing Color color = Color.White; provider.RunValidatingProcessorTest( - c => c.Fill(color.ToPixel(), polygon), + c => c.Fill(color, polygon), appendSourceFileOrDescription: false); } @@ -132,7 +132,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing FormattableString testOutput = $"V({vertices})_R({radius})_Ang({angleDeg})"; provider.RunValidatingProcessorTest( - c => c.Fill(color.ToPixel(), polygon), + c => c.Fill(color, polygon), testOutput, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); @@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing Color color = Color.Azure; provider.RunValidatingProcessorTest( - c => c.Fill(color.ToPixel(), polygon), + c => c.Fill(color, polygon), appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); } diff --git a/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs index 7461347de..818340dd2 100644 --- a/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillRadialGradientBrushTests.cs @@ -21,15 +21,15 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (Image image = provider.GetImage()) { - TPixel red = NamedColors.Red; + Color red = Color.Red; var unicolorRadialGradientBrush = - new RadialGradientBrush( + new RadialGradientBrush( new SixLabors.Primitives.Point(0, 0), 100, GradientRepetitionMode.None, - new ColorStop(0, red), - new ColorStop(1, red)); + new ColorStop(0, red), + new ColorStop(1, red)); image.Mutate(x => x.Fill(unicolorRadialGradientBrush)); @@ -56,12 +56,12 @@ namespace SixLabors.ImageSharp.Tests.Drawing TolerantComparer, image => { - var brush = new RadialGradientBrush( + var brush = new RadialGradientBrush( new SixLabors.Primitives.Point(centerX, centerY), image.Width / 2f, GradientRepetitionMode.None, - new ColorStop(0, NamedColors.Red), - new ColorStop(1, NamedColors.Yellow)); + new ColorStop(0, Color.Red), + new ColorStop(1, Color.Yellow)); image.Mutate(x => x.Fill(brush)); }, diff --git a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs index dc7da3543..bb78054a4 100644 --- a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs @@ -8,6 +8,7 @@ using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors; using SixLabors.Primitives; using Xunit; using SixLabors.ImageSharp.Processing.Processors.Drawing; @@ -30,14 +31,14 @@ namespace SixLabors.ImageSharp.Tests.Drawing { var bounds = new Rectangle(0, 0, 1, 1); - var brush = new Mock>(); + var brush = new Mock(); var region = new MockRegion2(bounds); var options = new GraphicsOptions(antialias) { AntialiasSubpixelDepth = 1 }; - var processor = new FillRegionProcessor(brush.Object, region, options); + var processor = new FillRegionProcessor(brush.Object, region, options); var img = new Image(1, 1); processor.Apply(img, bounds); @@ -48,9 +49,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing public void FillOffCanvas() { var bounds = new Rectangle(-100, -10, 10, 10); - var brush = new Mock>(); + var brush = new Mock(); var options = new GraphicsOptions(true); - var processor = new FillRegionProcessor(brush.Object, new MockRegion1(), options); + var processor = new FillRegionProcessor(brush.Object, new MockRegion1(), options); var img = new Image(10, 10); processor.Apply(img, bounds); } @@ -61,7 +62,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var img = new Image(10, 10)) { - img.Mutate(x => x.DrawLines(new Pen(Rgba32.Black, 10), new SixLabors.Primitives.PointF[] { + img.Mutate(x => x.DrawLines(new Pen(Rgba32.Black, 10), new SixLabors.Primitives.PointF[] { new Vector2(-10, 5), new Vector2(20, 5), })); diff --git a/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs index 639b3fe81..358552bf8 100644 --- a/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (Image image = provider.GetImage()) { - TPixel color = NamedColors.HotPink; + Color color = Color.HotPink; image.Mutate(c => c.Fill(color)); image.DebugSave(provider, appendPixelTypeToFileName: false); @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (Image image = provider.GetImage()) { - TPixel color = NamedColors.HotPink; + Color color = Color.HotPink; image.Mutate(c => c.Fill(color)); image.DebugSave(provider, appendSourceFileOrDescription: false); @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (Image image = provider.GetImage()) { - TPixel color = TestUtils.GetPixelOfNamedColor(newColorName); + Color color = TestUtils.GetColorByName(newColorName); image.Mutate(c => c.Fill(color)); image.DebugSave( @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { FormattableString testDetails = $"(x{x0},y{y0},w{w},h{h})"; var region = new RectangleF(x0, y0, w, h); - TPixel color = TestUtils.GetPixelOfNamedColor("Blue"); + Color color = TestUtils.GetColorByName("Blue"); provider.RunValidatingProcessorTest(c => c.Fill(color, region), testDetails, ImageComparer.Exact); } @@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { FormattableString testDetails = $"(x{x0},y{y0},w{w},h{h})"; var region = new RectangleF(x0, y0, w, h); - TPixel color = TestUtils.GetPixelOfNamedColor("Blue"); + Color color = TestUtils.GetColorByName("Blue"); provider.RunValidatingProcessorTestOnWrappedMemoryImage( c => c.Fill(color, region), @@ -150,11 +150,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing float blendPercentage) where TPixel : struct, IPixel { - var vec = TestUtils.GetPixelOfNamedColor(newColorName).ToVector4(); - vec.W = alpha; - - TPixel fillColor = default; - fillColor.FromVector4(vec); + Color fillColor = TestUtils.GetColorByName(newColorName).WithAlpha(alpha); using (Image image = provider.GetImage()) { @@ -169,11 +165,11 @@ namespace SixLabors.ImageSharp.Tests.Drawing { var region = new ShapeRegion(new RectangularPolygon(0, 0, 16, 16)); - image.Mutate(c => c.Fill(options, new SolidBrush(fillColor), region)); + image.Mutate(c => c.Fill(options, new SolidBrush(fillColor), region)); } else { - image.Mutate(c => c.Fill(options, new SolidBrush(fillColor))); + image.Mutate(c => c.Fill(options, new SolidBrush(fillColor))); } var testOutputDetails = new @@ -194,7 +190,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing PixelBlender blender = PixelOperations.Instance.GetPixelBlender( blenderMode, PixelAlphaCompositionMode.SrcOver); - TPixel expectedPixel = blender.Blend(bgColor, fillColor, blendPercentage); + TPixel expectedPixel = blender.Blend(bgColor, fillColor.ToPixel(), blendPercentage); image.ComparePixelBufferTo(expectedPixel); } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs index 326517a4e..5ab789435 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public class DrawPathCollection : BaseImageOperationsExtensionTest { GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - Pen pen = Pens.Solid(Rgba32.HotPink, 1); + Color color = Color.HotPink; + Pen pen = Pens.Solid(Rgba32.HotPink, 1); IPath path1 = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { new Vector2(10,10), new Vector2(20,10), @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(this.noneDefault, processor.Options); @@ -81,14 +81,14 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(GraphicsOptions.Default, processor.Options); ShapePath region = Assert.IsType(processor.Region); ComplexPolygon polygon = Assert.IsType(region.Shape); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } @@ -100,14 +100,14 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(this.noneDefault, processor.Options); ShapePath region = Assert.IsType(processor.Region); ComplexPolygon polygon = Assert.IsType(region.Shape); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs index e72fbbdf2..d65dcd8c6 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPath.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public class FillPath : BaseImageOperationsExtensionTest { GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + Color color = Color.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); IPath path = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { new Vector2(10,10), new Vector2(20,10), @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsBrushAndPath() { this.operations.Fill(this.brush, this.path); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsBrushPathOptions() { this.operations.Fill(this.noneDefault, this.brush, this.path); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorAndPath() { this.operations.Fill(this.color, this.path); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorPathAndOptions() { this.operations.Fill(this.noneDefault, this.color, this.path); - var processor = this.Verify>(); + var processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs index ec7a5a20c..1f8e2d423 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public class FillPathCollection : BaseImageOperationsExtensionTest { GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + Color color = Color.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); IPath path1 = new Path(new LinearLineSegment(new SixLabors.Primitives.PointF[] { new Vector2(10,10), new Vector2(20,10), @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(this.noneDefault, processor.Options); @@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } @@ -103,7 +103,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths for (int i = 0; i < 2; i++) { - FillRegionProcessor processor = this.Verify>(i); + FillRegionProcessor processor = this.Verify(i); Assert.Equal(this.noneDefault, processor.Options); @@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs index d8927a468..b270a03cf 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPolygon.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public class FillPolygon : BaseImageOperationsExtensionTest { GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + Color color = Color.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); SixLabors.Primitives.PointF[] path = { new Vector2(10,10), new Vector2(20,10), @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths { this.operations.FillPolygon(this.brush, this.path); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsBrushPathAndOptions() { this.operations.FillPolygon(this.noneDefault, this.brush, this.path); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorAndPath() { this.operations.FillPolygon(this.color, this.path); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segemnt = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorPathAndOptions() { this.operations.FillPolygon(this.noneDefault, this.color, this.path); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Polygon polygon = Assert.IsType(region.Shape); LinearLineSegment segemnt = Assert.IsType(polygon.LineSegments[0]); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs index 8f648e425..6cb052aa8 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillRectangle.cs @@ -12,15 +12,15 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public class FillRectangle : BaseImageOperationsExtensionTest { GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + Color color = Color.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); SixLabors.Primitives.Rectangle rectangle = new SixLabors.Primitives.Rectangle(10, 10, 77, 76); [Fact] public void CorrectlySetsBrushAndRectangle() { this.operations.Fill(this.brush, this.rectangle); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsBrushRectangleAndOptions() { this.operations.Fill(this.noneDefault, this.brush, this.rectangle); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorAndRectangle() { this.operations.Fill(this.color, this.rectangle); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(GraphicsOptions.Default, processor.Options); @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Assert.Equal(rect.Size.Width, this.rectangle.Width); Assert.Equal(rect.Size.Height, this.rectangle.Height); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths public void CorrectlySetsColorRectangleAndOptions() { this.operations.Fill(this.noneDefault, this.color, this.rectangle); - FillRegionProcessor processor = this.Verify>(); + FillRegionProcessor processor = this.Verify(); Assert.Equal(this.noneDefault, processor.Options); @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Paths Assert.Equal(rect.Size.Width, this.rectangle.Width); Assert.Equal(rect.Size.Height, this.rectangle.Height); - SolidBrush brush = Assert.IsType>(processor.Brush); + SolidBrush brush = Assert.IsType(processor.Brush); Assert.Equal(this.color, brush.Color); } } diff --git a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs index 461ca700f..fae0bf72b 100644 --- a/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/RecolorImageTests.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { Color sourceColor = TestUtils.GetColorByName(sourceColorName); Color targetColor = TestUtils.GetColorByName(targetColorName); - var brush = new RecolorBrush(sourceColor.ToPixel(), targetColor.ToPixel(), threshold); + var brush = new RecolorBrush(sourceColor, targetColor, threshold); FormattableString testInfo = $"{sourceColorName}-{targetColorName}-{threshold}"; provider.RunValidatingProcessorTest(x => x.Fill(brush), testInfo); @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { Color sourceColor = TestUtils.GetColorByName(sourceColorName); Color targetColor = TestUtils.GetColorByName(targetColorName); - var brush = new RecolorBrush(sourceColor.ToPixel(), targetColor.ToPixel(), threshold); + var brush = new RecolorBrush(sourceColor, targetColor, threshold); FormattableString testInfo = $"{sourceColorName}-{targetColorName}-{threshold}"; provider.RunValidatingProcessorTest(x => diff --git a/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs b/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs index e8f53de01..fd8713ccc 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidBezierTests.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (Image image = provider.GetImage()) { image.Mutate(x => x.BackgroundColor(blue)); - image.Mutate(x => x.Fill(hotPink.ToPixel(), new Polygon(new CubicBezierLineSegment(simplePath)))); + image.Mutate(x => x.Fill(hotPink, new Polygon(new CubicBezierLineSegment(simplePath)))); image.DebugSave(provider); image.CompareToReferenceOutput(provider); } diff --git a/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs b/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs index 94e12f858..c34d50297 100644 --- a/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs +++ b/tests/ImageSharp.Tests/Drawing/SolidFillBlendedShapesTests.cs @@ -43,11 +43,11 @@ namespace SixLabors.ImageSharp.Tests.Drawing int scaleY = img.Height / 100; img.Mutate( x => x.Fill( - NamedColors.DarkBlue, + Color.DarkBlue, new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY) ) .Fill(new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode=composition }, - NamedColors.HotPink, + Color.HotPink, new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY)) ); @@ -69,17 +69,17 @@ namespace SixLabors.ImageSharp.Tests.Drawing int scaleY = img.Height / 100; img.Mutate( x => x.Fill( - NamedColors.DarkBlue, + Color.DarkBlue, new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); img.Mutate( x => x.Fill( new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - NamedColors.HotPink, + Color.HotPink, new Rectangle(20 * scaleX, 0 * scaleY, 30 * scaleX, 100 * scaleY))); img.Mutate( x => x.Fill( new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - NamedColors.Transparent, + Color.Transparent, new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) ); @@ -101,22 +101,20 @@ namespace SixLabors.ImageSharp.Tests.Drawing int scaleY = (img.Height / 100); img.Mutate( x => x.Fill( - NamedColors.DarkBlue, + Color.DarkBlue, new Rectangle(0 * scaleX, 40, 100 * scaleX, 20 * scaleY))); img.Mutate( x => x.Fill( new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - NamedColors.HotPink, + Color.HotPink, new Rectangle(20 * scaleX, 0, 30 * scaleX, 100 * scaleY))); - var c = NamedColors.Red.ToVector4(); - c.W *= 0.5f; - var pixel = default(TPixel); - pixel.FromVector4(c); + + var transparentRed = Color.Red.WithAlpha(0.5f); img.Mutate( x => x.Fill( new GraphicsOptions(true) { ColorBlendingMode = blending, AlphaCompositionMode = composition }, - pixel, + transparentRed, new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY)) ); @@ -139,12 +137,12 @@ namespace SixLabors.ImageSharp.Tests.Drawing dstImg.Mutate( x => x.Fill( - NamedColors.DarkBlue, + Color.DarkBlue, new Rectangle(0 * scaleX, 40 * scaleY, 100 * scaleX, 20 * scaleY))); srcImg.Mutate( x => x.Fill( - NamedColors.Black, + Color.Black, new Shapes.EllipsePolygon(40 * scaleX, 50 * scaleY, 50 * scaleX, 50 * scaleY))); dstImg.Mutate( diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs index 76f40e0ac..8520a2f3f 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs @@ -14,9 +14,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text { public class DrawText : BaseImageOperationsExtensionTest { - Rgba32 color = Rgba32.HotPink; + Rgba32 color = Color.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + SolidBrush brush = Brushes.Solid(Color.HotPink); IPath path = new SixLabors.Shapes.Path( new LinearLineSegment( @@ -39,57 +39,57 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text new TextGraphicsOptions(true), "123", this.Font, - Brushes.Solid(Rgba32.Red), + Brushes.Solid(Color.Red), null, Vector2.Zero); - this.Verify>(0); + this.Verify(0); } [Fact] public void FillsForEachACharachterWhenBrushSetAndNotPenDefaultOptions() { - this.operations.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), null, Vector2.Zero); + this.operations.DrawText("123", this.Font, Brushes.Solid(Color.Red), null, Vector2.Zero); - this.Verify>(0); + this.Verify(0); } [Fact] public void FillsForEachACharachterWhenBrushSet() { - this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Brushes.Solid(Rgba32.Red), Vector2.Zero); + this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Brushes.Solid(Color.Red), Vector2.Zero); - this.Verify>(0); + this.Verify(0); } [Fact] public void FillsForEachACharachterWhenBrushSetDefaultOptions() { - this.operations.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), Vector2.Zero); + this.operations.DrawText("123", this.Font, Brushes.Solid(Color.Red), Vector2.Zero); - this.Verify>(0); + this.Verify(0); } [Fact] public void FillsForEachACharachterWhenColorSet() { - this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Rgba32.Red, Vector2.Zero); + this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Color.Red, Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); - SolidBrush brush = Assert.IsType>(processor.Brush); - Assert.Equal(Rgba32.Red, brush.Color); + SolidBrush brush = Assert.IsType(processor.Brush); + Assert.Equal(Color.Red, brush.Color); } [Fact] public void FillsForEachACharachterWhenColorSetDefaultOptions() { - this.operations.DrawText("123", this.Font, Rgba32.Red, Vector2.Zero); + this.operations.DrawText("123", this.Font, Color.Red, Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); - SolidBrush brush = Assert.IsType>(processor.Brush); - Assert.Equal(Rgba32.Red, brush.Color); + SolidBrush brush = Assert.IsType(processor.Brush); + Assert.Equal(Color.Red, brush.Color); } [Fact] @@ -100,39 +100,39 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text "123", this.Font, null, - Pens.Dash(Rgba32.Red, 1), + Pens.Dash(Color.Red, 1), Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); } [Fact] public void DrawForEachACharachterWhenPenSetAndNotBrushDefaultOptions() { - this.operations.DrawText("123", this.Font, null, Pens.Dash(Rgba32.Red, 1), Vector2.Zero); + this.operations.DrawText("123", this.Font, null, Pens.Dash(Color.Red, 1), Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); } [Fact] public void DrawForEachACharachterWhenPenSet() { - this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Pens.Dash(Rgba32.Red, 1), Vector2.Zero); + this.operations.DrawText(new TextGraphicsOptions(true), "123", this.Font, Pens.Dash(Color.Red, 1), Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); } [Fact] public void DrawForEachACharachterWhenPenSetDefaultOptions() { - this.operations.DrawText("123", this.Font, Pens.Dash(Rgba32.Red, 1), Vector2.Zero); + this.operations.DrawText("123", this.Font, Pens.Dash(Color.Red, 1), Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); Assert.Equal("123", processor.Text); Assert.Equal(this.Font, processor.Font); - var penBrush = Assert.IsType>(processor.Pen.StrokeFill); - Assert.Equal(Rgba32.Red, penBrush.Color); + var penBrush = Assert.IsType(processor.Pen.StrokeFill); + Assert.Equal(Color.Red, penBrush.Color); Assert.Equal(1, processor.Pen.StrokeWidth); Assert.Equal(PointF.Empty, processor.Location); } @@ -144,19 +144,19 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text new TextGraphicsOptions(true), "123", this.Font, - Brushes.Solid(Rgba32.Red), - Pens.Dash(Rgba32.Red, 1), + Brushes.Solid(Color.Red), + Pens.Dash(Color.Red, 1), Vector2.Zero); - var processor = this.Verify>(0); + var processor = this.Verify(0); Assert.Equal("123", processor.Text); Assert.Equal(this.Font, processor.Font); - var brush = Assert.IsType>(processor.Brush); - Assert.Equal(Rgba32.Red, brush.Color); + var brush = Assert.IsType(processor.Brush); + Assert.Equal(Color.Red, brush.Color); Assert.Equal(PointF.Empty, processor.Location); - var penBrush = Assert.IsType>(processor.Pen.StrokeFill); - Assert.Equal(Rgba32.Red, penBrush.Color); + var penBrush = Assert.IsType(processor.Pen.StrokeFill); + Assert.Equal(Color.Red, penBrush.Color); Assert.Equal(1, processor.Pen.StrokeWidth); } } diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs index 20ccb25a5..ebd9cf644 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text where TPixel : struct, IPixel { Font font = CreateFont("OpenSans-Regular.ttf", 36); - TPixel color = NamedColors.Black; + Color color = Color.Black; float padding = 5; var text = "A short piece of text"; @@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text where TPixel : struct, IPixel { Font font = CreateFont(fontName, fontSize); - TPixel color = NamedColors.Black; + Color color = Color.Black; provider.VerifyOperation( TextDrawingComparer, @@ -129,7 +129,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text HorizontalAlignment = HorizontalAlignment.Left, }; - TPixel color = NamedColors.Black; + Color color = Color.Black; // Based on the reported 0.0270% difference with AccuracyMultiple = 8 // We should avoid quality regressions leading to higher difference! @@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text where TPixel : struct, IPixel { Font font = CreateFont(fontName, fontSize); - TPixel color = NamedColors.Black; + Color color = Color.Black; provider.VerifyOperation( OutlinedTextDrawingComparer, @@ -186,7 +186,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text where TPixel : struct, IPixel { Font font = CreateFont(fontName, fontSize); - TPixel color = NamedColors.Black; + Color color = Color.Black; provider.VerifyOperation( OutlinedTextDrawingComparer, @@ -217,7 +217,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text var comparer = ImageComparer.TolerantPercentage(0.2f); provider.RunValidatingProcessorTest( - x => x.DrawText(textOptions, text, font, NamedColors.Black, new PointF(10, 50)), + x => x.DrawText(textOptions, text, font, Color.Black, new PointF(10, 50)), details, comparer, appendPixelTypeToFileName: false, diff --git a/tests/ImageSharp.Tests/Issues/Issue412.cs b/tests/ImageSharp.Tests/Issues/Issue412.cs index b0374ce1f..f22d3a85c 100644 --- a/tests/ImageSharp.Tests/Issues/Issue412.cs +++ b/tests/ImageSharp.Tests/Issues/Issue412.cs @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Tests.Issues { context.DrawLines( new GraphicsOptions(false), - NamedColors.Black, + Color.Black, 1, new[] { @@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Tests.Issues context.DrawLines( new GraphicsOptions(false), - NamedColors.Red, + Color.Red, 1, new[] { @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Tests.Issues for (var x = 0; x < 40; x++) { - Assert.True(NamedColors.Red.Equals(image[x, y]), $"expected {NamedColors.Red} but found {image[x, y]} at [{x}, {y}]"); + Assert.True(Color.Red.Equals(image[x, y]), $"expected {Color.Red} but found {image[x, y]} at [{x}, {y}]"); } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs index 1ff95f60d..88b30ce34 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs @@ -53,8 +53,7 @@ namespace SixLabors.ImageSharp.Tests public override Image GetImage() { Image image = base.GetImage(); - TPixel color = default(TPixel); - color.FromRgba32(new Rgba32(this.r, this.g, this.b, this.a)); + Color color = new Rgba32(this.r, this.g, this.b, this.a); image.Mutate(x => x.Fill(color)); return image; diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index c5aa1fb94..048c6347c 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -484,6 +484,20 @@ namespace SixLabors.ImageSharp.Tests return image; } + + /// + /// All pixels in all frames should be exactly equal to 'expectedPixelColor.ToPixel()'. + /// + public static Image ComparePixelBufferTo(this Image image, Color expectedPixelColor) + where TPixel : struct, IPixel + { + foreach (ImageFrame imageFrame in image.Frames) + { + imageFrame.ComparePixelBufferTo(expectedPixelColor.ToPixel()); + } + + return image; + } /// /// All pixels in the frame should be exactly equal to 'expectedPixel'. From f0b70b63efa1f2e09e388accc049aacfde05bd0c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 21:56:40 +0200 Subject: [PATCH 182/223] tests are passing --- .../Processing/Processors/Text/DrawTextProcessor.cs | 2 +- tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs index 016cf56de..d1e28afeb 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text public IImageProcessor CreatePixelSpecificProcessor() where TPixel : struct, IPixel { - throw new NotImplementedException(); + return new DrawTextProcessor(this); } } diff --git a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs index 5d1442e79..361e7e70d 100644 --- a/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs @@ -176,7 +176,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing // the result must be a black and white pattern, no other color should occur: Assert.All( Enumerable.Range(0, image.Width).Select(i => image[i, 0]), - color => Assert.True(color.Equals(black) || color.Equals(white))); + color => Assert.True( + color.Equals(black.ToPixel()) || color.Equals(white.ToPixel()))); image.CompareToReferenceOutput( TolerantComparer, From 5931537429589de85e7cb22659207ef15ba99213 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 22:14:46 +0200 Subject: [PATCH 183/223] fix new 8bit bmp code --- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 9 ++++++--- tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 90ea673d3..edde7dc89 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -306,12 +306,15 @@ namespace SixLabors.ImageSharp.Formats.Bmp where TPixel : struct, IPixel { using (IMemoryOwner colorPaletteBuffer = this.memoryAllocator.AllocateManagedByteBuffer(ColorPaletteSize8Bit, AllocationOptions.Clean)) - using (QuantizedFrame quantized = this.quantizer.CreateFrameQuantizer(this.configuration, 256).QuantizeFrame(image)) + using (IQuantizedFrame quantized = this.quantizer.CreateFrameQuantizer(this.configuration, 256).QuantizeFrame(image)) { Span colorPalette = colorPaletteBuffer.GetSpan(); int idx = 0; var color = default(Rgba32); - foreach (TPixel quantizedColor in quantized.Palette) + ReadOnlySpan paletteSpan = quantized.Palette.Span; + + // TODO: Use bulk conversion here for better perf + foreach (TPixel quantizedColor in paletteSpan) { quantizedColor.ToRgba32(ref color); colorPalette[idx] = color.B; @@ -327,7 +330,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp for (int y = image.Height - 1; y >= 0; y--) { - Span pixelSpan = quantized.GetRowSpan(y); + ReadOnlySpan pixelSpan = quantized.GetRowSpan(y); stream.Write(pixelSpan); for (int i = 0; i < this.padding; i++) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index abf57ed01..dd76e9443 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp { using static TestImages.Bmp; - public class BmpEncoderTests : FileTestBase + public class BmpEncoderTests { public static readonly TheoryData BitsPerPixel = new TheoryData From f7df30f58c45b53dbf73fc2f6b0fe8362854cf47 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 22:20:34 +0200 Subject: [PATCH 184/223] move drawing extensions to a (non-namespace-provider) subfolder --- .../ImageSharp.Drawing.csproj.DotSettings | 2 + .../{ => Extensions}/DrawBezierExtensions.cs | 0 .../{ => Extensions}/DrawImageExtensions.cs | 272 +++++++++--------- .../{ => Extensions}/DrawLineExtensions.cs | 0 .../DrawPathCollectionExtensions.cs | 0 .../{ => Extensions}/DrawPathExtensions.cs | 0 .../{ => Extensions}/DrawPolygonExtensions.cs | 0 .../DrawRectangleExtensions.cs | 0 .../{ => Extensions}/DrawTextExtensions.cs | 0 .../FillPathBuilderExtensions.cs | 0 .../FillPathCollectionExtensions.cs | 0 .../{ => Extensions}/FillPathExtensions.cs | 0 .../{ => Extensions}/FillPolygonExtensions.cs | 0 .../FillRectangleExtensions.cs | 0 .../{ => Extensions}/FillRegionExtensions.cs | 0 15 files changed, 138 insertions(+), 136 deletions(-) create mode 100644 src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawBezierExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawImageExtensions.cs (98%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawLineExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawPathCollectionExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawPathExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawPolygonExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawRectangleExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/DrawTextExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillPathBuilderExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillPathCollectionExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillPathExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillPolygonExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillRectangleExtensions.cs (100%) rename src/ImageSharp.Drawing/Processing/{ => Extensions}/FillRegionExtensions.cs (100%) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings new file mode 100644 index 000000000..a728b5497 --- /dev/null +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawBezierExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawBezierExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs similarity index 98% rename from src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs index a8ee4d90b..58459ebc5 100644 --- a/src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs @@ -1,137 +1,137 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors.Drawing; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Adds extensions that allow the drawing of images to the type. - /// - public static class DrawImageExtensions - { - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The blending mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The color blending mode. - /// The alpha composition mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The options, including the blending type and blending amount. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, GraphicsOptions options) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The color blending to apply. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The color blending to apply. - /// The alpha composition mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); - - /// - /// Draws the given image together with the current one by blending their pixels. - /// - /// The pixel format of the destination image. - /// The pixel format of the source image. - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The options containing the blend mode and opacity. - /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, GraphicsOptions options) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); - } +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Drawing; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing +{ + /// + /// Adds extensions that allow the drawing of images to the type. + /// + public static class DrawImageExtensions + { + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The blending mode. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The color blending mode. + /// The alpha composition mode. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The options, including the blending type and blending amount. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, GraphicsOptions options) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The color blending to apply. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The color blending to apply. + /// The alpha composition mode. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The pixel format of the destination image. + /// The pixel format of the source image. + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The options containing the blend mode and opacity. + /// The . + public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, GraphicsOptions options) + where TPixelDst : struct, IPixel + where TPixelSrc : struct, IPixel + => source.ApplyProcessor(new DrawImageProcessor(image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); + } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawLineExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawLineExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPathCollectionExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawPathCollectionExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPolygonExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawPolygonExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawRectangleExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawRectangleExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawTextExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/DrawTextExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillPathBuilderExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathCollectionExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillPathCollectionExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillPathExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPolygonExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillPolygonExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillRectangleExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillRectangleExtensions.cs diff --git a/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs rename to src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs From c07bd2fd97bba0648a9f82806784094aced0fff1 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 22:24:27 +0200 Subject: [PATCH 185/223] rename files --- .../Processing/{ColorStop{TPixel}.cs => ColorStop.cs} | 0 ...cGradientBrush{TPixel}.cs => EllipticGradientBrush.cs} | 0 ...{GradientBrushBase{TPixel}.cs => GradientBrushBase.cs} | 0 .../Processing/{ImageBrush{TPixel}.cs => ImageBrush.cs} | 7 +++---- ...earGradientBrush{TPixel}.cs => LinearGradientBrush.cs} | 1 - .../{PatternBrush{TPixel}.cs => PatternBrush.cs} | 0 .../Processing/{Pen{TPixel}.cs => Pen.cs} | 8 ++++---- ...ialGradientBrush{TPixel}.cs => RadialGradientBrush.cs} | 0 .../{RecolorBrush{TPixel}.cs => RecolorBrush.cs} | 1 - .../Processing/{SolidBrush{TPixel}.cs => SolidBrush.cs} | 0 tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs | 2 +- tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs | 2 +- 12 files changed, 9 insertions(+), 12 deletions(-) rename src/ImageSharp.Drawing/Processing/{ColorStop{TPixel}.cs => ColorStop.cs} (100%) rename src/ImageSharp.Drawing/Processing/{EllipticGradientBrush{TPixel}.cs => EllipticGradientBrush.cs} (100%) rename src/ImageSharp.Drawing/Processing/{GradientBrushBase{TPixel}.cs => GradientBrushBase.cs} (100%) rename src/ImageSharp.Drawing/Processing/{ImageBrush{TPixel}.cs => ImageBrush.cs} (97%) rename src/ImageSharp.Drawing/Processing/{LinearGradientBrush{TPixel}.cs => LinearGradientBrush.cs} (98%) rename src/ImageSharp.Drawing/Processing/{PatternBrush{TPixel}.cs => PatternBrush.cs} (100%) rename src/ImageSharp.Drawing/Processing/{Pen{TPixel}.cs => Pen.cs} (88%) rename src/ImageSharp.Drawing/Processing/{RadialGradientBrush{TPixel}.cs => RadialGradientBrush.cs} (100%) rename src/ImageSharp.Drawing/Processing/{RecolorBrush{TPixel}.cs => RecolorBrush.cs} (99%) rename src/ImageSharp.Drawing/Processing/{SolidBrush{TPixel}.cs => SolidBrush.cs} (100%) diff --git a/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ColorStop.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/ColorStop.cs diff --git a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/GradientBrushBase.cs diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ImageBrush.cs similarity index 97% rename from src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/ImageBrush.cs index d5ec1123d..983c09adb 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush.cs @@ -14,8 +14,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Provides an implementation of an image brush for painting images within areas. /// - /// The pixel format. - public class ImageBrush : IBrush + public class ImageBrush : IBrush { /// /// The image to paint. @@ -23,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing private readonly Image image; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The image. public ImageBrush(Image image) @@ -74,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing private readonly int offsetX; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target image. /// The image. diff --git a/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs similarity index 98% rename from src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs index 1a6f8d79a..fac43ad63 100644 --- a/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs @@ -13,7 +13,6 @@ namespace SixLabors.ImageSharp.Processing /// Supported right now: /// - a set of colors in relative distances to each other. /// - /// The pixel format public sealed class LinearGradientBrush : GradientBrushBase { diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/PatternBrush.cs diff --git a/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Pen.cs similarity index 88% rename from src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/Pen.cs index 922394946..c9d60a50e 100644 --- a/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/Pen.cs @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing private readonly float[] pattern; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color. /// The width. @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The brush. /// The width. @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color. /// The width. @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Processing } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The brush. /// The width. diff --git a/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs diff --git a/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RecolorBrush.cs similarity index 99% rename from src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/RecolorBrush.cs index ff098dce7..fca95be32 100644 --- a/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs +++ b/src/ImageSharp.Drawing/Processing/RecolorBrush.cs @@ -15,7 +15,6 @@ namespace SixLabors.ImageSharp.Processing /// /// Provides an implementation of a brush that can recolor an image /// - /// The pixel format. public class RecolorBrush : IBrush { /// diff --git a/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/SolidBrush.cs similarity index 100% rename from src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs rename to src/ImageSharp.Drawing/Processing/SolidBrush.cs diff --git a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs index 772f62d5c..e1fc7c30c 100644 --- a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing { using (var src = new Image(5, 5)) { - var brush = new ImageBrush(src); + var brush = new ImageBrush(src); using (var dest = new Image(10, 10)) { dest.Mutate(c => c.Fill(brush, new Rectangle(0, 0, 10, 10))); diff --git a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs index f84d2b31c..5393e9954 100644 --- a/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillPolygonTests.cs @@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (Image brushImage = Image.Load(TestFile.Create(brushImageName).Bytes)) { - var brush = new ImageBrush(brushImage); + var brush = new ImageBrush(brushImage); provider.RunValidatingProcessorTest( c => c.FillPolygon(brush, simplePath), From efaa3c05ed5829f4a75937c27b84915712d29527 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 12 May 2019 22:54:38 +0200 Subject: [PATCH 186/223] ImageBrush can apply a source image of a different pixel type than the target --- .../Processing/ImageBrush.cs | 44 ++++++++++++++----- src/ImageSharp/Image.cs | 17 +++++++ src/ImageSharp/Image{TPixel}.cs | 11 +---- .../Drawing/DrawImageTests.cs | 2 + .../Drawing/FillImageBrushTests.cs | 19 ++++++++ .../TestUtilities/ImagingTestCaseUtility.cs | 6 +-- .../TestUtilities/TestImageExtensions.cs | 29 +++++------- tests/Images/External | 2 +- 8 files changed, 86 insertions(+), 44 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush.cs b/src/ImageSharp.Drawing/Processing/ImageBrush.cs index 983c09adb..c2a8d3a26 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush.cs @@ -3,6 +3,7 @@ using System; using System.Buffers; + using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -37,8 +38,14 @@ namespace SixLabors.ImageSharp.Processing GraphicsOptions options) where TPixel : struct, IPixel { - Image specificImage = (Image)this.image; - return new ImageBrushApplicator(source, specificImage.Frames.RootFrame, region, options); + if (this.image is Image specificImage) + { + return new ImageBrushApplicator(source, specificImage, region, options, false); + } + + specificImage = this.image.CloneAs(); + + return new ImageBrushApplicator(source, specificImage, region, options, true); } /// @@ -47,10 +54,11 @@ namespace SixLabors.ImageSharp.Processing private class ImageBrushApplicator : BrushApplicator where TPixel : struct, IPixel { - /// - /// The source image. - /// - private readonly ImageFrame source; + private ImageFrame sourceFrame; + + private Image sourceImage; + + private readonly bool shouldDisposeImage; /// /// The y-length. @@ -79,10 +87,18 @@ namespace SixLabors.ImageSharp.Processing /// The image. /// The region. /// The options - public ImageBrushApplicator(ImageFrame target, ImageFrame image, RectangleF region, GraphicsOptions options) + /// Whether to dispose the image on disposal of the applicator. + public ImageBrushApplicator( + ImageFrame target, + Image image, + RectangleF region, + GraphicsOptions options, + bool shouldDisposeImage) : base(target, options) { - this.source = image; + this.sourceImage = image; + this.sourceFrame = image.Frames.RootFrame; + this.shouldDisposeImage = shouldDisposeImage; this.xLength = image.Width; this.yLength = image.Height; this.offsetY = (int)MathF.Max(MathF.Floor(region.Top), 0); @@ -103,13 +119,19 @@ namespace SixLabors.ImageSharp.Processing { int srcX = (x - this.offsetX) % this.xLength; int srcY = (y - this.offsetY) % this.yLength; - return this.source[srcX, srcY]; + return this.sourceFrame[srcX, srcY]; } } /// public override void Dispose() { + if (this.shouldDisposeImage) + { + this.sourceImage?.Dispose(); + this.sourceImage = null; + this.sourceFrame = null; + } } /// @@ -124,7 +146,7 @@ namespace SixLabors.ImageSharp.Processing int sourceY = (y - this.offsetY) % this.yLength; int offsetX = x - this.offsetX; - Span sourceRow = this.source.GetPixelRowSpan(sourceY); + Span sourceRow = this.sourceFrame.GetPixelRowSpan(sourceY); for (int i = 0; i < scanline.Length; i++) { @@ -137,7 +159,7 @@ namespace SixLabors.ImageSharp.Processing Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); this.Blender.Blend( - this.source.Configuration, + this.sourceFrame.Configuration, destinationRow, destinationRow, overlaySpan, diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index 1566fd0ee..db0328106 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -87,6 +87,23 @@ namespace SixLabors.ImageSharp EncodeVisitor visitor = new EncodeVisitor(encoder, stream); this.AcceptVisitor(visitor); } + + /// + /// Returns a copy of the image in the given pixel format. + /// + /// The pixel format. + /// The + public Image CloneAs() + where TPixel2 : struct, IPixel => this.CloneAs(this.Configuration); + + /// + /// Returns a copy of the image in the given pixel format. + /// + /// The pixel format. + /// The configuration providing initialization code which allows extending the library. + /// The . + public abstract Image CloneAs(Configuration configuration) + where TPixel2 : struct, IPixel; /// /// Accept a . diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 27e2bc593..2b93b710b 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -153,22 +153,13 @@ namespace SixLabors.ImageSharp return new Image(configuration, this.Metadata.DeepClone(), clonedFrames); } - /// - /// Returns a copy of the image in the given pixel format. - /// - /// The pixel format. - /// The - public Image CloneAs() - where TPixel2 : struct, IPixel => this.CloneAs(this.Configuration); - /// /// Returns a copy of the image in the given pixel format. /// /// The pixel format. /// The configuration providing initialization code which allows extending the library. /// The . - public Image CloneAs(Configuration configuration) - where TPixel2 : struct, IPixel + public override Image CloneAs(Configuration configuration) { IEnumerable> clonedFrames = this.Frames.Select(x => x.CloneAs(configuration)); return new Image(configuration, this.Metadata.DeepClone(), clonedFrames); diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index 70879e6fe..e48a0b0ae 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -175,5 +175,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing } } } + + } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs index e1fc7c30c..d33d7b70d 100644 --- a/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillImageBrushTests.cs @@ -32,5 +32,24 @@ namespace SixLabors.ImageSharp.Tests.Drawing } } } + + [Theory] + [WithTestPatternImages(200, 200, PixelTypes.Rgba32 | PixelTypes.Bgra32)] + public void UseBrushOfDifferentPixelType(TestImageProvider provider) + where TPixel : struct, IPixel + { + byte[] data = TestFile.Create(TestImages.Png.Ducky).Bytes; + using (Image background = provider.GetImage()) + using (Image overlay = provider.PixelType == PixelTypes.Rgba32 + ? (Image)Image.Load(data) + : Image.Load(data)) + { + var brush = new ImageBrush(overlay); + background.Mutate(c => c.Fill(brush)); + + background.DebugSave(provider, appendSourceFileOrDescription : false); + background.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false); + } + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs index c91ef56a1..92cc9f636 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs @@ -152,21 +152,19 @@ namespace SixLabors.ImageSharp.Tests /// /// Encodes image by the format matching the required extension, than saves it to the recommended output file. /// - /// The pixel format of the image /// The image instance /// The requested extension /// Optional encoder /// A value indicating whether to append the pixel type to the test output file name /// A boolean indicating whether to append to the test output file name. /// Additional information to append to the test output file name - public string SaveTestOutputFile( - Image image, + public string SaveTestOutputFile( + Image image, string extension = null, IImageEncoder encoder = null, object testOutputDetails = null, bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true) - where TPixel : struct, IPixel { string path = this.GetTestOutputFileName( extension, diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 048c6347c..e77b1974d 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -55,17 +55,16 @@ namespace SixLabors.ImageSharp.Tests }); } - public static Image DebugSave( - this Image image, + public static void DebugSave( + this Image image, ITestImageProvider provider, FormattableString testOutputDetails, string extension = "png", bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true, IImageEncoder encoder = null) - where TPixel : struct, IPixel { - return image.DebugSave( + image.DebugSave( provider, (object)testOutputDetails, extension, @@ -77,7 +76,6 @@ namespace SixLabors.ImageSharp.Tests /// /// Saves the image only when not running in the CI server. /// - /// The pixel format /// The image /// The image provider /// Details to be concatenated to the test output file, describing the parameters of the test. @@ -85,15 +83,14 @@ namespace SixLabors.ImageSharp.Tests /// A boolean indicating whether to append the pixel type to the output file name. /// A boolean indicating whether to append to the test output file name. /// Custom encoder to use. - public static Image DebugSave( - this Image image, + public static Image DebugSave( + this Image image, ITestImageProvider provider, object testOutputDetails = null, string extension = "png", bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true, IImageEncoder encoder = null) - where TPixel : struct, IPixel { if (TestEnvironment.RunsOnCI) { @@ -111,37 +108,34 @@ namespace SixLabors.ImageSharp.Tests return image; } - public static Image DebugSave( - this Image image, + public static void DebugSave( + this Image image, ITestImageProvider provider, IImageEncoder encoder, FormattableString testOutputDetails, bool appendPixelTypeToFileName = true) - where TPixel : struct, IPixel { - return image.DebugSave(provider, encoder, (object)testOutputDetails, appendPixelTypeToFileName); + image.DebugSave(provider, encoder, (object)testOutputDetails, appendPixelTypeToFileName); } /// /// Saves the image only when not running in the CI server. /// - /// The pixel format /// The image /// The image provider /// The image encoder /// Details to be concatenated to the test output file, describing the parameters of the test. /// A boolean indicating whether to append the pixel type to the output file name. - public static Image DebugSave( - this Image image, + public static void DebugSave( + this Image image, ITestImageProvider provider, IImageEncoder encoder, object testOutputDetails = null, bool appendPixelTypeToFileName = true) - where TPixel : struct, IPixel { if (TestEnvironment.RunsOnCI) { - return image; + return; } // We are running locally then we want to save it out @@ -150,7 +144,6 @@ namespace SixLabors.ImageSharp.Tests encoder: encoder, testOutputDetails: testOutputDetails, appendPixelTypeToFileName: appendPixelTypeToFileName); - return image; } public static Image DebugSaveMultiFrame( diff --git a/tests/Images/External b/tests/Images/External index 55c250ab8..9d1d9dd53 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 55c250ab80f7f9fc26208b9b9d9590cbe8012446 +Subproject commit 9d1d9dd53755007ee812907f64304d1925c6a91a From 0bd86ddcb698d59008d265db2f576ae345740d68 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 13 May 2019 01:56:07 +0200 Subject: [PATCH 187/223] non-generic DrawImageProcessor --- .../Extensions/DrawImageExtensions.cs | 134 +++++++++++------- .../Processors/Drawing/DrawImageProcessor.cs | 117 ++++++++++++--- 2 files changed, 187 insertions(+), 64 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs index 58459ebc5..981cf1bef 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/DrawImageExtensions.cs @@ -15,98 +15,126 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + float opacity) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + Point.Empty, + GraphicsOptions.Default.ColorBlendingMode, + GraphicsOptions.Default.AlphaCompositionMode, + opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The blending mode. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + PixelColorBlendingMode colorBlending, + float opacity) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + Point.Empty, + colorBlending, + GraphicsOptions.Default.AlphaCompositionMode, + opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The color blending mode. /// The alpha composition mode. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + PixelColorBlendingMode colorBlending, + PixelAlphaCompositionMode alphaComposition, + float opacity) => + source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The options, including the blending type and blending amount. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, GraphicsOptions options) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + GraphicsOptions options) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + Point.Empty, + options.ColorBlendingMode, + options.AlphaCompositionMode, + options.BlendPercentage)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, GraphicsOptions.Default.ColorBlendingMode, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + float opacity) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + location, + GraphicsOptions.Default.ColorBlendingMode, + GraphicsOptions.Default.AlphaCompositionMode, + opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The color blending to apply. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, GraphicsOptions.Default.AlphaCompositionMode, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + PixelColorBlendingMode colorBlending, + float opacity) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + location, + colorBlending, + GraphicsOptions.Default.AlphaCompositionMode, + opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. @@ -114,24 +142,34 @@ namespace SixLabors.ImageSharp.Processing /// The alpha composition mode. /// The opacity of the image to blend. Must be between 0 and 1. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, float opacity) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + PixelColorBlendingMode colorBlending, + PixelAlphaCompositionMode alphaComposition, + float opacity) => + source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); /// /// Draws the given image together with the current one by blending their pixels. /// - /// The pixel format of the destination image. - /// The pixel format of the source image. /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. /// The options containing the blend mode and opacity. /// The . - public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, GraphicsOptions options) - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel - => source.ApplyProcessor(new DrawImageProcessor(image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage)); + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + GraphicsOptions options) => + source.ApplyProcessor( + new DrawImageProcessor( + image, + location, + options.ColorBlendingMode, + options.AlphaCompositionMode, + options.BlendPercentage)); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs index 6c03537eb..0fbef9afe 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -13,14 +13,90 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { + public class DrawImageProcessor : IImageProcessor + { + public DrawImageProcessor( + Image image, + Point location, + PixelColorBlendingMode colorBlendingMode, + PixelAlphaCompositionMode alphaCompositionMode, + float opacity) + { + this.Image = image; + this.Location = location; + this.ColorBlendingMode = colorBlendingMode; + this.AlphaCompositionMode = alphaCompositionMode; + this.Opacity = opacity; + } + + /// + /// Gets the image to blend + /// + public Image Image { get; } + + /// + /// Gets the location to draw the blended image + /// + public Point Location { get; } + + /// + /// Gets the blending mode to use when drawing the image. + /// + public PixelColorBlendingMode ColorBlendingMode { get; } + + /// + /// Gets the Alpha blending mode to use when drawing the image. + /// + public PixelAlphaCompositionMode AlphaCompositionMode { get; } + + /// + /// Gets the opacity of the image to blend + /// + public float Opacity { get; } + + /// + public IImageProcessor CreatePixelSpecificProcessor() + where TPixelBg : struct, IPixel + { + var visitor = new ProcessorFactoryVisitor(this); + this.Image.AcceptVisitor(visitor); + return visitor.Result; + } + + private class ProcessorFactoryVisitor : IImageVisitor + where TPixelBg : struct, IPixel + { + private readonly DrawImageProcessor definition; + + public ProcessorFactoryVisitor(DrawImageProcessor definition) + { + this.definition = definition; + } + + public IImageProcessor Result { get; private set; } + + public void Visit(Image image) + where TPixelFg : struct, IPixel + { + this.Result = new DrawImageProcessor( + image, + this.definition.Location, + this.definition.ColorBlendingMode, + this.definition.AlphaCompositionMode, + this.definition.Opacity + ); + } + } + } + /// /// Combines two images together by blending the pixels. /// - /// The pixel format of destination image. - /// The pixel format of source image. - internal class DrawImageProcessor : ImageProcessor - where TPixelDst : struct, IPixel - where TPixelSrc : struct, IPixel + /// The pixel format of destination image. + /// The pixel format of source image. + internal class DrawImageProcessor : ImageProcessor + where TPixelBg : struct, IPixel + where TPixelFg : struct, IPixel { /// /// Initializes a new instance of the class. @@ -30,20 +106,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing /// The blending mode to use when drawing the image. /// The Alpha blending mode to use when drawing the image. /// The opacity of the image to blend. Must be between 0 and 1. - public DrawImageProcessor(Image image, Point location, PixelColorBlendingMode colorBlendingMode, PixelAlphaCompositionMode alphaCompositionMode, float opacity) + public DrawImageProcessor( + Image image, + Point location, + PixelColorBlendingMode colorBlendingMode, + PixelAlphaCompositionMode alphaCompositionMode, + float opacity) { Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); this.Image = image; this.Opacity = opacity; - this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode); + this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode); this.Location = location; } /// /// Gets the image to blend /// - public Image Image { get; } + public Image Image { get; } /// /// Gets the opacity of the image to blend @@ -53,7 +134,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing /// /// Gets the pixel blender /// - public PixelBlender Blender { get; } + public PixelBlender Blender { get; } /// /// Gets the location to draw the blended image @@ -61,10 +142,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing public Point Location { get; } /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) { - Image targetImage = this.Image; - PixelBlender blender = this.Blender; + Image targetImage = this.Image; + PixelBlender blender = this.Blender; int locationY = this.Location.Y; // Align start/end positions. @@ -84,7 +168,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing // not a valid operation because rectangle does not overlap with this image. if (workingRect.Width <= 0 || workingRect.Height <= 0) { - throw new ImageProcessingException("Cannot draw image because the source image does not overlap the target image."); + throw new ImageProcessingException( + "Cannot draw image because the source image does not overlap the target image."); } ParallelHelper.IterateRows( @@ -94,10 +179,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing { for (int y = rows.Min; y < rows.Max; y++) { - Span background = source.GetPixelRowSpan(y).Slice(minX, width); - Span foreground = + Span background = source.GetPixelRowSpan(y).Slice(minX, width); + Span foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); - blender.Blend(configuration, background, background, foreground, this.Opacity); + blender.Blend(configuration, background, background, foreground, this.Opacity); } }); } From 3b7a74141f259f70da6826426f57c105ddf6899e Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 13 May 2019 02:13:16 +0200 Subject: [PATCH 188/223] DrawImageOfDifferentPixelType test cases --- .../Drawing/DrawImageTests.cs | 22 +++++++++++++++++-- tests/Images/External | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index e48a0b0ae..cb44651d6 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -96,8 +96,26 @@ namespace SixLabors.ImageSharp.Tests.Drawing testInfo); } } - - + + [Theory] + [WithTestPatternImages(200, 200, PixelTypes.Rgba32 | PixelTypes.Bgra32)] + public void DrawImageOfDifferentPixelType(TestImageProvider provider) + where TPixel : struct, IPixel + { + byte[] brushData = TestFile.Create(TestImages.Png.Ducky).Bytes; + + using (Image image = provider.GetImage()) + using (Image brushImage = provider.PixelType == PixelTypes.Rgba32 + ? (Image)Image.Load(brushData) + : Image.Load(brushData)) + { + image.Mutate(c => c.DrawImage(brushImage, 0.5f)); + + image.DebugSave(provider, appendSourceFileOrDescription: false); + image.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false); + } + } + [Theory] [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 0, 0)] [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 25, 25)] diff --git a/tests/Images/External b/tests/Images/External index 9d1d9dd53..82f082ed3 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 9d1d9dd53755007ee812907f64304d1925c6a91a +Subproject commit 82f082ed3b47cc21b38dda9c5f8dda06dca5233a From b7dadca8b0434ae2e46acac1dbd07efab0234386 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 13 May 2019 23:52:03 +0200 Subject: [PATCH 189/223] clean-up drawing processors --- .../ImageSharp.Drawing.csproj | 2 +- .../Processing/BrushApplicator.cs | 2 +- .../Processing/PatternBrush.cs | 2 +- .../Processors/Drawing/DrawImageProcessor.cs | 131 +---- .../DrawImageProcessor{TPixelBg,TPixelFg}.cs | 111 +++++ .../Processors/Drawing/FillProcessor.cs | 128 +---- .../Drawing/FillProcessor{TPixel}.cs | 118 +++++ .../Processors/Drawing/FillRegionProcessor.cs | 197 +------- .../Drawing/FillRegionProcessor{TPixel}.cs | 195 ++++++++ .../Processors/Text/DrawTextProcessor.cs | 445 +---------------- .../Text/DrawTextProcessor{TPixel}.cs | 446 ++++++++++++++++++ .../Processing/RadialGradientBrush.cs | 1 - .../Processing/SolidBrush.cs | 4 +- .../Processing/TextGraphicsOptions.cs | 328 +++++++------ src/ImageSharp/Image.cs | 2 +- src/ImageSharp/ImageSharp.csproj | 2 +- 16 files changed, 1088 insertions(+), 1026 deletions(-) create mode 100644 src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs create mode 100644 src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs create mode 100644 src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs create mode 100644 src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index fdeb27a77..722ef33ff 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -40,9 +40,9 @@ + - diff --git a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs index 0c6e0d3b4..7e75d7eff 100644 --- a/src/ImageSharp.Drawing/Processing/BrushApplicator.cs +++ b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets the blend percentage /// - protected GraphicsOptions Options { get; private set; } + protected GraphicsOptions Options { get; } /// /// Gets the color for a single pixel. diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush.cs b/src/ImageSharp.Drawing/Processing/PatternBrush.cs index 21690055e..a7a6785b9 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush.cs @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The brush. internal PatternBrush(PatternBrush brush) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs index 0fbef9afe..54b7315b2 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -1,20 +1,29 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; using System.Buffers; using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; + using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { + /// + /// Combines two images together by blending the pixels. + /// public class DrawImageProcessor : IImageProcessor { + /// + /// Initializes a new instance of the class. + /// + /// The image to blend. + /// The location to draw the blended image. + /// The blending mode to use when drawing the image. + /// The Alpha blending mode to use when drawing the image. + /// The opacity of the image to blend. public DrawImageProcessor( Image image, Point location, @@ -30,27 +39,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } /// - /// Gets the image to blend + /// Gets the image to blend. /// public Image Image { get; } /// - /// Gets the location to draw the blended image + /// Gets the location to draw the blended image. /// public Point Location { get; } - + /// /// Gets the blending mode to use when drawing the image. /// public PixelColorBlendingMode ColorBlendingMode { get; } - + /// /// Gets the Alpha blending mode to use when drawing the image. /// public PixelAlphaCompositionMode AlphaCompositionMode { get; } - + /// - /// Gets the opacity of the image to blend + /// Gets the opacity of the image to blend. /// public float Opacity { get; } @@ -74,7 +83,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } public IImageProcessor Result { get; private set; } - + public void Visit(Image image) where TPixelFg : struct, IPixel { @@ -83,108 +92,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing this.definition.Location, this.definition.ColorBlendingMode, this.definition.AlphaCompositionMode, - this.definition.Opacity - ); + this.definition.Opacity); } } } - - /// - /// Combines two images together by blending the pixels. - /// - /// The pixel format of destination image. - /// The pixel format of source image. - internal class DrawImageProcessor : ImageProcessor - where TPixelBg : struct, IPixel - where TPixelFg : struct, IPixel - { - /// - /// Initializes a new instance of the class. - /// - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The blending mode to use when drawing the image. - /// The Alpha blending mode to use when drawing the image. - /// The opacity of the image to blend. Must be between 0 and 1. - public DrawImageProcessor( - Image image, - Point location, - PixelColorBlendingMode colorBlendingMode, - PixelAlphaCompositionMode alphaCompositionMode, - float opacity) - { - Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); - - this.Image = image; - this.Opacity = opacity; - this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode); - this.Location = location; - } - - /// - /// Gets the image to blend - /// - public Image Image { get; } - - /// - /// Gets the opacity of the image to blend - /// - public float Opacity { get; } - - /// - /// Gets the pixel blender - /// - public PixelBlender Blender { get; } - - /// - /// Gets the location to draw the blended image - /// - public Point Location { get; } - - /// - protected override void OnFrameApply( - ImageFrame source, - Rectangle sourceRectangle, - Configuration configuration) - { - Image targetImage = this.Image; - PixelBlender blender = this.Blender; - int locationY = this.Location.Y; - - // Align start/end positions. - Rectangle bounds = targetImage.Bounds(); - - int minX = Math.Max(this.Location.X, sourceRectangle.X); - int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Right); - int targetX = minX - this.Location.X; - - int minY = Math.Max(this.Location.Y, sourceRectangle.Y); - int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); - - int width = maxX - minX; - - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); - - // not a valid operation because rectangle does not overlap with this image. - if (workingRect.Width <= 0 || workingRect.Height <= 0) - { - throw new ImageProcessingException( - "Cannot draw image because the source image does not overlap the target image."); - } - - ParallelHelper.IterateRows( - workingRect, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span background = source.GetPixelRowSpan(y).Slice(minX, width); - Span foreground = - targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); - blender.Blend(configuration, background, background, foreground, this.Opacity); - } - }); - } - } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs new file mode 100644 index 000000000..21599bf78 --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs @@ -0,0 +1,111 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Drawing +{ + /// + /// Combines two images together by blending the pixels. + /// + /// The pixel format of destination image. + /// The pixel format of source image. + internal class DrawImageProcessor : ImageProcessor + where TPixelBg : struct, IPixel + where TPixelFg : struct, IPixel + { + /// + /// Initializes a new instance of the class. + /// + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The blending mode to use when drawing the image. + /// The Alpha blending mode to use when drawing the image. + /// The opacity of the image to blend. Must be between 0 and 1. + public DrawImageProcessor( + Image image, + Point location, + PixelColorBlendingMode colorBlendingMode, + PixelAlphaCompositionMode alphaCompositionMode, + float opacity) + { + Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); + + this.Image = image; + this.Opacity = opacity; + this.Blender = PixelOperations.Instance.GetPixelBlender(colorBlendingMode, alphaCompositionMode); + this.Location = location; + } + + /// + /// Gets the image to blend + /// + public Image Image { get; } + + /// + /// Gets the opacity of the image to blend + /// + public float Opacity { get; } + + /// + /// Gets the pixel blender + /// + public PixelBlender Blender { get; } + + /// + /// Gets the location to draw the blended image + /// + public Point Location { get; } + + /// + protected override void OnFrameApply( + ImageFrame source, + Rectangle sourceRectangle, + Configuration configuration) + { + Image targetImage = this.Image; + PixelBlender blender = this.Blender; + int locationY = this.Location.Y; + + // Align start/end positions. + Rectangle bounds = targetImage.Bounds(); + + int minX = Math.Max(this.Location.X, sourceRectangle.X); + int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Right); + int targetX = minX - this.Location.X; + + int minY = Math.Max(this.Location.Y, sourceRectangle.Y); + int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); + + int width = maxX - minX; + + var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + + // not a valid operation because rectangle does not overlap with this image. + if (workingRect.Width <= 0 || workingRect.Height <= 0) + { + throw new ImageProcessingException( + "Cannot draw image because the source image does not overlap the target image."); + } + + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span background = source.GetPixelRowSpan(y).Slice(minX, width); + Span foreground = + targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); + blender.Blend(configuration, background, background, foreground, this.Opacity); + } + }); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs index 8ea1c48cc..d6254c7cf 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs @@ -1,28 +1,38 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; using System.Threading.Tasks; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.ParallelUtils; + using SixLabors.ImageSharp.PixelFormats; using SixLabors.Memory; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { + /// + /// Defines a processor to fill an with the given + /// using blending defined by the given . + /// public class FillProcessor : IImageProcessor { + /// + /// Initializes a new instance of the class. + /// + /// The brush to use for filling. + /// The defining how to blend the brush pixels over the image pixels. public FillProcessor(IBrush brush, GraphicsOptions options) { this.Brush = brush; this.Options = options; } + /// + /// Gets the used for filling the destination image. + /// public IBrush Brush { get; } - + + /// + /// Gets the defining how to blend the brush pixels over the image pixels. + /// public GraphicsOptions Options { get; } /// @@ -32,108 +42,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing return new FillProcessor(this); } } - - /// - /// Using the brush as a source of pixels colors blends the brush color with source. - /// - /// The pixel format. - internal class FillProcessor : ImageProcessor - where TPixel : struct, IPixel - { - private readonly FillProcessor definition; - - public FillProcessor(FillProcessor definition) - { - this.definition = definition; - } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - int startY = sourceRectangle.Y; - int endY = sourceRectangle.Bottom; - - // Align start/end positions. - int minX = Math.Max(0, startX); - int maxX = Math.Min(source.Width, endX); - int minY = Math.Max(0, startY); - int maxY = Math.Min(source.Height, endY); - - int width = maxX - minX; - - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); - - IBrush brush = this.definition.Brush; - GraphicsOptions options = this.definition.Options; - - // If there's no reason for blending, then avoid it. - if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) - { - ParallelExecutionSettings parallelSettings = configuration.GetParallelSettings().MultiplyMinimumPixelsPerTask(4); - - TPixel colorPixel = solidBrush.Color.ToPixel(); - - ParallelHelper.IterateRows( - workingRect, - parallelSettings, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - source.GetPixelRowSpan(y).Slice(minX, width).Fill(colorPixel); - } - }); - } - else - { - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - startY = 0; - } - - using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width)) - using (BrushApplicator applicator = brush.CreateApplicator( - source, - sourceRectangle, - options)) - { - amount.GetSpan().Fill(1f); - - ParallelHelper.IterateRows( - workingRect, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - int offsetY = y - startY; - int offsetX = minX - startX; - - applicator.Apply(amount.GetSpan(), offsetX, offsetY); - } - }); - } - } - } - - private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) - { - solidBrush = this.definition.Brush as SolidBrush; - - if (solidBrush == null) - { - return false; - } - - return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); - } - } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs new file mode 100644 index 000000000..68aef82e2 --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor{TPixel}.cs @@ -0,0 +1,118 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Drawing +{ + /// + /// Using the brush as a source of pixels colors blends the brush color with source. + /// + /// The pixel format. + internal class FillProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly FillProcessor definition; + + public FillProcessor(FillProcessor definition) + { + this.definition = definition; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + int startX = sourceRectangle.X; + int endX = sourceRectangle.Right; + int startY = sourceRectangle.Y; + int endY = sourceRectangle.Bottom; + + // Align start/end positions. + int minX = Math.Max(0, startX); + int maxX = Math.Min(source.Width, endX); + int minY = Math.Max(0, startY); + int maxY = Math.Min(source.Height, endY); + + int width = maxX - minX; + + var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + + IBrush brush = this.definition.Brush; + GraphicsOptions options = this.definition.Options; + + // If there's no reason for blending, then avoid it. + if (this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush)) + { + ParallelExecutionSettings parallelSettings = configuration.GetParallelSettings().MultiplyMinimumPixelsPerTask(4); + + TPixel colorPixel = solidBrush.Color.ToPixel(); + + ParallelHelper.IterateRows( + workingRect, + parallelSettings, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + source.GetPixelRowSpan(y).Slice(minX, width).Fill(colorPixel); + } + }); + } + else + { + // Reset offset if necessary. + if (minX > 0) + { + startX = 0; + } + + if (minY > 0) + { + startY = 0; + } + + using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width)) + using (BrushApplicator applicator = brush.CreateApplicator( + source, + sourceRectangle, + options)) + { + amount.GetSpan().Fill(1f); + + ParallelHelper.IterateRows( + workingRect, + configuration, + rows => + { + for (int y = rows.Min; y < rows.Max; y++) + { + int offsetY = y - startY; + int offsetX = minX - startX; + + applicator.Apply(amount.GetSpan(), offsetX, offsetY); + } + }); + } + } + } + + private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) + { + solidBrush = this.definition.Brush as SolidBrush; + + if (solidBrush == null) + { + return false; + } + + return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs index 3653102ef..1b207d4cd 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs @@ -1,18 +1,16 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Buffers; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Utils; using SixLabors.Memory; -using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Drawing { + /// + /// Defines a processor to fill pixels withing a given + /// with the given and blending defined by the given . + /// public class FillRegionProcessor : IImageProcessor { /// @@ -29,7 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing } /// - /// Gets the brush. + /// Gets the used for filling the destination image. /// public IBrush Brush { get; } @@ -39,11 +37,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing public Region Region { get; } /// - /// Gets the options. + /// Gets the defining how to blend the brush pixels over the image pixels. /// - /// - /// The options. - /// public GraphicsOptions Options { get; } /// @@ -53,184 +48,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing return new FillRegionProcessor(this); } } - - /// - /// Using a brush and a shape fills shape with contents of brush the - /// - /// The type of the color. - /// - internal class FillRegionProcessor : ImageProcessor - where TPixel : struct, IPixel - { - private readonly FillRegionProcessor definition; - - public FillRegionProcessor(FillRegionProcessor definition) - { - this.definition = definition; - } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - GraphicsOptions options = this.definition.Options; - IBrush brush = this.definition.Brush; - Region region = this.definition.Region; - Rectangle rect = region.Bounds; - - // Align start/end positions. - int minX = Math.Max(0, rect.Left); - int maxX = Math.Min(source.Width, rect.Right); - int minY = Math.Max(0, rect.Top); - int maxY = Math.Min(source.Height, rect.Bottom); - if (minX >= maxX) - { - return; // no effect inside image; - } - - if (minY >= maxY) - { - return; // no effect inside image; - } - - int maxIntersections = region.MaxIntersections; - float subpixelCount = 4; - - // we need to offset the pixel grid to account for when we outline a path. - // basically if the line is [1,2] => [3,2] then when outlining at 1 we end up with a region of [0.5,1.5],[1.5, 1.5],[3.5,2.5],[2.5,2.5] - // and this can cause missed fills when not using antialiasing.so we offset the pixel grid by 0.5 in the x & y direction thus causing the# - // region to align with the pixel grid. - float offset = 0.5f; - if (options.Antialias) - { - offset = 0f; // we are antialiasing skip offsetting as real antialiasing should take care of offset. - subpixelCount = options.AntialiasSubpixelDepth; - if (subpixelCount < 4) - { - subpixelCount = 4; - } - } - - using (BrushApplicator applicator = brush.CreateApplicator(source, rect, options)) - { - int scanlineWidth = maxX - minX; - using (IMemoryOwner bBuffer = source.MemoryAllocator.Allocate(maxIntersections)) - using (IMemoryOwner bScanline = source.MemoryAllocator.Allocate(scanlineWidth)) - { - bool scanlineDirty = true; - float subpixelFraction = 1f / subpixelCount; - float subpixelFractionPoint = subpixelFraction / subpixelCount; - - Span buffer = bBuffer.GetSpan(); - Span scanline = bScanline.GetSpan(); - - bool isSolidBrushWithoutBlending = this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush); - TPixel solidBrushColor = isSolidBrushWithoutBlending ? solidBrush.Color.ToPixel() : default; - - for (int y = minY; y < maxY; y++) - { - if (scanlineDirty) - { - scanline.Clear(); - scanlineDirty = false; - } - - float yPlusOne = y + 1; - for (float subPixel = (float)y; subPixel < yPlusOne; subPixel += subpixelFraction) - { - int pointsFound = region.Scan(subPixel + offset, buffer, configuration); - if (pointsFound == 0) - { - // nothing on this line, skip - continue; - } - - QuickSort.Sort(buffer.Slice(0, pointsFound)); - - for (int point = 0; point < pointsFound; point += 2) - { - // points will be paired up - float scanStart = buffer[point] - minX; - float scanEnd = buffer[point + 1] - minX; - int startX = (int)MathF.Floor(scanStart + offset); - int endX = (int)MathF.Floor(scanEnd + offset); - - if (startX >= 0 && startX < scanline.Length) - { - for (float x = scanStart; x < startX + 1; x += subpixelFraction) - { - scanline[startX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - if (endX >= 0 && endX < scanline.Length) - { - for (float x = endX; x < scanEnd; x += subpixelFraction) - { - scanline[endX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - int nextX = startX + 1; - endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge - nextX = Math.Max(nextX, 0); - for (int x = nextX; x < endX; x++) - { - scanline[x] += subpixelFraction; - scanlineDirty = true; - } - } - } - - if (scanlineDirty) - { - if (!options.Antialias) - { - bool hasOnes = false; - bool hasZeros = false; - for (int x = 0; x < scanlineWidth; x++) - { - if (scanline[x] >= 0.5) - { - scanline[x] = 1; - hasOnes = true; - } - else - { - scanline[x] = 0; - hasZeros = true; - } - } - - if (isSolidBrushWithoutBlending && hasOnes != hasZeros) - { - if (hasOnes) - { - source.GetPixelRowSpan(y).Slice(minX, scanlineWidth).Fill(solidBrushColor); - } - - continue; - } - } - - applicator.Apply(scanline, minX, y); - } - } - } - } - } - - private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) - { - solidBrush = this.definition.Brush as SolidBrush; - - if (solidBrush == null) - { - return false; - } - - return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); - } - } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs new file mode 100644 index 000000000..d5778c865 --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor{TPixel}.cs @@ -0,0 +1,195 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Primitives; +using SixLabors.ImageSharp.Utils; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.Drawing +{ + /// + /// Using a brush and a shape fills shape with contents of brush the + /// + /// The type of the color. + /// + internal class FillRegionProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private readonly FillRegionProcessor definition; + + public FillRegionProcessor(FillRegionProcessor definition) + { + this.definition = definition; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + GraphicsOptions options = this.definition.Options; + IBrush brush = this.definition.Brush; + Region region = this.definition.Region; + Rectangle rect = region.Bounds; + + // Align start/end positions. + int minX = Math.Max(0, rect.Left); + int maxX = Math.Min(source.Width, rect.Right); + int minY = Math.Max(0, rect.Top); + int maxY = Math.Min(source.Height, rect.Bottom); + if (minX >= maxX) + { + return; // no effect inside image; + } + + if (minY >= maxY) + { + return; // no effect inside image; + } + + int maxIntersections = region.MaxIntersections; + float subpixelCount = 4; + + // we need to offset the pixel grid to account for when we outline a path. + // basically if the line is [1,2] => [3,2] then when outlining at 1 we end up with a region of [0.5,1.5],[1.5, 1.5],[3.5,2.5],[2.5,2.5] + // and this can cause missed fills when not using antialiasing.so we offset the pixel grid by 0.5 in the x & y direction thus causing the# + // region to align with the pixel grid. + float offset = 0.5f; + if (options.Antialias) + { + offset = 0f; // we are antialiasing skip offsetting as real antialiasing should take care of offset. + subpixelCount = options.AntialiasSubpixelDepth; + if (subpixelCount < 4) + { + subpixelCount = 4; + } + } + + using (BrushApplicator applicator = brush.CreateApplicator(source, rect, options)) + { + int scanlineWidth = maxX - minX; + using (IMemoryOwner bBuffer = source.MemoryAllocator.Allocate(maxIntersections)) + using (IMemoryOwner bScanline = source.MemoryAllocator.Allocate(scanlineWidth)) + { + bool scanlineDirty = true; + float subpixelFraction = 1f / subpixelCount; + float subpixelFractionPoint = subpixelFraction / subpixelCount; + + Span buffer = bBuffer.GetSpan(); + Span scanline = bScanline.GetSpan(); + + bool isSolidBrushWithoutBlending = this.IsSolidBrushWithoutBlending(out SolidBrush solidBrush); + TPixel solidBrushColor = isSolidBrushWithoutBlending ? solidBrush.Color.ToPixel() : default; + + for (int y = minY; y < maxY; y++) + { + if (scanlineDirty) + { + scanline.Clear(); + scanlineDirty = false; + } + + float yPlusOne = y + 1; + for (float subPixel = (float)y; subPixel < yPlusOne; subPixel += subpixelFraction) + { + int pointsFound = region.Scan(subPixel + offset, buffer, configuration); + if (pointsFound == 0) + { + // nothing on this line, skip + continue; + } + + QuickSort.Sort(buffer.Slice(0, pointsFound)); + + for (int point = 0; point < pointsFound; point += 2) + { + // points will be paired up + float scanStart = buffer[point] - minX; + float scanEnd = buffer[point + 1] - minX; + int startX = (int)MathF.Floor(scanStart + offset); + int endX = (int)MathF.Floor(scanEnd + offset); + + if (startX >= 0 && startX < scanline.Length) + { + for (float x = scanStart; x < startX + 1; x += subpixelFraction) + { + scanline[startX] += subpixelFractionPoint; + scanlineDirty = true; + } + } + + if (endX >= 0 && endX < scanline.Length) + { + for (float x = endX; x < scanEnd; x += subpixelFraction) + { + scanline[endX] += subpixelFractionPoint; + scanlineDirty = true; + } + } + + int nextX = startX + 1; + endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge + nextX = Math.Max(nextX, 0); + for (int x = nextX; x < endX; x++) + { + scanline[x] += subpixelFraction; + scanlineDirty = true; + } + } + } + + if (scanlineDirty) + { + if (!options.Antialias) + { + bool hasOnes = false; + bool hasZeros = false; + for (int x = 0; x < scanlineWidth; x++) + { + if (scanline[x] >= 0.5) + { + scanline[x] = 1; + hasOnes = true; + } + else + { + scanline[x] = 0; + hasZeros = true; + } + } + + if (isSolidBrushWithoutBlending && hasOnes != hasZeros) + { + if (hasOnes) + { + source.GetPixelRowSpan(y).Slice(minX, scanlineWidth).Fill(solidBrushColor); + } + + continue; + } + } + + applicator.Apply(scanline, minX, y); + } + } + } + } + } + + private bool IsSolidBrushWithoutBlending(out SolidBrush solidBrush) + { + solidBrush = this.definition.Brush as SolidBrush; + + if (solidBrush == null) + { + return false; + } + + return this.definition.Options.IsOpaqueColorWithoutBlending(solidBrush.Color); + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs index d1e28afeb..40621ce99 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs @@ -2,19 +2,16 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Buffers; -using System.Collections.Generic; + using SixLabors.Fonts; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Utils; -using SixLabors.Memory; using SixLabors.Primitives; -using SixLabors.Shapes; namespace SixLabors.ImageSharp.Processing.Processors.Text { + /// + /// Defines a processor to draw text on an . + /// public class DrawTextProcessor : IImageProcessor { /// @@ -45,17 +42,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text } /// - /// Gets the brush. + /// Gets the brush used to fill the glyphs. /// public IBrush Brush { get; } /// - /// Gets the options + /// Gets the defining blending modes and text-specific drawing settings. /// public TextGraphicsOptions Options { get; } /// - /// Gets the text + /// Gets the text to draw. /// public string Text { get; } @@ -81,432 +78,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text return new DrawTextProcessor(this); } } - - /// - /// Using the brush as a source of pixels colors blends the brush color with source. - /// - /// The pixel format. - internal class DrawTextProcessor : ImageProcessor - where TPixel : struct, IPixel - { - private CachingGlyphRenderer textRenderer; - - private readonly DrawTextProcessor definition; - - public DrawTextProcessor(DrawTextProcessor definition) - { - this.definition = definition; - } - - private TextGraphicsOptions Options => this.definition.Options; - - private Font Font => this.definition.Font; - - private PointF Location => this.definition.Location; - - private string Text => this.definition.Text; - - private IPen Pen => this.definition.Pen; - - private IBrush Brush => this.definition.Brush; - - protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) - { - base.BeforeImageApply(source, sourceRectangle); - - // do everything at the image level as we are delegating the processing down to other processors - var style = new RendererOptions(this.Font, this.Options.DpiX, this.Options.DpiY, this.Location) - { - ApplyKerning = this.Options.ApplyKerning, - TabWidth = this.Options.TabWidth, - WrappingWidth = this.Options.WrapTextWidth, - HorizontalAlignment = this.Options.HorizontalAlignment, - VerticalAlignment = this.Options.VerticalAlignment - }; - - this.textRenderer = new CachingGlyphRenderer(source.GetMemoryAllocator(), this.Text.Length, this.Pen, this.Brush != null); - this.textRenderer.Options = (GraphicsOptions)this.Options; - var renderer = new TextRenderer(this.textRenderer); - renderer.RenderText(this.Text, style); - } - - protected override void AfterImageApply(Image source, Rectangle sourceRectangle) - { - base.AfterImageApply(source, sourceRectangle); - this.textRenderer?.Dispose(); - this.textRenderer = null; - } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - // this is a no-op as we have processes all as an image, we should be able to pass out of before email apply a skip frames outcome - Draw(this.textRenderer.FillOperations, this.Brush); - Draw(this.textRenderer.OutlineOperations, this.Pen?.StrokeFill); - - void Draw(List operations, IBrush brush) - { - if (operations?.Count > 0) - { - using (BrushApplicator app = brush.CreateApplicator(source, sourceRectangle, this.textRenderer.Options)) - { - foreach (DrawingOperation operation in operations) - { - Buffer2D buffer = operation.Map; - int startY = operation.Location.Y; - int startX = operation.Location.X; - int offSetSpan = 0; - if (startX < 0) - { - offSetSpan = -startX; - startX = 0; - } - - int fistRow = 0; - if (startY < 0) - { - fistRow = -startY; - } - - int maxHeight = source.Height - startY; - int end = Math.Min(operation.Map.Height, maxHeight); - - for (int row = fistRow; row < end; row++) - { - int y = startY + row; - Span span = buffer.GetRowSpan(row).Slice(offSetSpan); - app.Apply(span, startX, y); - } - } - } - } - } - } - - private struct DrawingOperation - { - public Buffer2D Map { get; set; } - - public Point Location { get; set; } - } - - private class CachingGlyphRenderer : IGlyphRenderer, IDisposable - { - // just enough accuracy to allow for 1/8 pixel differences which - // later are accumulated while rendering, but do not grow into full pixel offsets - // The value 8 is benchmarked to: - // - Provide a good accuracy (smaller than 0.2% image difference compared to the non-caching variant) - // - Cache hit ratio above 60% - private const float AccuracyMultiple = 8; - - private readonly PathBuilder builder; - - private Point currentRenderPosition = default; - private (GlyphRendererParameters glyph, PointF subPixelOffset) currentGlyphRenderParams = default; - private readonly int offset = 0; - private PointF currentPoint = default(PointF); - - private readonly Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> - glyphData = new Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData>(); - - private readonly bool renderOutline = false; - private readonly bool renderFill = false; - private bool rasterizationRequired = false; - - public CachingGlyphRenderer(MemoryAllocator memoryAllocator, int size, IPen pen, bool renderFill) - { - this.MemoryAllocator = memoryAllocator; - this.Pen = pen; - this.renderFill = renderFill; - this.renderOutline = pen != null; - this.offset = 2; - if (this.renderFill) - { - this.FillOperations = new List(size); - } - - if (this.renderOutline) - { - this.offset = (int)MathF.Ceiling((pen.StrokeWidth * 2) + 2); - this.OutlineOperations = new List(size); - } - - this.builder = new PathBuilder(); - } - - public List FillOperations { get; } - - public List OutlineOperations { get; } - - public MemoryAllocator MemoryAllocator { get; internal set; } - - public IPen Pen { get; internal set; } - - public GraphicsOptions Options { get; internal set; } - - public void BeginFigure() - { - this.builder.StartFigure(); - } - - public bool BeginGlyph(RectangleF bounds, GlyphRendererParameters parameters) - { - this.currentRenderPosition = Point.Truncate(bounds.Location); - PointF subPixelOffset = bounds.Location - this.currentRenderPosition; - - subPixelOffset.X = MathF.Round(subPixelOffset.X * AccuracyMultiple) / AccuracyMultiple; - subPixelOffset.Y = MathF.Round(subPixelOffset.Y * AccuracyMultiple) / AccuracyMultiple; - - // we have offset our rendering origion a little bit down to prevent edge cropping, move the draw origin up to compensate - this.currentRenderPosition = new Point(this.currentRenderPosition.X - this.offset, this.currentRenderPosition.Y - this.offset); - this.currentGlyphRenderParams = (parameters, subPixelOffset); - - if (this.glyphData.ContainsKey(this.currentGlyphRenderParams)) - { - // we have already drawn the glyph vectors skip trying again - this.rasterizationRequired = false; - return false; - } - - // we check to see if we have a render cache and if we do then we render else - this.builder.Clear(); - - // ensure all glyphs render around [zero, zero] so offset negative root positions so when we draw the glyph we can offet it back - this.builder.SetOrigin(new PointF(-(int)bounds.X + this.offset, -(int)bounds.Y + this.offset)); - - this.rasterizationRequired = true; - return true; - } - - public void BeginText(RectangleF bounds) - { - // not concerned about this one - this.OutlineOperations?.Clear(); - this.FillOperations?.Clear(); - } - - public void CubicBezierTo(PointF secondControlPoint, PointF thirdControlPoint, PointF point) - { - this.builder.AddBezier(this.currentPoint, secondControlPoint, thirdControlPoint, point); - this.currentPoint = point; - } - - public void Dispose() - { - foreach (KeyValuePair<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> kv in this.glyphData) - { - kv.Value.Dispose(); - } - - this.glyphData.Clear(); - } - - public void EndFigure() - { - this.builder.CloseFigure(); - } - - public void EndGlyph() - { - GlyphRenderData renderData = default; - - // has the glyoh been rendedered already???? - if (this.rasterizationRequired) - { - IPath path = this.builder.Build(); - - if (this.renderFill) - { - renderData.FillMap = this.Render(path); - } - - if (this.renderOutline) - { - if (this.Pen.StrokePattern.Length == 0) - { - path = path.GenerateOutline(this.Pen.StrokeWidth); - } - else - { - path = path.GenerateOutline(this.Pen.StrokeWidth, this.Pen.StrokePattern); - } - - renderData.OutlineMap = this.Render(path); - } - - this.glyphData[this.currentGlyphRenderParams] = renderData; - } - else - { - renderData = this.glyphData[this.currentGlyphRenderParams]; - } - - if (this.renderFill) - { - this.FillOperations.Add(new DrawingOperation - { - Location = this.currentRenderPosition, - Map = renderData.FillMap - }); - } - - if (this.renderOutline) - { - this.OutlineOperations.Add(new DrawingOperation - { - Location = this.currentRenderPosition, - Map = renderData.OutlineMap - }); - } - } - - private Buffer2D Render(IPath path) - { - Size size = Rectangle.Ceiling(path.Bounds).Size; - size = new Size(size.Width + (this.offset * 2), size.Height + (this.offset * 2)); - - float subpixelCount = 4; - float offset = 0.5f; - if (this.Options.Antialias) - { - offset = 0f; // we are antialising skip offsetting as real antalising should take care of offset. - subpixelCount = this.Options.AntialiasSubpixelDepth; - if (subpixelCount < 4) - { - subpixelCount = 4; - } - } - - // take the path inside the path builder, scan thing and generate a Buffer2d representing the glyph and cache it. - Buffer2D fullBuffer = this.MemoryAllocator.Allocate2D(size.Width + 1, size.Height + 1, AllocationOptions.Clean); - - using (IMemoryOwner bufferBacking = this.MemoryAllocator.Allocate(path.MaxIntersections)) - using (IMemoryOwner rowIntersectionBuffer = this.MemoryAllocator.Allocate(size.Width)) - { - float subpixelFraction = 1f / subpixelCount; - float subpixelFractionPoint = subpixelFraction / subpixelCount; - - for (int y = 0; y <= size.Height; y++) - { - Span scanline = fullBuffer.GetRowSpan(y); - bool scanlineDirty = false; - float yPlusOne = y + 1; - - for (float subPixel = (float)y; subPixel < yPlusOne; subPixel += subpixelFraction) - { - var start = new PointF(path.Bounds.Left - 1, subPixel); - var end = new PointF(path.Bounds.Right + 1, subPixel); - Span intersectionSpan = rowIntersectionBuffer.GetSpan(); - Span buffer = bufferBacking.GetSpan(); - int pointsFound = path.FindIntersections(start, end, intersectionSpan); - - if (pointsFound == 0) - { - // nothing on this line skip - continue; - } - - for (int i = 0; i < pointsFound && i < intersectionSpan.Length; i++) - { - buffer[i] = intersectionSpan[i].X; - } - - QuickSort.Sort(buffer.Slice(0, pointsFound)); - - for (int point = 0; point < pointsFound; point += 2) - { - // points will be paired up - float scanStart = buffer[point]; - float scanEnd = buffer[point + 1]; - int startX = (int)MathF.Floor(scanStart + offset); - int endX = (int)MathF.Floor(scanEnd + offset); - - if (startX >= 0 && startX < scanline.Length) - { - for (float x = scanStart; x < startX + 1; x += subpixelFraction) - { - scanline[startX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - if (endX >= 0 && endX < scanline.Length) - { - for (float x = endX; x < scanEnd; x += subpixelFraction) - { - scanline[endX] += subpixelFractionPoint; - scanlineDirty = true; - } - } - - int nextX = startX + 1; - endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge - nextX = Math.Max(nextX, 0); - for (int x = nextX; x < endX; x++) - { - scanline[x] += subpixelFraction; - scanlineDirty = true; - } - } - } - - if (scanlineDirty) - { - if (!this.Options.Antialias) - { - for (int x = 0; x < size.Width; x++) - { - if (scanline[x] >= 0.5) - { - scanline[x] = 1; - } - else - { - scanline[x] = 0; - } - } - } - } - } - } - - return fullBuffer; - } - - public void EndText() - { - } - - public void LineTo(PointF point) - { - this.builder.AddLine(this.currentPoint, point); - this.currentPoint = point; - } - - public void MoveTo(PointF point) - { - this.builder.StartFigure(); - this.currentPoint = point; - } - - public void QuadraticBezierTo(PointF secondControlPoint, PointF point) - { - this.builder.AddBezier(this.currentPoint, secondControlPoint, point); - this.currentPoint = point; - } - - private struct GlyphRenderData : IDisposable - { - public Buffer2D FillMap; - - public Buffer2D OutlineMap; - - public void Dispose() - { - this.FillMap?.Dispose(); - this.OutlineMap?.Dispose(); - } - } - } - } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs new file mode 100644 index 000000000..9fb52d6bc --- /dev/null +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs @@ -0,0 +1,446 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Collections.Generic; + +using SixLabors.Fonts; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Utils; +using SixLabors.Memory; +using SixLabors.Primitives; +using SixLabors.Shapes; + +namespace SixLabors.ImageSharp.Processing.Processors.Text +{ + /// + /// Using the brush as a source of pixels colors blends the brush color with source. + /// + /// The pixel format. + internal class DrawTextProcessor : ImageProcessor + where TPixel : struct, IPixel + { + private CachingGlyphRenderer textRenderer; + + private readonly DrawTextProcessor definition; + + public DrawTextProcessor(DrawTextProcessor definition) + { + this.definition = definition; + } + + private TextGraphicsOptions Options => this.definition.Options; + + private Font Font => this.definition.Font; + + private PointF Location => this.definition.Location; + + private string Text => this.definition.Text; + + private IPen Pen => this.definition.Pen; + + private IBrush Brush => this.definition.Brush; + + protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) + { + base.BeforeImageApply(source, sourceRectangle); + + // do everything at the image level as we are delegating the processing down to other processors + var style = new RendererOptions(this.Font, this.Options.DpiX, this.Options.DpiY, this.Location) + { + ApplyKerning = this.Options.ApplyKerning, + TabWidth = this.Options.TabWidth, + WrappingWidth = this.Options.WrapTextWidth, + HorizontalAlignment = this.Options.HorizontalAlignment, + VerticalAlignment = this.Options.VerticalAlignment + }; + + this.textRenderer = new CachingGlyphRenderer(source.GetMemoryAllocator(), this.Text.Length, this.Pen, this.Brush != null); + this.textRenderer.Options = (GraphicsOptions)this.Options; + var renderer = new TextRenderer(this.textRenderer); + renderer.RenderText(this.Text, style); + } + + protected override void AfterImageApply(Image source, Rectangle sourceRectangle) + { + base.AfterImageApply(source, sourceRectangle); + this.textRenderer?.Dispose(); + this.textRenderer = null; + } + + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + // this is a no-op as we have processes all as an image, we should be able to pass out of before email apply a skip frames outcome + Draw(this.textRenderer.FillOperations, this.Brush); + Draw(this.textRenderer.OutlineOperations, this.Pen?.StrokeFill); + + void Draw(List operations, IBrush brush) + { + if (operations?.Count > 0) + { + using (BrushApplicator app = brush.CreateApplicator(source, sourceRectangle, this.textRenderer.Options)) + { + foreach (DrawingOperation operation in operations) + { + Buffer2D buffer = operation.Map; + int startY = operation.Location.Y; + int startX = operation.Location.X; + int offSetSpan = 0; + if (startX < 0) + { + offSetSpan = -startX; + startX = 0; + } + + int fistRow = 0; + if (startY < 0) + { + fistRow = -startY; + } + + int maxHeight = source.Height - startY; + int end = Math.Min(operation.Map.Height, maxHeight); + + for (int row = fistRow; row < end; row++) + { + int y = startY + row; + Span span = buffer.GetRowSpan(row).Slice(offSetSpan); + app.Apply(span, startX, y); + } + } + } + } + } + } + + private struct DrawingOperation + { + public Buffer2D Map { get; set; } + + public Point Location { get; set; } + } + + private class CachingGlyphRenderer : IGlyphRenderer, IDisposable + { + // just enough accuracy to allow for 1/8 pixel differences which + // later are accumulated while rendering, but do not grow into full pixel offsets + // The value 8 is benchmarked to: + // - Provide a good accuracy (smaller than 0.2% image difference compared to the non-caching variant) + // - Cache hit ratio above 60% + private const float AccuracyMultiple = 8; + + private readonly PathBuilder builder; + + private Point currentRenderPosition = default; + private (GlyphRendererParameters glyph, PointF subPixelOffset) currentGlyphRenderParams = default; + private readonly int offset = 0; + private PointF currentPoint = default(PointF); + + private readonly Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> + glyphData = new Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData>(); + + private readonly bool renderOutline = false; + private readonly bool renderFill = false; + private bool rasterizationRequired = false; + + public CachingGlyphRenderer(MemoryAllocator memoryAllocator, int size, IPen pen, bool renderFill) + { + this.MemoryAllocator = memoryAllocator; + this.Pen = pen; + this.renderFill = renderFill; + this.renderOutline = pen != null; + this.offset = 2; + if (this.renderFill) + { + this.FillOperations = new List(size); + } + + if (this.renderOutline) + { + this.offset = (int)MathF.Ceiling((pen.StrokeWidth * 2) + 2); + this.OutlineOperations = new List(size); + } + + this.builder = new PathBuilder(); + } + + public List FillOperations { get; } + + public List OutlineOperations { get; } + + public MemoryAllocator MemoryAllocator { get; internal set; } + + public IPen Pen { get; internal set; } + + public GraphicsOptions Options { get; internal set; } + + public void BeginFigure() + { + this.builder.StartFigure(); + } + + public bool BeginGlyph(RectangleF bounds, GlyphRendererParameters parameters) + { + this.currentRenderPosition = Point.Truncate(bounds.Location); + PointF subPixelOffset = bounds.Location - this.currentRenderPosition; + + subPixelOffset.X = MathF.Round(subPixelOffset.X * AccuracyMultiple) / AccuracyMultiple; + subPixelOffset.Y = MathF.Round(subPixelOffset.Y * AccuracyMultiple) / AccuracyMultiple; + + // we have offset our rendering origion a little bit down to prevent edge cropping, move the draw origin up to compensate + this.currentRenderPosition = new Point(this.currentRenderPosition.X - this.offset, this.currentRenderPosition.Y - this.offset); + this.currentGlyphRenderParams = (parameters, subPixelOffset); + + if (this.glyphData.ContainsKey(this.currentGlyphRenderParams)) + { + // we have already drawn the glyph vectors skip trying again + this.rasterizationRequired = false; + return false; + } + + // we check to see if we have a render cache and if we do then we render else + this.builder.Clear(); + + // ensure all glyphs render around [zero, zero] so offset negative root positions so when we draw the glyph we can offet it back + this.builder.SetOrigin(new PointF(-(int)bounds.X + this.offset, -(int)bounds.Y + this.offset)); + + this.rasterizationRequired = true; + return true; + } + + public void BeginText(RectangleF bounds) + { + // not concerned about this one + this.OutlineOperations?.Clear(); + this.FillOperations?.Clear(); + } + + public void CubicBezierTo(PointF secondControlPoint, PointF thirdControlPoint, PointF point) + { + this.builder.AddBezier(this.currentPoint, secondControlPoint, thirdControlPoint, point); + this.currentPoint = point; + } + + public void Dispose() + { + foreach (KeyValuePair<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> kv in this.glyphData) + { + kv.Value.Dispose(); + } + + this.glyphData.Clear(); + } + + public void EndFigure() + { + this.builder.CloseFigure(); + } + + public void EndGlyph() + { + GlyphRenderData renderData = default; + + // has the glyoh been rendedered already???? + if (this.rasterizationRequired) + { + IPath path = this.builder.Build(); + + if (this.renderFill) + { + renderData.FillMap = this.Render(path); + } + + if (this.renderOutline) + { + if (this.Pen.StrokePattern.Length == 0) + { + path = path.GenerateOutline(this.Pen.StrokeWidth); + } + else + { + path = path.GenerateOutline(this.Pen.StrokeWidth, this.Pen.StrokePattern); + } + + renderData.OutlineMap = this.Render(path); + } + + this.glyphData[this.currentGlyphRenderParams] = renderData; + } + else + { + renderData = this.glyphData[this.currentGlyphRenderParams]; + } + + if (this.renderFill) + { + this.FillOperations.Add(new DrawingOperation + { + Location = this.currentRenderPosition, + Map = renderData.FillMap + }); + } + + if (this.renderOutline) + { + this.OutlineOperations.Add(new DrawingOperation + { + Location = this.currentRenderPosition, + Map = renderData.OutlineMap + }); + } + } + + private Buffer2D Render(IPath path) + { + Size size = Rectangle.Ceiling(path.Bounds).Size; + size = new Size(size.Width + (this.offset * 2), size.Height + (this.offset * 2)); + + float subpixelCount = 4; + float offset = 0.5f; + if (this.Options.Antialias) + { + offset = 0f; // we are antialising skip offsetting as real antalising should take care of offset. + subpixelCount = this.Options.AntialiasSubpixelDepth; + if (subpixelCount < 4) + { + subpixelCount = 4; + } + } + + // take the path inside the path builder, scan thing and generate a Buffer2d representing the glyph and cache it. + Buffer2D fullBuffer = this.MemoryAllocator.Allocate2D(size.Width + 1, size.Height + 1, AllocationOptions.Clean); + + using (IMemoryOwner bufferBacking = this.MemoryAllocator.Allocate(path.MaxIntersections)) + using (IMemoryOwner rowIntersectionBuffer = this.MemoryAllocator.Allocate(size.Width)) + { + float subpixelFraction = 1f / subpixelCount; + float subpixelFractionPoint = subpixelFraction / subpixelCount; + + for (int y = 0; y <= size.Height; y++) + { + Span scanline = fullBuffer.GetRowSpan(y); + bool scanlineDirty = false; + float yPlusOne = y + 1; + + for (float subPixel = (float)y; subPixel < yPlusOne; subPixel += subpixelFraction) + { + var start = new PointF(path.Bounds.Left - 1, subPixel); + var end = new PointF(path.Bounds.Right + 1, subPixel); + Span intersectionSpan = rowIntersectionBuffer.GetSpan(); + Span buffer = bufferBacking.GetSpan(); + int pointsFound = path.FindIntersections(start, end, intersectionSpan); + + if (pointsFound == 0) + { + // nothing on this line skip + continue; + } + + for (int i = 0; i < pointsFound && i < intersectionSpan.Length; i++) + { + buffer[i] = intersectionSpan[i].X; + } + + QuickSort.Sort(buffer.Slice(0, pointsFound)); + + for (int point = 0; point < pointsFound; point += 2) + { + // points will be paired up + float scanStart = buffer[point]; + float scanEnd = buffer[point + 1]; + int startX = (int)MathF.Floor(scanStart + offset); + int endX = (int)MathF.Floor(scanEnd + offset); + + if (startX >= 0 && startX < scanline.Length) + { + for (float x = scanStart; x < startX + 1; x += subpixelFraction) + { + scanline[startX] += subpixelFractionPoint; + scanlineDirty = true; + } + } + + if (endX >= 0 && endX < scanline.Length) + { + for (float x = endX; x < scanEnd; x += subpixelFraction) + { + scanline[endX] += subpixelFractionPoint; + scanlineDirty = true; + } + } + + int nextX = startX + 1; + endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge + nextX = Math.Max(nextX, 0); + for (int x = nextX; x < endX; x++) + { + scanline[x] += subpixelFraction; + scanlineDirty = true; + } + } + } + + if (scanlineDirty) + { + if (!this.Options.Antialias) + { + for (int x = 0; x < size.Width; x++) + { + if (scanline[x] >= 0.5) + { + scanline[x] = 1; + } + else + { + scanline[x] = 0; + } + } + } + } + } + } + + return fullBuffer; + } + + public void EndText() + { + } + + public void LineTo(PointF point) + { + this.builder.AddLine(this.currentPoint, point); + this.currentPoint = point; + } + + public void MoveTo(PointF point) + { + this.builder.StartFigure(); + this.currentPoint = point; + } + + public void QuadraticBezierTo(PointF secondControlPoint, PointF point) + { + this.builder.AddBezier(this.currentPoint, secondControlPoint, point); + this.currentPoint = point; + } + + private struct GlyphRenderData : IDisposable + { + public Buffer2D FillMap; + + public Buffer2D OutlineMap; + + public void Dispose() + { + this.FillMap?.Dispose(); + this.OutlineMap?.Dispose(); + } + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs index 84a97e7d1..aac0f2e7b 100644 --- a/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs @@ -12,7 +12,6 @@ namespace SixLabors.ImageSharp.Processing /// A Circular Gradient Brush, defined by center point and radius. /// public sealed class RadialGradientBrush : GradientBrushBase - { private readonly PointF center; diff --git a/src/ImageSharp.Drawing/Processing/SolidBrush.cs b/src/ImageSharp.Drawing/Processing/SolidBrush.cs index 75ca5aa7e..c62566f6b 100644 --- a/src/ImageSharp.Drawing/Processing/SolidBrush.cs +++ b/src/ImageSharp.Drawing/Processing/SolidBrush.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Processing private readonly Color color; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The color. public SolidBrush(Color color) @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing where TPixel : struct, IPixel { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The source image. /// The color. diff --git a/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs index 3c682a761..7f7332a57 100644 --- a/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs +++ b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs @@ -1,169 +1,163 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.Fonts; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// Options for influencing the drawing functions. - /// - public struct TextGraphicsOptions - { - private const int DefaultTextDpi = 72; - - /// - /// Represents the default . - /// - public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); - - private float? blendPercentage; - - private int? antialiasSubpixelDepth; - - private bool? antialias; - - private bool? applyKerning; - - private float? tabWidth; - - private float? dpiX; - - private float? dpiY; - - private PixelColorBlendingMode colorBlendingMode; - - private PixelAlphaCompositionMode alphaCompositionMode; - - private float wrapTextWidth; - - private HorizontalAlignment? horizontalAlignment; - - private VerticalAlignment? verticalAlignment; - - /// - /// Initializes a new instance of the struct. - /// - /// If set to true [enable antialiasing]. - public TextGraphicsOptions(bool enableAntialiasing) - { - this.applyKerning = true; - this.tabWidth = 4; - this.wrapTextWidth = 0; - this.horizontalAlignment = HorizontalAlignment.Left; - this.verticalAlignment = VerticalAlignment.Top; - - this.antialiasSubpixelDepth = 16; - this.colorBlendingMode = PixelColorBlendingMode.Normal; - this.alphaCompositionMode = PixelAlphaCompositionMode.SrcOver; - this.blendPercentage = 1; - this.antialias = enableAntialiasing; - this.dpiX = DefaultTextDpi; - this.dpiY = DefaultTextDpi; - } - - /// - /// Gets or sets a value indicating whether antialiasing should be applied. - /// - public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; } - - /// - /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. - /// - public int AntialiasSubpixelDepth { get => this.antialiasSubpixelDepth ?? 16; set => this.antialiasSubpixelDepth = value; } - - /// - /// Gets or sets a value indicating the blending percentage to apply to the drawing operation - /// - public float BlendPercentage { get => (this.blendPercentage ?? 1).Clamp(0, 1); set => this.blendPercentage = value; } - - // In the future we could expose a PixelBlender directly on here - // or some forms of PixelBlender factory for each pixel type. Will need - // some API thought post V1. - - /// - /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation - /// - public PixelColorBlendingMode ColorBlendingMode { get => this.colorBlendingMode; set => this.colorBlendingMode = value; } - - /// - /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation - /// - public PixelAlphaCompositionMode AlphaCompositionMode { get => this.alphaCompositionMode; set => this.alphaCompositionMode = value; } - - /// - /// Gets or sets a value indicating whether the text should be drawing with kerning enabled. - /// - public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; } - - /// - /// Gets or sets a value indicating the number of space widths a tab should lock to. - /// - public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; } - - /// - /// Gets or sets a value indicating if greater than zero determine the width at which text should wrap. - /// - public float WrapTextWidth { get => this.wrapTextWidth; set => this.wrapTextWidth = value; } - - /// - /// Gets or sets a value indicating the DPI to render text along the X axis. - /// - public float DpiX { get => this.dpiX ?? DefaultTextDpi; set => this.dpiX = value; } - - /// - /// Gets or sets a value indicating the DPI to render text along the Y axis. - /// - public float DpiY { get => this.dpiY ?? DefaultTextDpi; set => this.dpiY = value; } - - /// - /// Gets or sets a value indicating how to align the text relative to the rendering space. - /// If is greater than zero it will align relative to the space - /// defined by the location and width, if equals zero, and thus - /// wrapping disabled, then the alignment is relative to the drawing location. - /// - public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } - - /// - /// Gets or sets a value indicating how to align the text relative to the rendering space. - /// - public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } - - /// - /// Performs an implicit conversion from to . - /// - /// The options. - /// - /// The result of the conversion. - /// - public static implicit operator TextGraphicsOptions(GraphicsOptions options) - { - return new TextGraphicsOptions(options.Antialias) - { - AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, - blendPercentage = options.BlendPercentage, - colorBlendingMode = options.ColorBlendingMode, - alphaCompositionMode = options.AlphaCompositionMode - }; - } - - /// - /// Performs an explicit conversion from to . - /// - /// The options. - /// - /// The result of the conversion. - /// - public static explicit operator GraphicsOptions(TextGraphicsOptions options) - { - return new GraphicsOptions(options.Antialias) - { - AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.Fonts; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing +{ + /// + /// Options for influencing the drawing functions. + /// + public struct TextGraphicsOptions + { + private const int DefaultTextDpi = 72; + + /// + /// Represents the default . + /// + public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true); + + private float? blendPercentage; + + private int? antialiasSubpixelDepth; + + private bool? antialias; + + private bool? applyKerning; + + private float? tabWidth; + + private float? dpiX; + + private float? dpiY; + + private HorizontalAlignment? horizontalAlignment; + + private VerticalAlignment? verticalAlignment; + + /// + /// Initializes a new instance of the struct. + /// + /// If set to true [enable antialiasing]. + public TextGraphicsOptions(bool enableAntialiasing) + { + this.applyKerning = true; + this.tabWidth = 4; + this.WrapTextWidth = 0; + this.horizontalAlignment = HorizontalAlignment.Left; + this.verticalAlignment = VerticalAlignment.Top; + + this.antialiasSubpixelDepth = 16; + this.ColorBlendingMode = PixelColorBlendingMode.Normal; + this.AlphaCompositionMode = PixelAlphaCompositionMode.SrcOver; + this.blendPercentage = 1; + this.antialias = enableAntialiasing; + this.dpiX = DefaultTextDpi; + this.dpiY = DefaultTextDpi; + } + + /// + /// Gets or sets a value indicating whether antialiasing should be applied. + /// + public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; } + + /// + /// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled. + /// + public int AntialiasSubpixelDepth { get => this.antialiasSubpixelDepth ?? 16; set => this.antialiasSubpixelDepth = value; } + + /// + /// Gets or sets a value indicating the blending percentage to apply to the drawing operation + /// + public float BlendPercentage { get => (this.blendPercentage ?? 1).Clamp(0, 1); set => this.blendPercentage = value; } + + // In the future we could expose a PixelBlender directly on here + // or some forms of PixelBlender factory for each pixel type. Will need + // some API thought post V1. + + /// + /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation + /// + public PixelColorBlendingMode ColorBlendingMode { get; set; } + + /// + /// Gets or sets a value indicating the color blending percentage to apply to the drawing operation + /// + public PixelAlphaCompositionMode AlphaCompositionMode { get; set; } + + /// + /// Gets or sets a value indicating whether the text should be drawing with kerning enabled. + /// + public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; } + + /// + /// Gets or sets a value indicating the number of space widths a tab should lock to. + /// + public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; } + + /// + /// Gets or sets a value indicating if greater than zero determine the width at which text should wrap. + /// + public float WrapTextWidth { get; set; } + + /// + /// Gets or sets a value indicating the DPI to render text along the X axis. + /// + public float DpiX { get => this.dpiX ?? DefaultTextDpi; set => this.dpiX = value; } + + /// + /// Gets or sets a value indicating the DPI to render text along the Y axis. + /// + public float DpiY { get => this.dpiY ?? DefaultTextDpi; set => this.dpiY = value; } + + /// + /// Gets or sets a value indicating how to align the text relative to the rendering space. + /// If is greater than zero it will align relative to the space + /// defined by the location and width, if equals zero, and thus + /// wrapping disabled, then the alignment is relative to the drawing location. + /// + public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } + + /// + /// Gets or sets a value indicating how to align the text relative to the rendering space. + /// + public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } + + /// + /// Performs an implicit conversion from to . + /// + /// The options. + /// + /// The result of the conversion. + /// + public static implicit operator TextGraphicsOptions(GraphicsOptions options) + { + return new TextGraphicsOptions(options.Antialias) + { + AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, + blendPercentage = options.BlendPercentage, + ColorBlendingMode = options.ColorBlendingMode, + AlphaCompositionMode = options.AlphaCompositionMode + }; + } + + /// + /// Performs an explicit conversion from to . + /// + /// The options. + /// + /// The result of the conversion. + /// + public static explicit operator GraphicsOptions(TextGraphicsOptions options) + { + return new GraphicsOptions(options.Antialias) + { + AntialiasSubpixelDepth = options.AntialiasSubpixelDepth, ColorBlendingMode = options.ColorBlendingMode, - AlphaCompositionMode = options.AlphaCompositionMode, - BlendPercentage = options.BlendPercentage - }; - } - } + AlphaCompositionMode = options.AlphaCompositionMode, + BlendPercentage = options.BlendPercentage + }; + } + } } \ No newline at end of file diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index db0328106..3f3d6a62f 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp EncodeVisitor visitor = new EncodeVisitor(encoder, stream); this.AcceptVisitor(visitor); } - + /// /// Returns a copy of the image in the given pixel format. /// diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 4abe2f57a..1b213c26d 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -41,7 +41,7 @@ - + From d2ea0056c4fe9d28b983ed0c0de4086106d9b665 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Mon, 13 May 2019 23:59:50 +0200 Subject: [PATCH 190/223] fix remaining stylecop issues --- .../Processing/DrawingHelpers.cs | 7 ++- .../Extensions/DrawPathExtensions.cs | 58 +++++++++++-------- .../Extensions/FillPathExtensions.cs | 33 +++++------ .../Extensions/FillRegionExtensions.cs | 54 ++++++++--------- .../Processing/GradientBrushBase.cs | 2 +- .../Processing/GradientRepetitionMode.cs | 6 +- src/ImageSharp.Drawing/Processing/IBrush.cs | 4 +- src/ImageSharp.Drawing/Processing/IPen.cs | 5 +- .../Processing/ImageBrush.cs | 2 +- .../Processing/LinearGradientBrush.cs | 18 ++++-- 10 files changed, 102 insertions(+), 87 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs b/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs index 314b65f7e..b4ce0c5cb 100644 --- a/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs +++ b/src/ImageSharp.Drawing/Processing/DrawingHelpers.cs @@ -1,5 +1,5 @@ -// // Copyright (c) Six Labors and contributors. -// // Licensed under the Apache License, Version 2.0. +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; @@ -8,6 +8,9 @@ namespace SixLabors.ImageSharp.Processing { internal static class DrawingHelpers { + /// + /// Convert a to a of the given pixel type. + /// public static DenseMatrix ToPixelMatrix(this DenseMatrix colorMatrix, Configuration configuration) where TPixel : struct, IPixel { diff --git a/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs index f231f1baa..efafdde5a 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/DrawPathExtensions.cs @@ -15,80 +15,90 @@ namespace SixLabors.ImageSharp.Processing /// /// Draws the outline of the polygon with the provided pen. /// - /// The image this method extends. /// The options. /// The pen. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IPen pen, IPath path) - - => source.Fill(options, pen.StrokeFill, new ShapePath(path, pen)); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IPen pen, + IPath path) => + source.Fill(options, pen.StrokeFill, new ShapePath(path, pen)); /// /// Draws the outline of the polygon with the provided pen. /// - /// The image this method extends. /// The pen. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPath path) - - => source.Draw(GraphicsOptions.Default, pen, path); + public static IImageProcessingContext Draw(this IImageProcessingContext source, IPen pen, IPath path) => + source.Draw(GraphicsOptions.Default, pen, path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The image this method extends. /// The options. /// The brush. /// The thickness. /// The shape. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, float thickness, IPath path) - - => source.Draw(options, new Pen(brush, thickness), path); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + float thickness, + IPath path) => + source.Draw(options, new Pen(brush, thickness), path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The image this method extends. /// The brush. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, IBrush brush, float thickness, IPath path) - - => source.Draw(new Pen(brush, thickness), path); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + IBrush brush, + float thickness, + IPath path) => + source.Draw(new Pen(brush, thickness), path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The image this method extends. /// The options. /// The color. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, GraphicsOptions options, Color color, float thickness, IPath path) - - => source.Draw(options, new SolidBrush(color), thickness, path); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + float thickness, + IPath path) => + source.Draw(options, new SolidBrush(color), thickness, path); /// /// Draws the outline of the polygon with the provided brush at the provided thickness. /// - /// The image this method extends. /// The color. /// The thickness. /// The path. /// The . - public static IImageProcessingContext Draw(this IImageProcessingContext source, Color color, float thickness, IPath path) - - => source.Draw(new SolidBrush(color), thickness, path); + public static IImageProcessingContext Draw( + this IImageProcessingContext source, + Color color, + float thickness, + IPath path) => + source.Draw(new SolidBrush(color), thickness, path); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs index 7cf67612a..718016a9e 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/FillPathExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; using SixLabors.Shapes; @@ -15,51 +14,51 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The image this method extends. /// The graphics options. /// The brush. /// The shape. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, IPath path) - - => source.Fill(options, brush, new ShapeRegion(path)); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + IPath path) => + source.Fill(options, brush, new ShapeRegion(path)); /// /// Flood fills the image in the shape of the provided polygon with the specified brush. /// - /// The image this method extends. /// The brush. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPath path) - - => source.Fill(GraphicsOptions.Default, brush, new ShapeRegion(path)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, IPath path) => + source.Fill(GraphicsOptions.Default, brush, new ShapeRegion(path)); /// /// Flood fills the image in the shape of the provided polygon with the specified brush.. /// - /// The image this method extends. /// The options. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, Color color, IPath path) - - => source.Fill(options, new SolidBrush(color), path); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + IPath path) => + source.Fill(options, new SolidBrush(color), path); /// /// Flood fills the image in the shape of the provided polygon with the specified brush.. /// - /// The image this method extends. /// The color. /// The path. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, IPath path) - - => source.Fill(new SolidBrush(color), path); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, IPath path) => + source.Fill(new SolidBrush(color), path); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs b/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs index 457ad98b0..294e57514 100644 --- a/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs +++ b/src/ImageSharp.Drawing/Processing/Extensions/FillRegionExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; using SixLabors.ImageSharp.Processing.Processors.Drawing; @@ -15,85 +14,82 @@ namespace SixLabors.ImageSharp.Processing /// /// Flood fills the image with the specified brush. /// - /// The image this method extends. /// The details how to fill the region of interest. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) - - => source.Fill(GraphicsOptions.Default, brush); + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush) => + source.Fill(GraphicsOptions.Default, brush); /// /// Flood fills the image with the specified color. /// - /// The image this method extends. /// The color. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color) - - => source.Fill(new SolidBrush(color)); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color) => + source.Fill(new SolidBrush(color)); /// /// Flood fills the image with in the region with the specified brush. /// - /// The image this method extends. /// The brush. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Region region) - - => source.Fill(GraphicsOptions.Default, brush, region); + public static IImageProcessingContext Fill(this IImageProcessingContext source, IBrush brush, Region region) => + source.Fill(GraphicsOptions.Default, brush, region); /// /// Flood fills the image with in the region with the specified color. /// - /// The image this method extends. /// The options. /// The color. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, Color color, Region region) - - => source.Fill(options, new SolidBrush(color), region); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + Color color, + Region region) => + source.Fill(options, new SolidBrush(color), region); /// /// Flood fills the image with in the region with the specified color. /// - /// The image this method extends. /// The color. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, Region region) - - => source.Fill(new SolidBrush(color), region); + public static IImageProcessingContext Fill(this IImageProcessingContext source, Color color, Region region) => + source.Fill(new SolidBrush(color), region); /// /// Flood fills the image with in the region with the specified brush. /// - /// The image this method extends. /// The graphics options. /// The brush. /// The region. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush, Region region) - - => source.ApplyProcessor(new FillRegionProcessor(brush, region, options)); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush, + Region region) => + source.ApplyProcessor(new FillRegionProcessor(brush, region, options)); /// /// Flood fills the image with the specified brush. /// - /// The image this method extends. /// The graphics options. /// The details how to fill the region of interest. /// The . - public static IImageProcessingContext Fill(this IImageProcessingContext source, GraphicsOptions options, IBrush brush) - - => source.ApplyProcessor(new FillProcessor(brush, options)); + public static IImageProcessingContext Fill( + this IImageProcessingContext source, + GraphicsOptions options, + IBrush brush) => + source.ApplyProcessor(new FillProcessor(brush, options)); } } \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs index a877ea96c..6e1e0086d 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Base class for gradient brush applicators /// - protected abstract class GradientBrushApplicatorBase : BrushApplicator + internal abstract class GradientBrushApplicatorBase : BrushApplicator where TPixel : struct, IPixel { private readonly ColorStop[] colorStops; diff --git a/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs b/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs index c156153be..6aed8a030 100644 --- a/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs +++ b/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs @@ -21,16 +21,16 @@ namespace SixLabors.ImageSharp.Processing /// /// Reflect the gradient. - /// Similar to , but each other repetition uses inverse order of s. + /// Similar to , but each other repetition uses inverse order of s. /// Used on a Black-White gradient, Reflect leads to Black->{gray}->White->{gray}->White... /// Reflect, /// /// With DontFill a gradient does not touch any pixel beyond it's borders. - /// For the this is beyond the orthogonal through start and end, + /// For the this is beyond the orthogonal through start and end, /// TODO For the cref="PolygonalGradientBrush" it's outside the polygon, - /// For and it's beyond 1.0. + /// For and it's beyond 1.0. /// DontFill } diff --git a/src/ImageSharp.Drawing/Processing/IBrush.cs b/src/ImageSharp.Drawing/Processing/IBrush.cs index aa8c25b95..0cd2e20fd 100644 --- a/src/ImageSharp.Drawing/Processing/IBrush.cs +++ b/src/ImageSharp.Drawing/Processing/IBrush.cs @@ -9,16 +9,16 @@ namespace SixLabors.ImageSharp.Processing /// /// Brush represents a logical configuration of a brush which can be used to source pixel colors /// - /// The pixel format. /// /// A brush is a simple class that will return an that will perform the - /// logic for converting a pixel location to a . + /// logic for retrieving pixel values for specific locations. /// public interface IBrush { /// /// Creates the applicator for this brush. /// + /// The pixel type. /// The source image. /// The region the brush will be applied to. /// The graphic options diff --git a/src/ImageSharp.Drawing/Processing/IPen.cs b/src/ImageSharp.Drawing/Processing/IPen.cs index b9e359d60..af7517905 100644 --- a/src/ImageSharp.Drawing/Processing/IPen.cs +++ b/src/ImageSharp.Drawing/Processing/IPen.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; + using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing @@ -15,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing /// Gets the stroke fill. /// IBrush StrokeFill { get; } - + /// /// Gets the width to apply to the stroke /// @@ -26,4 +27,4 @@ namespace SixLabors.ImageSharp.Processing /// ReadOnlySpan StrokePattern { get; } } -} +} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/ImageBrush.cs b/src/ImageSharp.Drawing/Processing/ImageBrush.cs index c2a8d3a26..33f7b831a 100644 --- a/src/ImageSharp.Drawing/Processing/ImageBrush.cs +++ b/src/ImageSharp.Drawing/Processing/ImageBrush.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing } specificImage = this.image.CloneAs(); - + return new ImageBrushApplicator(source, specificImage, region, options, true); } diff --git a/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs index fac43ad63..6eeadee5d 100644 --- a/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs @@ -14,7 +14,6 @@ namespace SixLabors.ImageSharp.Processing /// - a set of colors in relative distances to each other. /// public sealed class LinearGradientBrush : GradientBrushBase - { private readonly PointF p1; @@ -39,8 +38,17 @@ namespace SixLabors.ImageSharp.Processing } /// - public override BrushApplicator CreateApplicator(ImageFrame source, RectangleF region, GraphicsOptions options) - => new LinearGradientBrushApplicator(source, this.p1, this.p2, this.ColorStops, this.RepetitionMode, options); + public override BrushApplicator CreateApplicator( + ImageFrame source, + RectangleF region, + GraphicsOptions options) => + new LinearGradientBrushApplicator( + source, + this.p1, + this.p2, + this.ColorStops, + this.RepetitionMode, + options); /// /// The linear gradient brush applicator. @@ -137,9 +145,7 @@ namespace SixLabors.ImageSharp.Processing float y4 = y + (k * this.alongX); // get distance from (x4,y4) to start - float distance = (float)Math.Sqrt( - Math.Pow(x4 - this.start.X, 2) - + Math.Pow(y4 - this.start.Y, 2)); + float distance = (float)Math.Sqrt(Math.Pow(x4 - this.start.X, 2) + Math.Pow(y4 - this.start.Y, 2)); // get and return ratio float ratio = distance / this.length; From c2e955c064567ab909da6a95d9c20b2031d7c6e9 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 14 May 2019 00:01:50 +0200 Subject: [PATCH 191/223] Rgba32.Definitions: use Color instead of NamedColors --- .../Rgba32.Definitions.cs | 284 +++++++++--------- 1 file changed, 142 insertions(+), 142 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.Definitions.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.Definitions.cs index 032d0b546..f9cc3256c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.Definitions.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.Definitions.cs @@ -11,711 +11,711 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Represents a matching the W3C definition that has an hex value of #F0F8FF. /// - public static readonly Rgba32 AliceBlue = NamedColors.AliceBlue; + public static readonly Rgba32 AliceBlue = Color.AliceBlue; /// /// Represents a matching the W3C definition that has an hex value of #FAEBD7. /// - public static readonly Rgba32 AntiqueWhite = NamedColors.AntiqueWhite; + public static readonly Rgba32 AntiqueWhite = Color.AntiqueWhite; /// /// Represents a matching the W3C definition that has an hex value of #00FFFF. /// - public static readonly Rgba32 Aqua = NamedColors.Aqua; + public static readonly Rgba32 Aqua = Color.Aqua; /// /// Represents a matching the W3C definition that has an hex value of #7FFFD4. /// - public static readonly Rgba32 Aquamarine = NamedColors.Aquamarine; + public static readonly Rgba32 Aquamarine = Color.Aquamarine; /// /// Represents a matching the W3C definition that has an hex value of #F0FFFF. /// - public static readonly Rgba32 Azure = NamedColors.Azure; + public static readonly Rgba32 Azure = Color.Azure; /// /// Represents a matching the W3C definition that has an hex value of #F5F5DC. /// - public static readonly Rgba32 Beige = NamedColors.Beige; + public static readonly Rgba32 Beige = Color.Beige; /// /// Represents a matching the W3C definition that has an hex value of #FFE4C4. /// - public static readonly Rgba32 Bisque = NamedColors.Bisque; + public static readonly Rgba32 Bisque = Color.Bisque; /// /// Represents a matching the W3C definition that has an hex value of #000000. /// - public static readonly Rgba32 Black = NamedColors.Black; + public static readonly Rgba32 Black = Color.Black; /// /// Represents a matching the W3C definition that has an hex value of #FFEBCD. /// - public static readonly Rgba32 BlanchedAlmond = NamedColors.BlanchedAlmond; + public static readonly Rgba32 BlanchedAlmond = Color.BlanchedAlmond; /// /// Represents a matching the W3C definition that has an hex value of #0000FF. /// - public static readonly Rgba32 Blue = NamedColors.Blue; + public static readonly Rgba32 Blue = Color.Blue; /// /// Represents a matching the W3C definition that has an hex value of #8A2BE2. /// - public static readonly Rgba32 BlueViolet = NamedColors.BlueViolet; + public static readonly Rgba32 BlueViolet = Color.BlueViolet; /// /// Represents a matching the W3C definition that has an hex value of #A52A2A. /// - public static readonly Rgba32 Brown = NamedColors.Brown; + public static readonly Rgba32 Brown = Color.Brown; /// /// Represents a matching the W3C definition that has an hex value of #DEB887. /// - public static readonly Rgba32 BurlyWood = NamedColors.BurlyWood; + public static readonly Rgba32 BurlyWood = Color.BurlyWood; /// /// Represents a matching the W3C definition that has an hex value of #5F9EA0. /// - public static readonly Rgba32 CadetBlue = NamedColors.CadetBlue; + public static readonly Rgba32 CadetBlue = Color.CadetBlue; /// /// Represents a matching the W3C definition that has an hex value of #7FFF00. /// - public static readonly Rgba32 Chartreuse = NamedColors.Chartreuse; + public static readonly Rgba32 Chartreuse = Color.Chartreuse; /// /// Represents a matching the W3C definition that has an hex value of #D2691E. /// - public static readonly Rgba32 Chocolate = NamedColors.Chocolate; + public static readonly Rgba32 Chocolate = Color.Chocolate; /// /// Represents a matching the W3C definition that has an hex value of #FF7F50. /// - public static readonly Rgba32 Coral = NamedColors.Coral; + public static readonly Rgba32 Coral = Color.Coral; /// /// Represents a matching the W3C definition that has an hex value of #6495ED. /// - public static readonly Rgba32 CornflowerBlue = NamedColors.CornflowerBlue; + public static readonly Rgba32 CornflowerBlue = Color.CornflowerBlue; /// /// Represents a matching the W3C definition that has an hex value of #FFF8DC. /// - public static readonly Rgba32 Cornsilk = NamedColors.Cornsilk; + public static readonly Rgba32 Cornsilk = Color.Cornsilk; /// /// Represents a matching the W3C definition that has an hex value of #DC143C. /// - public static readonly Rgba32 Crimson = NamedColors.Crimson; + public static readonly Rgba32 Crimson = Color.Crimson; /// /// Represents a matching the W3C definition that has an hex value of #00FFFF. /// - public static readonly Rgba32 Cyan = NamedColors.Cyan; + public static readonly Rgba32 Cyan = Color.Cyan; /// /// Represents a matching the W3C definition that has an hex value of #00008B. /// - public static readonly Rgba32 DarkBlue = NamedColors.DarkBlue; + public static readonly Rgba32 DarkBlue = Color.DarkBlue; /// /// Represents a matching the W3C definition that has an hex value of #008B8B. /// - public static readonly Rgba32 DarkCyan = NamedColors.DarkCyan; + public static readonly Rgba32 DarkCyan = Color.DarkCyan; /// /// Represents a matching the W3C definition that has an hex value of #B8860B. /// - public static readonly Rgba32 DarkGoldenrod = NamedColors.DarkGoldenrod; + public static readonly Rgba32 DarkGoldenrod = Color.DarkGoldenrod; /// /// Represents a matching the W3C definition that has an hex value of #A9A9A9. /// - public static readonly Rgba32 DarkGray = NamedColors.DarkGray; + public static readonly Rgba32 DarkGray = Color.DarkGray; /// /// Represents a matching the W3C definition that has an hex value of #006400. /// - public static readonly Rgba32 DarkGreen = NamedColors.DarkGreen; + public static readonly Rgba32 DarkGreen = Color.DarkGreen; /// /// Represents a matching the W3C definition that has an hex value of #BDB76B. /// - public static readonly Rgba32 DarkKhaki = NamedColors.DarkKhaki; + public static readonly Rgba32 DarkKhaki = Color.DarkKhaki; /// /// Represents a matching the W3C definition that has an hex value of #8B008B. /// - public static readonly Rgba32 DarkMagenta = NamedColors.DarkMagenta; + public static readonly Rgba32 DarkMagenta = Color.DarkMagenta; /// /// Represents a matching the W3C definition that has an hex value of #556B2F. /// - public static readonly Rgba32 DarkOliveGreen = NamedColors.DarkOliveGreen; + public static readonly Rgba32 DarkOliveGreen = Color.DarkOliveGreen; /// /// Represents a matching the W3C definition that has an hex value of #FF8C00. /// - public static readonly Rgba32 DarkOrange = NamedColors.DarkOrange; + public static readonly Rgba32 DarkOrange = Color.DarkOrange; /// /// Represents a matching the W3C definition that has an hex value of #9932CC. /// - public static readonly Rgba32 DarkOrchid = NamedColors.DarkOrchid; + public static readonly Rgba32 DarkOrchid = Color.DarkOrchid; /// /// Represents a matching the W3C definition that has an hex value of #8B0000. /// - public static readonly Rgba32 DarkRed = NamedColors.DarkRed; + public static readonly Rgba32 DarkRed = Color.DarkRed; /// /// Represents a matching the W3C definition that has an hex value of #E9967A. /// - public static readonly Rgba32 DarkSalmon = NamedColors.DarkSalmon; + public static readonly Rgba32 DarkSalmon = Color.DarkSalmon; /// /// Represents a matching the W3C definition that has an hex value of #8FBC8B. /// - public static readonly Rgba32 DarkSeaGreen = NamedColors.DarkSeaGreen; + public static readonly Rgba32 DarkSeaGreen = Color.DarkSeaGreen; /// /// Represents a matching the W3C definition that has an hex value of #483D8B. /// - public static readonly Rgba32 DarkSlateBlue = NamedColors.DarkSlateBlue; + public static readonly Rgba32 DarkSlateBlue = Color.DarkSlateBlue; /// /// Represents a matching the W3C definition that has an hex value of #2F4F4F. /// - public static readonly Rgba32 DarkSlateGray = NamedColors.DarkSlateGray; + public static readonly Rgba32 DarkSlateGray = Color.DarkSlateGray; /// /// Represents a matching the W3C definition that has an hex value of #00CED1. /// - public static readonly Rgba32 DarkTurquoise = NamedColors.DarkTurquoise; + public static readonly Rgba32 DarkTurquoise = Color.DarkTurquoise; /// /// Represents a matching the W3C definition that has an hex value of #9400D3. /// - public static readonly Rgba32 DarkViolet = NamedColors.DarkViolet; + public static readonly Rgba32 DarkViolet = Color.DarkViolet; /// /// Represents a matching the W3C definition that has an hex value of #FF1493. /// - public static readonly Rgba32 DeepPink = NamedColors.DeepPink; + public static readonly Rgba32 DeepPink = Color.DeepPink; /// /// Represents a matching the W3C definition that has an hex value of #00BFFF. /// - public static readonly Rgba32 DeepSkyBlue = NamedColors.DeepSkyBlue; + public static readonly Rgba32 DeepSkyBlue = Color.DeepSkyBlue; /// /// Represents a matching the W3C definition that has an hex value of #696969. /// - public static readonly Rgba32 DimGray = NamedColors.DimGray; + public static readonly Rgba32 DimGray = Color.DimGray; /// /// Represents a matching the W3C definition that has an hex value of #1E90FF. /// - public static readonly Rgba32 DodgerBlue = NamedColors.DodgerBlue; + public static readonly Rgba32 DodgerBlue = Color.DodgerBlue; /// /// Represents a matching the W3C definition that has an hex value of #B22222. /// - public static readonly Rgba32 Firebrick = NamedColors.Firebrick; + public static readonly Rgba32 Firebrick = Color.Firebrick; /// /// Represents a matching the W3C definition that has an hex value of #FFFAF0. /// - public static readonly Rgba32 FloralWhite = NamedColors.FloralWhite; + public static readonly Rgba32 FloralWhite = Color.FloralWhite; /// /// Represents a matching the W3C definition that has an hex value of #228B22. /// - public static readonly Rgba32 ForestGreen = NamedColors.ForestGreen; + public static readonly Rgba32 ForestGreen = Color.ForestGreen; /// /// Represents a matching the W3C definition that has an hex value of #FF00FF. /// - public static readonly Rgba32 Fuchsia = NamedColors.Fuchsia; + public static readonly Rgba32 Fuchsia = Color.Fuchsia; /// /// Represents a matching the W3C definition that has an hex value of #DCDCDC. /// - public static readonly Rgba32 Gainsboro = NamedColors.Gainsboro; + public static readonly Rgba32 Gainsboro = Color.Gainsboro; /// /// Represents a matching the W3C definition that has an hex value of #F8F8FF. /// - public static readonly Rgba32 GhostWhite = NamedColors.GhostWhite; + public static readonly Rgba32 GhostWhite = Color.GhostWhite; /// /// Represents a matching the W3C definition that has an hex value of #FFD700. /// - public static readonly Rgba32 Gold = NamedColors.Gold; + public static readonly Rgba32 Gold = Color.Gold; /// /// Represents a matching the W3C definition that has an hex value of #DAA520. /// - public static readonly Rgba32 Goldenrod = NamedColors.Goldenrod; + public static readonly Rgba32 Goldenrod = Color.Goldenrod; /// /// Represents a matching the W3C definition that has an hex value of #808080. /// - public static readonly Rgba32 Gray = NamedColors.Gray; + public static readonly Rgba32 Gray = Color.Gray; /// /// Represents a matching the W3C definition that has an hex value of #008000. /// - public static readonly Rgba32 Green = NamedColors.Green; + public static readonly Rgba32 Green = Color.Green; /// /// Represents a matching the W3C definition that has an hex value of #ADFF2F. /// - public static readonly Rgba32 GreenYellow = NamedColors.GreenYellow; + public static readonly Rgba32 GreenYellow = Color.GreenYellow; /// /// Represents a matching the W3C definition that has an hex value of #F0FFF0. /// - public static readonly Rgba32 Honeydew = NamedColors.Honeydew; + public static readonly Rgba32 Honeydew = Color.Honeydew; /// /// Represents a matching the W3C definition that has an hex value of #FF69B4. /// - public static readonly Rgba32 HotPink = NamedColors.HotPink; + public static readonly Rgba32 HotPink = Color.HotPink; /// /// Represents a matching the W3C definition that has an hex value of #CD5C5C. /// - public static readonly Rgba32 IndianRed = NamedColors.IndianRed; + public static readonly Rgba32 IndianRed = Color.IndianRed; /// /// Represents a matching the W3C definition that has an hex value of #4B0082. /// - public static readonly Rgba32 Indigo = NamedColors.Indigo; + public static readonly Rgba32 Indigo = Color.Indigo; /// /// Represents a matching the W3C definition that has an hex value of #FFFFF0. /// - public static readonly Rgba32 Ivory = NamedColors.Ivory; + public static readonly Rgba32 Ivory = Color.Ivory; /// /// Represents a matching the W3C definition that has an hex value of #F0E68C. /// - public static readonly Rgba32 Khaki = NamedColors.Khaki; + public static readonly Rgba32 Khaki = Color.Khaki; /// /// Represents a matching the W3C definition that has an hex value of #E6E6FA. /// - public static readonly Rgba32 Lavender = NamedColors.Lavender; + public static readonly Rgba32 Lavender = Color.Lavender; /// /// Represents a matching the W3C definition that has an hex value of #FFF0F5. /// - public static readonly Rgba32 LavenderBlush = NamedColors.LavenderBlush; + public static readonly Rgba32 LavenderBlush = Color.LavenderBlush; /// /// Represents a matching the W3C definition that has an hex value of #7CFC00. /// - public static readonly Rgba32 LawnGreen = NamedColors.LawnGreen; + public static readonly Rgba32 LawnGreen = Color.LawnGreen; /// /// Represents a matching the W3C definition that has an hex value of #FFFACD. /// - public static readonly Rgba32 LemonChiffon = NamedColors.LemonChiffon; + public static readonly Rgba32 LemonChiffon = Color.LemonChiffon; /// /// Represents a matching the W3C definition that has an hex value of #ADD8E6. /// - public static readonly Rgba32 LightBlue = NamedColors.LightBlue; + public static readonly Rgba32 LightBlue = Color.LightBlue; /// /// Represents a matching the W3C definition that has an hex value of #F08080. /// - public static readonly Rgba32 LightCoral = NamedColors.LightCoral; + public static readonly Rgba32 LightCoral = Color.LightCoral; /// /// Represents a matching the W3C definition that has an hex value of #E0FFFF. /// - public static readonly Rgba32 LightCyan = NamedColors.LightCyan; + public static readonly Rgba32 LightCyan = Color.LightCyan; /// /// Represents a matching the W3C definition that has an hex value of #FAFAD2. /// - public static readonly Rgba32 LightGoldenrodYellow = NamedColors.LightGoldenrodYellow; + public static readonly Rgba32 LightGoldenrodYellow = Color.LightGoldenrodYellow; /// /// Represents a matching the W3C definition that has an hex value of #D3D3D3. /// - public static readonly Rgba32 LightGray = NamedColors.LightGray; + public static readonly Rgba32 LightGray = Color.LightGray; /// /// Represents a matching the W3C definition that has an hex value of #90EE90. /// - public static readonly Rgba32 LightGreen = NamedColors.LightGreen; + public static readonly Rgba32 LightGreen = Color.LightGreen; /// /// Represents a matching the W3C definition that has an hex value of #FFB6C1. /// - public static readonly Rgba32 LightPink = NamedColors.LightPink; + public static readonly Rgba32 LightPink = Color.LightPink; /// /// Represents a matching the W3C definition that has an hex value of #FFA07A. /// - public static readonly Rgba32 LightSalmon = NamedColors.LightSalmon; + public static readonly Rgba32 LightSalmon = Color.LightSalmon; /// /// Represents a matching the W3C definition that has an hex value of #20B2AA. /// - public static readonly Rgba32 LightSeaGreen = NamedColors.LightSeaGreen; + public static readonly Rgba32 LightSeaGreen = Color.LightSeaGreen; /// /// Represents a matching the W3C definition that has an hex value of #87CEFA. /// - public static readonly Rgba32 LightSkyBlue = NamedColors.LightSkyBlue; + public static readonly Rgba32 LightSkyBlue = Color.LightSkyBlue; /// /// Represents a matching the W3C definition that has an hex value of #778899. /// - public static readonly Rgba32 LightSlateGray = NamedColors.LightSlateGray; + public static readonly Rgba32 LightSlateGray = Color.LightSlateGray; /// /// Represents a matching the W3C definition that has an hex value of #B0C4DE. /// - public static readonly Rgba32 LightSteelBlue = NamedColors.LightSteelBlue; + public static readonly Rgba32 LightSteelBlue = Color.LightSteelBlue; /// /// Represents a matching the W3C definition that has an hex value of #FFFFE0. /// - public static readonly Rgba32 LightYellow = NamedColors.LightYellow; + public static readonly Rgba32 LightYellow = Color.LightYellow; /// /// Represents a matching the W3C definition that has an hex value of #00FF00. /// - public static readonly Rgba32 Lime = NamedColors.Lime; + public static readonly Rgba32 Lime = Color.Lime; /// /// Represents a matching the W3C definition that has an hex value of #32CD32. /// - public static readonly Rgba32 LimeGreen = NamedColors.LimeGreen; + public static readonly Rgba32 LimeGreen = Color.LimeGreen; /// /// Represents a matching the W3C definition that has an hex value of #FAF0E6. /// - public static readonly Rgba32 Linen = NamedColors.Linen; + public static readonly Rgba32 Linen = Color.Linen; /// /// Represents a matching the W3C definition that has an hex value of #FF00FF. /// - public static readonly Rgba32 Magenta = NamedColors.Magenta; + public static readonly Rgba32 Magenta = Color.Magenta; /// /// Represents a matching the W3C definition that has an hex value of #800000. /// - public static readonly Rgba32 Maroon = NamedColors.Maroon; + public static readonly Rgba32 Maroon = Color.Maroon; /// /// Represents a matching the W3C definition that has an hex value of #66CDAA. /// - public static readonly Rgba32 MediumAquamarine = NamedColors.MediumAquamarine; + public static readonly Rgba32 MediumAquamarine = Color.MediumAquamarine; /// /// Represents a matching the W3C definition that has an hex value of #0000CD. /// - public static readonly Rgba32 MediumBlue = NamedColors.MediumBlue; + public static readonly Rgba32 MediumBlue = Color.MediumBlue; /// /// Represents a matching the W3C definition that has an hex value of #BA55D3. /// - public static readonly Rgba32 MediumOrchid = NamedColors.MediumOrchid; + public static readonly Rgba32 MediumOrchid = Color.MediumOrchid; /// /// Represents a matching the W3C definition that has an hex value of #9370DB. /// - public static readonly Rgba32 MediumPurple = NamedColors.MediumPurple; + public static readonly Rgba32 MediumPurple = Color.MediumPurple; /// /// Represents a matching the W3C definition that has an hex value of #3CB371. /// - public static readonly Rgba32 MediumSeaGreen = NamedColors.MediumSeaGreen; + public static readonly Rgba32 MediumSeaGreen = Color.MediumSeaGreen; /// /// Represents a matching the W3C definition that has an hex value of #7B68EE. /// - public static readonly Rgba32 MediumSlateBlue = NamedColors.MediumSlateBlue; + public static readonly Rgba32 MediumSlateBlue = Color.MediumSlateBlue; /// /// Represents a matching the W3C definition that has an hex value of #00FA9A. /// - public static readonly Rgba32 MediumSpringGreen = NamedColors.MediumSpringGreen; + public static readonly Rgba32 MediumSpringGreen = Color.MediumSpringGreen; /// /// Represents a matching the W3C definition that has an hex value of #48D1CC. /// - public static readonly Rgba32 MediumTurquoise = NamedColors.MediumTurquoise; + public static readonly Rgba32 MediumTurquoise = Color.MediumTurquoise; /// /// Represents a matching the W3C definition that has an hex value of #C71585. /// - public static readonly Rgba32 MediumVioletRed = NamedColors.MediumVioletRed; + public static readonly Rgba32 MediumVioletRed = Color.MediumVioletRed; /// /// Represents a matching the W3C definition that has an hex value of #191970. /// - public static readonly Rgba32 MidnightBlue = NamedColors.MidnightBlue; + public static readonly Rgba32 MidnightBlue = Color.MidnightBlue; /// /// Represents a matching the W3C definition that has an hex value of #F5FFFA. /// - public static readonly Rgba32 MintCream = NamedColors.MintCream; + public static readonly Rgba32 MintCream = Color.MintCream; /// /// Represents a matching the W3C definition that has an hex value of #FFE4E1. /// - public static readonly Rgba32 MistyRose = NamedColors.MistyRose; + public static readonly Rgba32 MistyRose = Color.MistyRose; /// /// Represents a matching the W3C definition that has an hex value of #FFE4B5. /// - public static readonly Rgba32 Moccasin = NamedColors.Moccasin; + public static readonly Rgba32 Moccasin = Color.Moccasin; /// /// Represents a matching the W3C definition that has an hex value of #FFDEAD. /// - public static readonly Rgba32 NavajoWhite = NamedColors.NavajoWhite; + public static readonly Rgba32 NavajoWhite = Color.NavajoWhite; /// /// Represents a matching the W3C definition that has an hex value of #000080. /// - public static readonly Rgba32 Navy = NamedColors.Navy; + public static readonly Rgba32 Navy = Color.Navy; /// /// Represents a matching the W3C definition that has an hex value of #FDF5E6. /// - public static readonly Rgba32 OldLace = NamedColors.OldLace; + public static readonly Rgba32 OldLace = Color.OldLace; /// /// Represents a matching the W3C definition that has an hex value of #808000. /// - public static readonly Rgba32 Olive = NamedColors.Olive; + public static readonly Rgba32 Olive = Color.Olive; /// /// Represents a matching the W3C definition that has an hex value of #6B8E23. /// - public static readonly Rgba32 OliveDrab = NamedColors.OliveDrab; + public static readonly Rgba32 OliveDrab = Color.OliveDrab; /// /// Represents a matching the W3C definition that has an hex value of #FFA500. /// - public static readonly Rgba32 Orange = NamedColors.Orange; + public static readonly Rgba32 Orange = Color.Orange; /// /// Represents a matching the W3C definition that has an hex value of #FF4500. /// - public static readonly Rgba32 OrangeRed = NamedColors.OrangeRed; + public static readonly Rgba32 OrangeRed = Color.OrangeRed; /// /// Represents a matching the W3C definition that has an hex value of #DA70D6. /// - public static readonly Rgba32 Orchid = NamedColors.Orchid; + public static readonly Rgba32 Orchid = Color.Orchid; /// /// Represents a matching the W3C definition that has an hex value of #EEE8AA. /// - public static readonly Rgba32 PaleGoldenrod = NamedColors.PaleGoldenrod; + public static readonly Rgba32 PaleGoldenrod = Color.PaleGoldenrod; /// /// Represents a matching the W3C definition that has an hex value of #98FB98. /// - public static readonly Rgba32 PaleGreen = NamedColors.PaleGreen; + public static readonly Rgba32 PaleGreen = Color.PaleGreen; /// /// Represents a matching the W3C definition that has an hex value of #AFEEEE. /// - public static readonly Rgba32 PaleTurquoise = NamedColors.PaleTurquoise; + public static readonly Rgba32 PaleTurquoise = Color.PaleTurquoise; /// /// Represents a matching the W3C definition that has an hex value of #DB7093. /// - public static readonly Rgba32 PaleVioletRed = NamedColors.PaleVioletRed; + public static readonly Rgba32 PaleVioletRed = Color.PaleVioletRed; /// /// Represents a matching the W3C definition that has an hex value of #FFEFD5. /// - public static readonly Rgba32 PapayaWhip = NamedColors.PapayaWhip; + public static readonly Rgba32 PapayaWhip = Color.PapayaWhip; /// /// Represents a matching the W3C definition that has an hex value of #FFDAB9. /// - public static readonly Rgba32 PeachPuff = NamedColors.PeachPuff; + public static readonly Rgba32 PeachPuff = Color.PeachPuff; /// /// Represents a matching the W3C definition that has an hex value of #CD853F. /// - public static readonly Rgba32 Peru = NamedColors.Peru; + public static readonly Rgba32 Peru = Color.Peru; /// /// Represents a matching the W3C definition that has an hex value of #FFC0CB. /// - public static readonly Rgba32 Pink = NamedColors.Pink; + public static readonly Rgba32 Pink = Color.Pink; /// /// Represents a matching the W3C definition that has an hex value of #DDA0DD. /// - public static readonly Rgba32 Plum = NamedColors.Plum; + public static readonly Rgba32 Plum = Color.Plum; /// /// Represents a matching the W3C definition that has an hex value of #B0E0E6. /// - public static readonly Rgba32 PowderBlue = NamedColors.PowderBlue; + public static readonly Rgba32 PowderBlue = Color.PowderBlue; /// /// Represents a matching the W3C definition that has an hex value of #800080. /// - public static readonly Rgba32 Purple = NamedColors.Purple; + public static readonly Rgba32 Purple = Color.Purple; /// /// Represents a matching the W3C definition that has an hex value of #663399. /// - public static readonly Rgba32 RebeccaPurple = NamedColors.RebeccaPurple; + public static readonly Rgba32 RebeccaPurple = Color.RebeccaPurple; /// /// Represents a matching the W3C definition that has an hex value of #FF0000. /// - public static readonly Rgba32 Red = NamedColors.Red; + public static readonly Rgba32 Red = Color.Red; /// /// Represents a matching the W3C definition that has an hex value of #BC8F8F. /// - public static readonly Rgba32 RosyBrown = NamedColors.RosyBrown; + public static readonly Rgba32 RosyBrown = Color.RosyBrown; /// /// Represents a matching the W3C definition that has an hex value of #4169E1. /// - public static readonly Rgba32 RoyalBlue = NamedColors.RoyalBlue; + public static readonly Rgba32 RoyalBlue = Color.RoyalBlue; /// /// Represents a matching the W3C definition that has an hex value of #8B4513. /// - public static readonly Rgba32 SaddleBrown = NamedColors.SaddleBrown; + public static readonly Rgba32 SaddleBrown = Color.SaddleBrown; /// /// Represents a matching the W3C definition that has an hex value of #FA8072. /// - public static readonly Rgba32 Salmon = NamedColors.Salmon; + public static readonly Rgba32 Salmon = Color.Salmon; /// /// Represents a matching the W3C definition that has an hex value of #F4A460. /// - public static readonly Rgba32 SandyBrown = NamedColors.SandyBrown; + public static readonly Rgba32 SandyBrown = Color.SandyBrown; /// /// Represents a matching the W3C definition that has an hex value of #2E8B57. /// - public static readonly Rgba32 SeaGreen = NamedColors.SeaGreen; + public static readonly Rgba32 SeaGreen = Color.SeaGreen; /// /// Represents a matching the W3C definition that has an hex value of #FFF5EE. /// - public static readonly Rgba32 SeaShell = NamedColors.SeaShell; + public static readonly Rgba32 SeaShell = Color.SeaShell; /// /// Represents a matching the W3C definition that has an hex value of #A0522D. /// - public static readonly Rgba32 Sienna = NamedColors.Sienna; + public static readonly Rgba32 Sienna = Color.Sienna; /// /// Represents a matching the W3C definition that has an hex value of #C0C0C0. /// - public static readonly Rgba32 Silver = NamedColors.Silver; + public static readonly Rgba32 Silver = Color.Silver; /// /// Represents a matching the W3C definition that has an hex value of #87CEEB. /// - public static readonly Rgba32 SkyBlue = NamedColors.SkyBlue; + public static readonly Rgba32 SkyBlue = Color.SkyBlue; /// /// Represents a matching the W3C definition that has an hex value of #6A5ACD. /// - public static readonly Rgba32 SlateBlue = NamedColors.SlateBlue; + public static readonly Rgba32 SlateBlue = Color.SlateBlue; /// /// Represents a matching the W3C definition that has an hex value of #708090. /// - public static readonly Rgba32 SlateGray = NamedColors.SlateGray; + public static readonly Rgba32 SlateGray = Color.SlateGray; /// /// Represents a matching the W3C definition that has an hex value of #FFFAFA. /// - public static readonly Rgba32 Snow = NamedColors.Snow; + public static readonly Rgba32 Snow = Color.Snow; /// /// Represents a matching the W3C definition that has an hex value of #00FF7F. /// - public static readonly Rgba32 SpringGreen = NamedColors.SpringGreen; + public static readonly Rgba32 SpringGreen = Color.SpringGreen; /// /// Represents a matching the W3C definition that has an hex value of #4682B4. /// - public static readonly Rgba32 SteelBlue = NamedColors.SteelBlue; + public static readonly Rgba32 SteelBlue = Color.SteelBlue; /// /// Represents a matching the W3C definition that has an hex value of #D2B48C. /// - public static readonly Rgba32 Tan = NamedColors.Tan; + public static readonly Rgba32 Tan = Color.Tan; /// /// Represents a matching the W3C definition that has an hex value of #008080. /// - public static readonly Rgba32 Teal = NamedColors.Teal; + public static readonly Rgba32 Teal = Color.Teal; /// /// Represents a matching the W3C definition that has an hex value of #D8BFD8. /// - public static readonly Rgba32 Thistle = NamedColors.Thistle; + public static readonly Rgba32 Thistle = Color.Thistle; /// /// Represents a matching the W3C definition that has an hex value of #FF6347. /// - public static readonly Rgba32 Tomato = NamedColors.Tomato; + public static readonly Rgba32 Tomato = Color.Tomato; /// /// Represents a matching the W3C definition that has an hex value of #FFFFFF. /// - public static readonly Rgba32 Transparent = NamedColors.Transparent; + public static readonly Rgba32 Transparent = Color.Transparent; /// /// Represents a matching the W3C definition that has an hex value of #40E0D0. /// - public static readonly Rgba32 Turquoise = NamedColors.Turquoise; + public static readonly Rgba32 Turquoise = Color.Turquoise; /// /// Represents a matching the W3C definition that has an hex value of #EE82EE. /// - public static readonly Rgba32 Violet = NamedColors.Violet; + public static readonly Rgba32 Violet = Color.Violet; /// /// Represents a matching the W3C definition that has an hex value of #F5DEB3. /// - public static readonly Rgba32 Wheat = NamedColors.Wheat; + public static readonly Rgba32 Wheat = Color.Wheat; /// /// Represents a matching the W3C definition that has an hex value of #FFFFFF. /// - public static readonly Rgba32 White = NamedColors.White; + public static readonly Rgba32 White = Color.White; /// /// Represents a matching the W3C definition that has an hex value of #F5F5F5. /// - public static readonly Rgba32 WhiteSmoke = NamedColors.WhiteSmoke; + public static readonly Rgba32 WhiteSmoke = Color.WhiteSmoke; /// /// Represents a matching the W3C definition that has an hex value of #FFFF00. /// - public static readonly Rgba32 Yellow = NamedColors.Yellow; + public static readonly Rgba32 Yellow = Color.Yellow; /// /// Represents a matching the W3C definition that has an hex value of #9ACD32. /// - public static readonly Rgba32 YellowGreen = NamedColors.YellowGreen; + public static readonly Rgba32 YellowGreen = Color.YellowGreen; } } \ No newline at end of file From 51e23eb7d8bfcb0ea898e5348fe3b23caa5029e8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 14 May 2019 00:06:17 +0200 Subject: [PATCH 192/223] Remove NamedColors usages --- src/ImageSharp.Drawing/Processing/GradientBrushBase.cs | 4 +++- .../Attributes/WithSolidFilledImagesAttribute.cs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs index 6e1e0086d..39dbcb61a 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs @@ -49,6 +49,8 @@ namespace SixLabors.ImageSharp.Processing internal abstract class GradientBrushApplicatorBase : BrushApplicator where TPixel : struct, IPixel { + private static readonly TPixel Transparent = Color.Transparent.ToPixel(); + private readonly ColorStop[] colorStops; private readonly GradientRepetitionMode repetitionMode; @@ -103,7 +105,7 @@ namespace SixLabors.ImageSharp.Processing case GradientRepetitionMode.DontFill: if (positionOnCompleteGradient > 1 || positionOnCompleteGradient < 0) { - return NamedColors.Transparent; + return Transparent; } break; diff --git a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithSolidFilledImagesAttribute.cs b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithSolidFilledImagesAttribute.cs index f95db45f7..190e80fba 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithSolidFilledImagesAttribute.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithSolidFilledImagesAttribute.cs @@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.Tests /// /// The width of the requested image /// The height of the requested image - /// The referenced color name (name of property in + /// The referenced color name (name of property in ). /// The requested pixel types /// Additional theory parameter values public WithSolidFilledImagesAttribute( @@ -119,7 +119,7 @@ namespace SixLabors.ImageSharp.Tests /// The member data to apply to theories /// The width of the requested image /// The height of the requested image - /// The referenced color name (name of property in + /// The referenced color name (name of property in ). /// The requested pixel types /// Additional theory parameter values public WithSolidFilledImagesAttribute( From 89d09ee994b07ee751cea2461bf2c728fa14f414 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Wed, 15 May 2019 21:15:17 +0200 Subject: [PATCH 193/223] Not using quantization for Grey8 images when encoding 8Bit Bitmaps --- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 83 ++++++++++++++----- .../Formats/Bmp/BmpEncoderTests.cs | 6 +- 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index edde7dc89..532d20e00 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -305,37 +305,74 @@ namespace SixLabors.ImageSharp.Formats.Bmp private void Write8Bit(Stream stream, ImageFrame image) where TPixel : struct, IPixel { + bool isGray8 = typeof(TPixel) == typeof(Gray8); using (IMemoryOwner colorPaletteBuffer = this.memoryAllocator.AllocateManagedByteBuffer(ColorPaletteSize8Bit, AllocationOptions.Clean)) - using (IQuantizedFrame quantized = this.quantizer.CreateFrameQuantizer(this.configuration, 256).QuantizeFrame(image)) { Span colorPalette = colorPaletteBuffer.GetSpan(); - int idx = 0; - var color = default(Rgba32); - ReadOnlySpan paletteSpan = quantized.Palette.Span; - - // TODO: Use bulk conversion here for better perf - foreach (TPixel quantizedColor in paletteSpan) + if (isGray8) { - quantizedColor.ToRgba32(ref color); - colorPalette[idx] = color.B; - colorPalette[idx + 1] = color.G; - colorPalette[idx + 2] = color.R; - - // Padding byte, always 0 - colorPalette[idx + 3] = 0; - idx += 4; - } + for (byte i = 0; i <= 255; i++) + { + int idx = i * 4; + colorPalette[idx] = i; + colorPalette[idx + 1] = i; + colorPalette[idx + 2] = i; - stream.Write(colorPalette); + // Padding byte, always 0 + colorPalette[idx + 3] = 0; + } - for (int y = image.Height - 1; y >= 0; y--) - { - ReadOnlySpan pixelSpan = quantized.GetRowSpan(y); - stream.Write(pixelSpan); + stream.Write(colorPalette); - for (int i = 0; i < this.padding; i++) + using (IMemoryOwner rowSpanBuffer = this.memoryAllocator.AllocateManagedByteBuffer(image.Width, AllocationOptions.Clean)) + { + Span outputPixelRow = rowSpanBuffer.GetSpan(); + for (int y = image.Height - 1; y >= 0; y--) + { + Span inputPixelRow = image.GetPixelRowSpan(y); + PixelOperations.Instance.ToGray8Bytes(this.configuration, inputPixelRow, outputPixelRow, image.Width); + stream.Write(outputPixelRow); + + for (int i = 0; i < this.padding; i++) + { + stream.WriteByte(0); + } + } + } + } + else + { + using (IQuantizedFrame quantized = this.quantizer.CreateFrameQuantizer(this.configuration, 256).QuantizeFrame(image)) { - stream.WriteByte(0); + ReadOnlySpan quantizedColors = quantized.Palette.Span; + var color = default(Rgba32); + + // TODO: Use bulk conversion here for better perf + int idx = 0; + foreach (TPixel quantizedColor in quantizedColors) + { + quantizedColor.ToRgba32(ref color); + colorPalette[idx] = color.B; + colorPalette[idx + 1] = color.G; + colorPalette[idx + 2] = color.R; + + // Padding byte, always 0 + colorPalette[idx + 3] = 0; + idx += 4; + } + + stream.Write(colorPalette); + + for (int y = image.Height - 1; y >= 0; y--) + { + ReadOnlySpan pixelSpan = quantized.GetRowSpan(y); + stream.Write(pixelSpan); + + for (int i = 0; i < this.padding; i++) + { + stream.WriteByte(0); + } + } } } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index dd76e9443..162d3f30b 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -169,8 +169,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp TestBmpEncoderCore( provider, bitsPerPixel, - supportTransparency: false, - ImageComparer.TolerantPercentage(0.01f)); + supportTransparency: false); [Theory] [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] @@ -179,8 +178,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp TestBmpEncoderCore( provider, bitsPerPixel, - supportTransparency: true, - ImageComparer.TolerantPercentage(0.01f)); + supportTransparency: true); [Theory] [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] From a1829bccc24d1da25b1059a986943d2a2e888811 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Thu, 16 May 2019 20:08:16 +0200 Subject: [PATCH 194/223] Refactor Write8Bit into two methods: one for gray and one for color --- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 140 ++++++++++++------- 1 file changed, 86 insertions(+), 54 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 532d20e00..e9600f640 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -311,68 +311,100 @@ namespace SixLabors.ImageSharp.Formats.Bmp Span colorPalette = colorPaletteBuffer.GetSpan(); if (isGray8) { - for (byte i = 0; i <= 255; i++) - { - int idx = i * 4; - colorPalette[idx] = i; - colorPalette[idx + 1] = i; - colorPalette[idx + 2] = i; + this.Write8BitGray(stream, image, colorPalette); + } + else + { + this.Write8BitColor(stream, image, colorPalette); + } + } + } - // Padding byte, always 0 - colorPalette[idx + 3] = 0; - } + /// + /// Writes an 8 Bit color image with a color palette. The color palette has 256 entry's with 4 bytes for each entry. + /// + /// The type of the pixel. + /// The to write to. + /// The containing pixel data. + /// A byte span of size 1024 for the color palette. + private void Write8BitColor(Stream stream, ImageFrame image, Span colorPalette) + where TPixel : struct, IPixel + { + using (IQuantizedFrame quantized = this.quantizer.CreateFrameQuantizer(this.configuration, 256).QuantizeFrame(image)) + { + ReadOnlySpan quantizedColors = quantized.Palette.Span; + var color = default(Rgba32); - stream.Write(colorPalette); + // TODO: Use bulk conversion here for better perf + int idx = 0; + foreach (TPixel quantizedColor in quantizedColors) + { + quantizedColor.ToRgba32(ref color); + colorPalette[idx] = color.B; + colorPalette[idx + 1] = color.G; + colorPalette[idx + 2] = color.R; + + // Padding byte, always 0. + colorPalette[idx + 3] = 0; + idx += 4; + } - using (IMemoryOwner rowSpanBuffer = this.memoryAllocator.AllocateManagedByteBuffer(image.Width, AllocationOptions.Clean)) + stream.Write(colorPalette); + + for (int y = image.Height - 1; y >= 0; y--) + { + ReadOnlySpan pixelSpan = quantized.GetRowSpan(y); + stream.Write(pixelSpan); + + for (int i = 0; i < this.padding; i++) { - Span outputPixelRow = rowSpanBuffer.GetSpan(); - for (int y = image.Height - 1; y >= 0; y--) - { - Span inputPixelRow = image.GetPixelRowSpan(y); - PixelOperations.Instance.ToGray8Bytes(this.configuration, inputPixelRow, outputPixelRow, image.Width); - stream.Write(outputPixelRow); - - for (int i = 0; i < this.padding; i++) - { - stream.WriteByte(0); - } - } + stream.WriteByte(0); } } - else + } + } + + /// + /// Writes an 8 Bit gray image with a color palette. The color palette has 256 entry's with 4 bytes for each entry. + /// + /// The type of the pixel. + /// The to write to. + /// The containing pixel data. + /// A byte span of size 1024 for the color palette. + private void Write8BitGray(Stream stream, ImageFrame image, Span colorPalette) + where TPixel : struct, IPixel + { + // Create a color palette with 256 different gray values. + for (int i = 0; i <= 255; i++) + { + int idx = i * 4; + byte grayValue = (byte)i; + colorPalette[idx] = grayValue; + colorPalette[idx + 1] = grayValue; + colorPalette[idx + 2] = grayValue; + + // Padding byte, always 0. + colorPalette[idx + 3] = 0; + } + + stream.Write(colorPalette); + + using (IMemoryOwner rowSpanBuffer = this.memoryAllocator.AllocateManagedByteBuffer(image.Width, AllocationOptions.Clean)) + { + Span outputPixelRow = rowSpanBuffer.GetSpan(); + for (int y = image.Height - 1; y >= 0; y--) { - using (IQuantizedFrame quantized = this.quantizer.CreateFrameQuantizer(this.configuration, 256).QuantizeFrame(image)) + Span inputPixelRow = image.GetPixelRowSpan(y); + PixelOperations.Instance.ToGray8Bytes( + this.configuration, + inputPixelRow, + outputPixelRow, + image.Width); + stream.Write(outputPixelRow); + + for (int i = 0; i < this.padding; i++) { - ReadOnlySpan quantizedColors = quantized.Palette.Span; - var color = default(Rgba32); - - // TODO: Use bulk conversion here for better perf - int idx = 0; - foreach (TPixel quantizedColor in quantizedColors) - { - quantizedColor.ToRgba32(ref color); - colorPalette[idx] = color.B; - colorPalette[idx + 1] = color.G; - colorPalette[idx + 2] = color.R; - - // Padding byte, always 0 - colorPalette[idx + 3] = 0; - idx += 4; - } - - stream.Write(colorPalette); - - for (int y = image.Height - 1; y >= 0; y--) - { - ReadOnlySpan pixelSpan = quantized.GetRowSpan(y); - stream.Write(pixelSpan); - - for (int i = 0; i < this.padding; i++) - { - stream.WriteByte(0); - } - } + stream.WriteByte(0); } } } From 17f231101874904402fdab61089fa669f7493957 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 16 May 2019 23:38:28 +0200 Subject: [PATCH 195/223] drop unnecessary generic IImageProcessorContext usages --- .../Extensions/ProcessingExtensions.cs | 14 ++-- .../ImageSharp.Benchmarks/Drawing/DrawText.cs | 10 ++- .../Drawing/DrawTextOutline.cs | 5 +- .../ImageSharp.Benchmarks/Samplers/Resize.cs | 10 +-- tests/ImageSharp.Tests/ImageOperationTests.cs | 39 ++++++----- .../Basic1ParameterConvolutionTests.cs | 6 +- .../Processors/Convolution/BoxBlurTest.cs | 4 +- .../Convolution/GaussianBlurTest.cs | 4 +- .../Convolution/GaussianSharpenTest.cs | 4 +- .../Processors/Transforms/ResizeTests.cs | 6 +- .../ImageProviders/TestImageProvider.cs | 2 +- .../TestUtilities/TestImageExtensions.cs | 69 ++++++++++--------- .../TestUtilities/TestUtils.cs | 14 ++-- 13 files changed, 99 insertions(+), 88 deletions(-) diff --git a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs index c72e8cfb7..e469af18b 100644 --- a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image to mutate. /// The operation to perform on the source. - public static void Mutate(this Image source, Action> operation) + public static void Mutate(this Image source, Action operation) where TPixel : struct, IPixel { Guard.NotNull(operation, nameof(operation)); @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Processing /// The pixel format. /// The image to mutate. /// The operations to perform on the source. - public static void Mutate(this Image source, params IImageProcessor[] operations) + public static void Mutate(this Image source, params IImageProcessor[] operations) where TPixel : struct, IPixel { Guard.NotNull(operations, nameof(operations)); @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.Processing /// The image to clone. /// The operation to perform on the clone. /// The new - public static Image Clone(this Image source, Action> operation) + public static Image Clone(this Image source, Action operation) where TPixel : struct, IPixel { Guard.NotNull(operation, nameof(operation)); @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.Processing /// The image to clone. /// The operations to perform on the clone. /// The new - public static Image Clone(this Image source, params IImageProcessor[] operations) + public static Image Clone(this Image source, params IImageProcessor[] operations) where TPixel : struct, IPixel { Guard.NotNull(operations, nameof(operations)); @@ -122,14 +122,12 @@ namespace SixLabors.ImageSharp.Processing /// /// Applies the given collection against the context /// - /// The pixel format. /// The image processing context. /// The operations to perform on the source. /// The to allow chaining of operations. - public static IImageProcessingContext ApplyProcessors(this IImageProcessingContext source, params IImageProcessor[] operations) - where TPixel : struct, IPixel + public static IImageProcessingContext ApplyProcessors(this IImageProcessingContext source, params IImageProcessor[] operations) { - foreach (IImageProcessor p in operations) + foreach (IImageProcessor p in operations) { source = source.ApplyProcessor(p); } diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs index 28f410e7d..0982db334 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawText.cs @@ -55,8 +55,14 @@ namespace SixLabors.ImageSharp.Benchmarks image.Mutate(x => DrawTextOldVersion(x, new TextGraphicsOptions(true) { WrapTextWidth = 780 }, TextToRender, font, Processing.Brushes.Solid(Rgba32.HotPink), null, new SixLabors.Primitives.PointF(10, 10))); } - IImageProcessingContext DrawTextOldVersion(IImageProcessingContext source, TextGraphicsOptions options, string text, SixLabors.Fonts.Font font, IBrush brush, IPen pen, SixLabors.Primitives.PointF location) - where TPixel : struct, IPixel + IImageProcessingContext DrawTextOldVersion( + IImageProcessingContext source, + TextGraphicsOptions options, + string text, + SixLabors.Fonts.Font font, + IBrush brush, + IPen pen, + SixLabors.Primitives.PointF location) { float dpiX = 72; float dpiY = 72; diff --git a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs index 658590e2d..c5c1ba5ac 100644 --- a/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs +++ b/tests/ImageSharp.Benchmarks/Drawing/DrawTextOutline.cs @@ -64,15 +64,14 @@ namespace SixLabors.ImageSharp.Benchmarks new SixLabors.Primitives.PointF(10, 10))); } - IImageProcessingContext DrawTextOldVersion( - IImageProcessingContext source, + IImageProcessingContext DrawTextOldVersion( + IImageProcessingContext source, TextGraphicsOptions options, string text, SixLabors.Fonts.Font font, IBrush brush, IPen pen, SixLabors.Primitives.PointF location) - where TPixel : struct, IPixel { var style = new SixLabors.Fonts.RendererOptions(font, options.DpiX, options.DpiY, location) { diff --git a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs index cf47202cc..172e24372 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Resize.cs @@ -91,12 +91,12 @@ namespace SixLabors.ImageSharp.Benchmarks } } - protected abstract void ExecuteResizeOperation(IImageProcessingContext ctx); + protected abstract void ExecuteResizeOperation(IImageProcessingContext ctx); } public class Resize_Bicubic_Rgba32 : ResizeBenchmarkBase { - protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); } @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Benchmarks public class Resize_Bicubic_Bgra32 : ResizeBenchmarkBase { - protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); } @@ -171,7 +171,7 @@ namespace SixLabors.ImageSharp.Benchmarks public class Resize_Bicubic_Rgb24 : ResizeBenchmarkBase { - protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); } @@ -198,7 +198,7 @@ namespace SixLabors.ImageSharp.Benchmarks public class Resize_BicubicCompand_Rgba32 : ResizeBenchmarkBase { - protected override void ExecuteResizeOperation(IImageProcessingContext ctx) + protected override void ExecuteResizeOperation(IImageProcessingContext ctx) { ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic, true); } diff --git a/tests/ImageSharp.Tests/ImageOperationTests.cs b/tests/ImageSharp.Tests/ImageOperationTests.cs index e694f0b64..b99ad64b2 100644 --- a/tests/ImageSharp.Tests/ImageOperationTests.cs +++ b/tests/ImageSharp.Tests/ImageOperationTests.cs @@ -21,14 +21,21 @@ namespace SixLabors.ImageSharp.Tests { private readonly Image image; private readonly FakeImageOperationsProvider provider; - private readonly IImageProcessor processor; + private readonly IImageProcessor processorImplementation; + + private readonly IImageProcessor processorDefinition; public Configuration Configuration { get; private set; } public ImageOperationTests() { this.provider = new FakeImageOperationsProvider(); - this.processor = new Mock>().Object; + this.processorImplementation = new Mock>().Object; + + Mock processorMock = new Mock(); + processorMock.Setup(p => p.CreatePixelSpecificProcessor()).Returns(this.processorImplementation); + this.processorDefinition = processorMock.Object; + this.image = new Image(new Configuration() { ImageOperationsProvider = this.provider @@ -38,61 +45,61 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void MutateCallsImageOperationsProvider_Func_OriginalImage() { - this.image.Mutate(x => x.ApplyProcessor(this.processor)); + this.image.Mutate(x => x.ApplyProcessor(this.processorDefinition)); Assert.True(this.provider.HasCreated(this.image)); - Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] public void MutateCallsImageOperationsProvider_ListOfProcessors_OriginalImage() { - this.image.Mutate(this.processor); + this.image.Mutate(this.processorDefinition); Assert.True(this.provider.HasCreated(this.image)); - Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] public void CloneCallsImageOperationsProvider_Func_WithDuplicateImage() { - Image returned = this.image.Clone(x => x.ApplyProcessor(this.processor)); + Image returned = this.image.Clone(x => x.ApplyProcessor(this.processorDefinition)); Assert.True(this.provider.HasCreated(returned)); - Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); + Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); } [Fact] public void CloneCallsImageOperationsProvider_ListOfProcessors_WithDuplicateImage() { - Image returned = this.image.Clone(this.processor); + Image returned = this.image.Clone(this.processorDefinition); Assert.True(this.provider.HasCreated(returned)); - Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); + Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); } [Fact] public void CloneCallsImageOperationsProvider_Func_NotOnOrigional() { - Image returned = this.image.Clone(x => x.ApplyProcessor(this.processor)); + Image returned = this.image.Clone(x => x.ApplyProcessor(this.processorDefinition)); Assert.False(this.provider.HasCreated(this.image)); - Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.DoesNotContain(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] public void CloneCallsImageOperationsProvider_ListOfProcessors_NotOnOrigional() { - Image returned = this.image.Clone(this.processor); + Image returned = this.image.Clone(this.processorDefinition); Assert.False(this.provider.HasCreated(this.image)); - Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.DoesNotContain(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); } [Fact] public void ApplyProcessors_ListOfProcessors_AppliesAllProcessorsToOperation() { var operations = new FakeImageOperationsProvider.FakeImageOperations(null, false); - operations.ApplyProcessors(this.processor); - Assert.Contains(this.processor, operations.Applied.Select(x => x.GenericProcessor)); + operations.ApplyProcessors(this.processorDefinition); + Assert.Contains(this.processorImplementation, operations.Applied.Select(x => x.GenericProcessor)); } public void Dispose() => this.image.Dispose(); diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs index 1f939a281..0a10d0755 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs @@ -47,10 +47,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution ValidatorComparer); } - protected abstract void Apply(IImageProcessingContext ctx, int value) - where TPixel : struct, IPixel; + protected abstract void Apply(IImageProcessingContext ctx, int value); - protected abstract void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) - where TPixel : struct, IPixel; + protected abstract void Apply(IImageProcessingContext ctx, int value, Rectangle bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs index 923f9d616..a7cf9360c 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs @@ -9,9 +9,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution [GroupOutput("Convolution")] public class BoxBlurTest : Basic1ParameterConvolutionTests { - protected override void Apply(IImageProcessingContext ctx, int value) => ctx.BoxBlur(value); + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.BoxBlur(value); - protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => ctx.BoxBlur(value, bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs index 6307a1c51..68eb8c4f6 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs @@ -13,9 +13,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution [GroupOutput("Convolution")] public class GaussianBlurTest : Basic1ParameterConvolutionTests { - protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianBlur(value); + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianBlur(value); - protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => ctx.GaussianBlur(value, bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs index 29a1643b0..4b497309e 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs @@ -12,9 +12,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution [GroupOutput("Convolution")] public class GaussianSharpenTest : Basic1ParameterConvolutionTests { - protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianSharpen(value); + protected override void Apply(IImageProcessingContext ctx, int value) => ctx.GaussianSharpen(value); - protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => + protected override void Apply(IImageProcessingContext ctx, int value, Rectangle bounds) => ctx.GaussianSharpen(value, bounds); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 9bf9079d4..8ae298c51 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -322,11 +322,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms } FormattableString testOutputDetails = $"{samplerName}-{destSizeInfo}"; - ctx.Apply( - img => img.DebugSave( - provider, - $"{testOutputDetails}-ORIGINAL", - appendPixelTypeToFileName: false)); + ctx.Resize((Size)newSize, sampler, false); return testOutputDetails; }, diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs index 15fab9b2b..8d493c7d4 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs @@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Tests /// /// Returns an instance to the test case with the necessary traits. /// - public Image GetImage(Action> operationsToApply) + public Image GetImage(Action operationsToApply) { Image img = this.GetImage(); img.Mutate(operationsToApply); diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index e77b1974d..8de3a347b 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -9,10 +9,13 @@ using System.Numerics; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.ParallelUtils; using SixLabors.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.Primitives; using Xunit; @@ -21,39 +24,11 @@ namespace SixLabors.ImageSharp.Tests public static class TestImageExtensions { /// - /// TODO: This should be a common processing method! The image.Opacity(val) multiplies the alpha channel! + /// TODO: Consider adding this private processor to the library /// - /// /// - public static void MakeOpaque(this IImageProcessingContext ctx) - where TPixel : struct, IPixel - { - MemoryAllocator memoryAllocator = ctx.MemoryAllocator; - - ctx.Apply( - img => - { - Configuration configuration = img.GetConfiguration(); - using (Buffer2D temp = memoryAllocator.Allocate2D(img.Width, img.Height)) - { - Span tempSpan = temp.GetSpan(); - foreach (ImageFrame frame in img.Frames) - { - Span pixelSpan = frame.GetPixelSpan(); - - PixelOperations.Instance.ToVector4(configuration, pixelSpan, tempSpan, PixelConversionModifiers.Scale); - - for (int i = 0; i < tempSpan.Length; i++) - { - ref Vector4 v = ref tempSpan[i]; - v.W = 1F; - } - - PixelOperations.Instance.FromVector4Destructive(configuration, tempSpan, pixelSpan, PixelConversionModifiers.Scale); - } - } - }); - } + public static void MakeOpaque(this IImageProcessingContext ctx) => + ctx.ApplyProcessor(new MakeOpaqueProcessor()); public static void DebugSave( this Image image, @@ -702,5 +677,37 @@ namespace SixLabors.ImageSharp.Tests return image; } + private class MakeOpaqueProcessor : IImageProcessor + { + public IImageProcessor CreatePixelSpecificProcessor() + where TPixel : struct, IPixel + { + return new MakeOpaqueProcessor(); + } + } + + private class MakeOpaqueProcessor : ImageProcessor + where TPixel : struct, IPixel + { + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + ParallelHelper.IterateRowsWithTempBuffer(sourceRectangle, configuration, + (rows, temp) => + { + Span tempSpan = temp.Span; + for (int y = rows.Min; y < rows.Max; y++) + { + var rowSpan = source.GetPixelRowSpan(y).Slice(sourceRectangle.Left, sourceRectangle.Width); + PixelOperations.Instance.ToVector4(configuration, rowSpan, tempSpan, PixelConversionModifiers.Scale); + for (int i = 0; i < tempSpan.Length; i++) + { + ref Vector4 v = ref tempSpan[i]; + v.W = 1F; + } + PixelOperations.Instance.FromVector4Destructive(configuration, tempSpan, rowSpan, PixelConversionModifiers.Scale); + } + }); + } + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs index 5db0c0828..b56ce0517 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs @@ -165,7 +165,7 @@ namespace SixLabors.ImageSharp.Tests /// internal static void RunValidatingProcessorTest( this TestImageProvider provider, - Action> process, + Action process, object testOutputDetails = null, ImageComparer comparer = null, bool appendPixelTypeToFileName = true, @@ -202,7 +202,7 @@ namespace SixLabors.ImageSharp.Tests internal static void RunValidatingProcessorTest( this TestImageProvider provider, - Func, FormattableString> processAndGetTestOutputDetails, + Func processAndGetTestOutputDetails, ImageComparer comparer = null, bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true) @@ -241,7 +241,7 @@ namespace SixLabors.ImageSharp.Tests public static void RunValidatingProcessorTestOnWrappedMemoryImage( this TestImageProvider provider, - Action> process, + Action process, object testOutputDetails = null, ImageComparer comparer = null, string useReferenceOutputFrom = null, @@ -291,11 +291,11 @@ namespace SixLabors.ImageSharp.Tests } /// - /// Same as but with an additional parameter passed to 'process' + /// Same as 'RunValidatingProcessorTest{TPixel}' but with an additional parameter passed to 'process' /// internal static void RunRectangleConstrainedValidatingProcessorTest( this TestImageProvider provider, - Action, Rectangle> process, + Action process, object testOutputDetails = null, ImageComparer comparer = null) where TPixel : struct, IPixel @@ -315,11 +315,11 @@ namespace SixLabors.ImageSharp.Tests } /// - /// Same as but without the 'CompareToReferenceOutput()' step. + /// Same as 'RunValidatingProcessorTest{TPixel}' but without the 'CompareToReferenceOutput()' step. /// internal static void RunProcessorTest( this TestImageProvider provider, - Action> process, + Action process, object testOutputDetails = null) where TPixel : struct, IPixel { From 7e57fce3076eb905f7ed6b3ddbf2dabf6cb68986 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 17 May 2019 00:06:37 +0200 Subject: [PATCH 196/223] drop almost all usages of FileTestBase --- .../Binarization/BinaryDitherTests.cs | 19 ++++++++++--------- .../Binarization/BinaryThresholdTest.cs | 15 +++++++++++---- .../Processors/Transforms/PadTest.cs | 9 +++++++-- .../Processors/Transforms/RotateFlipTests.cs | 6 +++--- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryDitherTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryDitherTests.cs index 44fdfc703..d3507ed4c 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryDitherTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryDitherTests.cs @@ -12,7 +12,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { - public class BinaryDitherTests : FileTestBase + public class BinaryDitherTests { public static readonly string[] CommonTestImages = { @@ -40,14 +40,15 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { "Stucki", KnownDiffusers.Stucki }, }; + public const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24; private static IOrderedDither DefaultDitherer => KnownDitherers.BayerDither4x4; private static IErrorDiffuser DefaultErrorDiffuser => KnownDiffusers.Atkinson; [Theory] - [WithFileCollection(nameof(CommonTestImages), nameof(OrderedDitherers), DefaultPixelType)] - [WithTestPatternImages(nameof(OrderedDitherers), 100, 100, DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), nameof(OrderedDitherers), PixelTypes.Rgba32)] + [WithTestPatternImages(nameof(OrderedDitherers), 100, 100, PixelTypes.Rgba32)] public void BinaryDitherFilter_WorksWithAllDitherers(TestImageProvider provider, string name, IOrderedDither ditherer) where TPixel : struct, IPixel { @@ -59,8 +60,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFileCollection(nameof(CommonTestImages), nameof(ErrorDiffusers), DefaultPixelType)] - [WithTestPatternImages(nameof(ErrorDiffusers), 100, 100, DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), nameof(ErrorDiffusers), PixelTypes.Rgba32)] + [WithTestPatternImages(nameof(ErrorDiffusers), 100, 100, PixelTypes.Rgba32)] public void DiffusionFilter_WorksWithAllErrorDiffusers(TestImageProvider provider, string name, IErrorDiffuser diffuser) where TPixel : struct, IPixel { @@ -72,7 +73,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFile(TestImages.Png.Bike, CommonNonDefaultPixelTypes)] + [WithFile(TestImages.Png.Bike, TestPixelTypes)] public void BinaryDitherFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { @@ -84,7 +85,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFile(TestImages.Png.Bike, CommonNonDefaultPixelTypes)] + [WithFile(TestImages.Png.Bike, TestPixelTypes)] public void DiffusionFilter_ShouldNotDependOnSinglePixelType(TestImageProvider provider) where TPixel : struct, IPixel { @@ -96,7 +97,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFile(TestImages.Png.CalliphoraPartial, DefaultPixelType)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] public void ApplyDitherFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { @@ -113,7 +114,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFile(TestImages.Png.CalliphoraPartial, DefaultPixelType)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] public void ApplyDiffusionFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs index 988c9125b..4ae5d6051 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs @@ -11,17 +11,24 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { using SixLabors.ImageSharp.Processing; - public class BinaryThresholdTest : FileTestBase + public class BinaryThresholdTest { public static readonly TheoryData BinaryThresholdValues - = new TheoryData + = new TheoryData { .25F, .75F }; + + public static readonly string[] CommonTestImages = + { + TestImages.Png.CalliphoraPartial, TestImages.Png.Bike + }; + + public const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BinaryThresholdValues), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), nameof(BinaryThresholdValues), PixelTypes.Rgba32)] public void ImageShouldApplyBinaryThresholdFilter(TestImageProvider provider, float value) where TPixel : struct, IPixel { @@ -33,7 +40,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BinaryThresholdValues), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), nameof(BinaryThresholdValues), PixelTypes.Rgba32)] public void ImageShouldApplyBinaryThresholdInBox(TestImageProvider provider, float value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs index 6cce62d14..750d67c32 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs @@ -7,10 +7,15 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { - public class PadTest : FileTestBase + public class PadTest { + public static readonly string[] CommonTestImages = + { + TestImages.Png.CalliphoraPartial, TestImages.Png.Bike + }; + [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)] public void ImageShouldPad(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateFlipTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateFlipTests.cs index d6376b179..20e12cb7f 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateFlipTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateFlipTests.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { using SixLabors.ImageSharp.Processing; - public class RotateFlipTests : FileTestBase + public class RotateFlipTests { public static readonly string[] FlipFiles = { TestImages.Bmp.F }; @@ -24,8 +24,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms }; [Theory] - [WithTestPatternImages(nameof(RotateFlipValues), 100, 50, DefaultPixelType)] - [WithTestPatternImages(nameof(RotateFlipValues), 50, 100, DefaultPixelType)] + [WithTestPatternImages(nameof(RotateFlipValues), 100, 50, PixelTypes.Rgba32)] + [WithTestPatternImages(nameof(RotateFlipValues), 50, 100, PixelTypes.Rgba32)] public void RotateFlip(TestImageProvider provider, RotateMode rotateType, FlipMode flipType) where TPixel : struct, IPixel { From 3af895b55ef7ddd7d54d3999f5077bcb1fa0dab8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 17 May 2019 00:29:06 +0200 Subject: [PATCH 197/223] fix tests --- .../Drawing/DrawImageTests.cs | 5 ++- tests/ImageSharp.Tests/ImageOperationTests.cs | 34 +++++++++++-------- tests/ImageSharp.Tests/Issues/Issue412.cs | 3 +- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index cb44651d6..52821cf47 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -112,7 +112,10 @@ namespace SixLabors.ImageSharp.Tests.Drawing image.Mutate(c => c.DrawImage(brushImage, 0.5f)); image.DebugSave(provider, appendSourceFileOrDescription: false); - image.CompareToReferenceOutput(provider, appendSourceFileOrDescription: false); + image.CompareToReferenceOutput( + ImageComparer.TolerantPercentage(0.01f), + provider, + appendSourceFileOrDescription: false); } } diff --git a/tests/ImageSharp.Tests/ImageOperationTests.cs b/tests/ImageSharp.Tests/ImageOperationTests.cs index b99ad64b2..30371f000 100644 --- a/tests/ImageSharp.Tests/ImageOperationTests.cs +++ b/tests/ImageSharp.Tests/ImageOperationTests.cs @@ -21,19 +21,13 @@ namespace SixLabors.ImageSharp.Tests { private readonly Image image; private readonly FakeImageOperationsProvider provider; - private readonly IImageProcessor processorImplementation; - private readonly IImageProcessor processorDefinition; - public Configuration Configuration { get; private set; } - public ImageOperationTests() { this.provider = new FakeImageOperationsProvider(); - this.processorImplementation = new Mock>().Object; - + Mock processorMock = new Mock(); - processorMock.Setup(p => p.CreatePixelSpecificProcessor()).Returns(this.processorImplementation); this.processorDefinition = processorMock.Object; this.image = new Image(new Configuration() @@ -48,7 +42,9 @@ namespace SixLabors.ImageSharp.Tests this.image.Mutate(x => x.ApplyProcessor(this.processorDefinition)); Assert.True(this.provider.HasCreated(this.image)); - Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.Contains( + this.processorDefinition, + this.provider.AppliedOperations(this.image).Select(x => x.NonGenericProcessor)); } [Fact] @@ -57,7 +53,9 @@ namespace SixLabors.ImageSharp.Tests this.image.Mutate(this.processorDefinition); Assert.True(this.provider.HasCreated(this.image)); - Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.Contains( + this.processorDefinition, + this.provider.AppliedOperations(this.image).Select(x => x.NonGenericProcessor)); } [Fact] @@ -66,7 +64,9 @@ namespace SixLabors.ImageSharp.Tests Image returned = this.image.Clone(x => x.ApplyProcessor(this.processorDefinition)); Assert.True(this.provider.HasCreated(returned)); - Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); + Assert.Contains( + this.processorDefinition, + this.provider.AppliedOperations(returned).Select(x => x.NonGenericProcessor)); } [Fact] @@ -75,7 +75,9 @@ namespace SixLabors.ImageSharp.Tests Image returned = this.image.Clone(this.processorDefinition); Assert.True(this.provider.HasCreated(returned)); - Assert.Contains(this.processorImplementation, this.provider.AppliedOperations(returned).Select(x => x.GenericProcessor)); + Assert.Contains( + this.processorDefinition, + this.provider.AppliedOperations(returned).Select(x => x.NonGenericProcessor)); } [Fact] @@ -83,7 +85,9 @@ namespace SixLabors.ImageSharp.Tests { Image returned = this.image.Clone(x => x.ApplyProcessor(this.processorDefinition)); Assert.False(this.provider.HasCreated(this.image)); - Assert.DoesNotContain(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.DoesNotContain( + this.processorDefinition, + this.provider.AppliedOperations(this.image).Select(x => x.NonGenericProcessor)); } [Fact] @@ -91,7 +95,9 @@ namespace SixLabors.ImageSharp.Tests { Image returned = this.image.Clone(this.processorDefinition); Assert.False(this.provider.HasCreated(this.image)); - Assert.DoesNotContain(this.processorImplementation, this.provider.AppliedOperations(this.image).Select(x => x.GenericProcessor)); + Assert.DoesNotContain( + this.processorDefinition, + this.provider.AppliedOperations(this.image).Select(x => x.NonGenericProcessor)); } [Fact] @@ -99,7 +105,7 @@ namespace SixLabors.ImageSharp.Tests { var operations = new FakeImageOperationsProvider.FakeImageOperations(null, false); operations.ApplyProcessors(this.processorDefinition); - Assert.Contains(this.processorImplementation, operations.Applied.Select(x => x.GenericProcessor)); + Assert.Contains(this.processorDefinition, operations.Applied.Select(x => x.NonGenericProcessor)); } public void Dispose() => this.image.Dispose(); diff --git a/tests/ImageSharp.Tests/Issues/Issue412.cs b/tests/ImageSharp.Tests/Issues/Issue412.cs index f22d3a85c..7b2cfd81c 100644 --- a/tests/ImageSharp.Tests/Issues/Issue412.cs +++ b/tests/ImageSharp.Tests/Issues/Issue412.cs @@ -46,8 +46,9 @@ namespace SixLabors.ImageSharp.Tests.Issues { for (var x = 0; x < 40; x++) { + TPixel red = Color.Red.ToPixel(); - Assert.True(Color.Red.Equals(image[x, y]), $"expected {Color.Red} but found {image[x, y]} at [{x}, {y}]"); + Assert.True(red.Equals(image[x, y]), $"expected {Color.Red} but found {image[x, y]} at [{x}, {y}]"); } } } From a36aa55a59a116aaac50b280852dc6d5b755b5a2 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Fri, 17 May 2019 01:01:20 +0200 Subject: [PATCH 198/223] re-enable target frameworks --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 3 +-- src/ImageSharp/ImageSharp.csproj | 3 +-- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 722ef33ff..f9181b45d 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -11,8 +11,7 @@ $(packageversion) 0.0.1 - - netstandard2.0 + netcoreapp2.1;netstandard1.3;netstandard2.0 7.3 true diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 1b213c26d..832a6ce3f 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -11,8 +11,7 @@ $(packageversion) 0.0.1 - - netstandard2.0 + netcoreapp2.1;netstandard1.3;netstandard2.0;net472 true true diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index efdf89964..0b727f30c 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,7 +1,6 @@  - - netcoreapp2.1 + netcoreapp2.1;net462;net472 True latest full From ec0e91376f4e0a2297e55b0f6250d495e31cafcb Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sat, 18 May 2019 11:44:47 +0200 Subject: [PATCH 199/223] Add tests for quantization of 32 bit bitmap to 8 bit color image --- .../Formats/Bmp/BmpEncoderTests.cs | 44 +++++++++++++++++++ tests/Images/External | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index 162d3f30b..36bd2bbdb 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -3,10 +3,12 @@ using System.IO; +using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using Xunit; @@ -180,6 +182,48 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp bitsPerPixel, supportTransparency: true); + [Theory] + [WithFile(Bit32Rgb, PixelTypes.Rgba32)] + public void Encode_8BitColor_WithWuQuantizer(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var encoder = new BmpEncoder + { + BitsPerPixel = BmpBitsPerPixel.Pixel8, + Quantizer = new WuQuantizer(256) + }; + string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); + IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); + using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) + { + referenceImage.CompareToReferenceOutput(ImageComparer.Exact, provider, extension: "bmp", appendPixelTypeToFileName: false); + } + } + } + + [Theory] + [WithFile(Bit32Rgb, PixelTypes.Rgba32)] + public void Encode_8BitColor_WithOctreeQuantizer(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var encoder = new BmpEncoder + { + BitsPerPixel = BmpBitsPerPixel.Pixel8, + Quantizer = new OctreeQuantizer(256) + }; + string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); + IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); + using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) + { + referenceImage.CompareToReferenceOutput(ImageComparer.Exact, provider, extension: "bmp", appendPixelTypeToFileName: false); + } + } + } + [Theory] [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] [WithFile(Bit32Rgba, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] diff --git a/tests/Images/External b/tests/Images/External index c057090b4..42b3b980e 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit c057090b4402120a83a8efe251aa5b691db9c0dc +Subproject commit 42b3b980ed07afd7b6603a5bfa6ffb91d6c8a124 From 18cda2ea480267c55a0ca469e851406bb3f9b7fb Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sat, 18 May 2019 12:07:47 +0200 Subject: [PATCH 200/223] Renamed DrawImageTest to DrawImageTests, fixed namespace --- .../Drawing/{DrawImageTest.cs => DrawImageTests.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename tests/ImageSharp.Tests/Drawing/{DrawImageTest.cs => DrawImageTests.cs} (99%) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs similarity index 99% rename from tests/ImageSharp.Tests/Drawing/DrawImageTest.cs rename to tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index 54b04390e..0d0a82125 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -8,10 +8,10 @@ using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.Primitives; using Xunit; -namespace SixLabors.ImageSharp.Tests +namespace SixLabors.ImageSharp.Tests.Drawing { [GroupOutput("Drawing")] - public class DrawImageTest : FileTestBase + public class DrawImageTests : FileTestBase { private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32; From 5733661aca0e5ba69bf78a10db54d784fb93ac90 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sat, 18 May 2019 12:49:35 +0200 Subject: [PATCH 201/223] Using tolerant comparer for the Encode_8BitColor tests --- tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index 36bd2bbdb..f4c3154da 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -198,7 +198,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) { - referenceImage.CompareToReferenceOutput(ImageComparer.Exact, provider, extension: "bmp", appendPixelTypeToFileName: false); + referenceImage.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), provider, extension: "bmp", appendPixelTypeToFileName: false); } } } @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) { - referenceImage.CompareToReferenceOutput(ImageComparer.Exact, provider, extension: "bmp", appendPixelTypeToFileName: false); + referenceImage.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), provider, extension: "bmp", appendPixelTypeToFileName: false); } } } From d98f003b91cbf0af787329622ad16a51e8aad0be Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sat, 18 May 2019 19:06:44 +0200 Subject: [PATCH 202/223] Removed the Encode_8BitColor, because of the quantization differences with net472 and netcore --- .../Formats/Bmp/BmpEncoderTests.cs | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index f4c3154da..9208de694 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -182,48 +182,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp bitsPerPixel, supportTransparency: true); - [Theory] - [WithFile(Bit32Rgb, PixelTypes.Rgba32)] - public void Encode_8BitColor_WithWuQuantizer(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - var encoder = new BmpEncoder - { - BitsPerPixel = BmpBitsPerPixel.Pixel8, - Quantizer = new WuQuantizer(256) - }; - string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); - IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); - using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) - { - referenceImage.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), provider, extension: "bmp", appendPixelTypeToFileName: false); - } - } - } - - [Theory] - [WithFile(Bit32Rgb, PixelTypes.Rgba32)] - public void Encode_8BitColor_WithOctreeQuantizer(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - var encoder = new BmpEncoder - { - BitsPerPixel = BmpBitsPerPixel.Pixel8, - Quantizer = new OctreeQuantizer(256) - }; - string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); - IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); - using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) - { - referenceImage.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), provider, extension: "bmp", appendPixelTypeToFileName: false); - } - } - } - [Theory] [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] [WithFile(Bit32Rgba, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] From e62ae795c76212018c872e14eab9c28d7552d1b5 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sun, 19 May 2019 18:34:07 +0200 Subject: [PATCH 203/223] Re-enabled Encode_8BitColor tests, if its 64 bit process --- .../Formats/Bmp/BmpEncoderTests.cs | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index 9208de694..178e652ae 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -182,6 +182,58 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp bitsPerPixel, supportTransparency: true); + [Theory] + [WithFile(Bit32Rgb, PixelTypes.Rgba32)] + public void Encode_8BitColor_WithWuQuantizer(TestImageProvider provider) + where TPixel : struct, IPixel + { + if (!TestEnvironment.Is64BitProcess) + { + return; + } + + using (Image image = provider.GetImage()) + { + var encoder = new BmpEncoder + { + BitsPerPixel = BmpBitsPerPixel.Pixel8, + Quantizer = new WuQuantizer(256) + }; + string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); + IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); + using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) + { + referenceImage.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), provider, extension: "bmp", appendPixelTypeToFileName: false); + } + } + } + + [Theory] + [WithFile(Bit32Rgb, PixelTypes.Rgba32)] + public void Encode_8BitColor_WithOctreeQuantizer(TestImageProvider provider) + where TPixel : struct, IPixel + { + if (!TestEnvironment.Is64BitProcess) + { + return; + } + + using (Image image = provider.GetImage()) + { + var encoder = new BmpEncoder + { + BitsPerPixel = BmpBitsPerPixel.Pixel8, + Quantizer = new OctreeQuantizer(256) + }; + string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); + IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); + using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) + { + referenceImage.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), provider, extension: "bmp", appendPixelTypeToFileName: false); + } + } + } + [Theory] [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] [WithFile(Bit32Rgba, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)] From 88097655b8111ca2b9956d9e620dababa47c5b76 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sun, 19 May 2019 20:56:20 +0200 Subject: [PATCH 204/223] Using MemoryMarshal.AsBytes in Write8BitGray to get the bytes of a row --- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 23 +++++++------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index e9600f640..9fbd0b5ad 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -4,6 +4,7 @@ using System; using System.Buffers; using System.IO; +using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Common.Helpers; @@ -389,23 +390,15 @@ namespace SixLabors.ImageSharp.Formats.Bmp stream.Write(colorPalette); - using (IMemoryOwner rowSpanBuffer = this.memoryAllocator.AllocateManagedByteBuffer(image.Width, AllocationOptions.Clean)) + for (int y = image.Height - 1; y >= 0; y--) { - Span outputPixelRow = rowSpanBuffer.GetSpan(); - for (int y = image.Height - 1; y >= 0; y--) - { - Span inputPixelRow = image.GetPixelRowSpan(y); - PixelOperations.Instance.ToGray8Bytes( - this.configuration, - inputPixelRow, - outputPixelRow, - image.Width); - stream.Write(outputPixelRow); + ReadOnlySpan inputPixelRow = image.GetPixelRowSpan(y); + ReadOnlySpan outputPixelRow = MemoryMarshal.AsBytes(inputPixelRow); + stream.Write(outputPixelRow); - for (int i = 0; i < this.padding; i++) - { - stream.WriteByte(0); - } + for (int i = 0; i < this.padding; i++) + { + stream.WriteByte(0); } } } From bb8911dd392fa58e8c30b5e1b78bb24383df8993 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Sun, 19 May 2019 21:28:39 +0200 Subject: [PATCH 205/223] Fix merge mistake: Using DrawImageTests from current master branch --- .../Drawing/DrawImageTests.cs | 228 +++++++++--------- 1 file changed, 116 insertions(+), 112 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index 0d0a82125..b2d499c7f 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -2,58 +2,37 @@ // Licensed under the Apache License, Version 2.0. using System; + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.Primitives; +using SixLabors.Shapes; + using Xunit; namespace SixLabors.ImageSharp.Tests.Drawing { [GroupOutput("Drawing")] - public class DrawImageTests : FileTestBase + public class DrawImageTests { - private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32; - - public static readonly string[] TestFiles = { - TestImages.Jpeg.Baseline.Calliphora, - TestImages.Bmp.Car, - TestImages.Png.Splash, - TestImages.Gif.Rings - }; - - [Theory] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Normal)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Multiply)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Add)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Subtract)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Screen)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Darken)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Lighten)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Overlay)] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.HardLight)] - public void ImageShouldApplyDrawImage(TestImageProvider provider, PixelColorBlendingMode mode) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - using (var blend = Image.Load(TestFile.Create(TestImages.Bmp.Car).Bytes)) + public static readonly TheoryData BlendingModes = new TheoryData { - blend.Mutate(x => x.Resize(image.Width / 2, image.Height / 2)); - image.Mutate(x => x.DrawImage(blend, new Point(image.Width / 4, image.Height / 4), mode, .75f)); - image.DebugSave(provider, new { mode }); - } - } + PixelColorBlendingMode.Normal, + PixelColorBlendingMode.Multiply, + PixelColorBlendingMode.Add, + PixelColorBlendingMode.Subtract, + PixelColorBlendingMode.Screen, + PixelColorBlendingMode.Darken, + PixelColorBlendingMode.Lighten, + PixelColorBlendingMode.Overlay, + PixelColorBlendingMode.HardLight, + }; [Theory] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Normal)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Multiply)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Add)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Subtract)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Screen)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Darken)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Lighten)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.Overlay)] - [WithFile(TestImages.Png.Rainbow, PixelTypes, PixelColorBlendingMode.HardLight)] + [WithFile(TestImages.Png.Rainbow, nameof(BlendingModes), PixelTypes.Rgba32)] public void ImageBlendingMatchesSvgSpecExamples(TestImageProvider provider, PixelColorBlendingMode mode) where TPixel : struct, IPixel { @@ -61,96 +40,139 @@ namespace SixLabors.ImageSharp.Tests.Drawing using (var source = Image.Load(TestFile.Create(TestImages.Png.Ducky).Bytes)) { background.Mutate(x => x.DrawImage(source, mode, 1F)); - VerifyImage(provider, mode, background); + background.DebugSave( + provider, + new { mode = mode }, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + + var comparer = ImageComparer.TolerantPercentage(0.01F); + background.CompareToReferenceOutput(comparer, + provider, + new { mode = mode }, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); } } [Theory] - [WithFileCollection(nameof(TestFiles), PixelTypes, PixelColorBlendingMode.Normal)] - public void ImageShouldDrawTransformedImage(TestImageProvider provider, PixelColorBlendingMode mode) + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 1f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Bgr24, TestImages.Png.Bike, PixelColorBlendingMode.Normal, 1f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 0.75f)] + [WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 0.25f)] + + [WithTestPatternImages(400, 400, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Multiply, 0.5f)] + [WithTestPatternImages(400, 400, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Add, 0.5f)] + [WithTestPatternImages(400, 400, PixelTypes.Rgba32, TestImages.Png.Splash, PixelColorBlendingMode.Subtract, 0.5f)] + + [WithFile(TestImages.Png.Rgb48Bpp, PixelTypes.Rgba64, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 1f)] + [WithFile(TestImages.Png.Rgb48Bpp, PixelTypes.Rgba64, TestImages.Png.Splash, PixelColorBlendingMode.Normal, 0.25f)] + public void WorksWithDifferentConfigurations( + TestImageProvider provider, + string brushImage, + PixelColorBlendingMode mode, + float opacity) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) - using (var blend = Image.Load(TestFile.Create(TestImages.Bmp.Car).Bytes)) + using (var blend = Image.Load(TestFile.Create(brushImage).Bytes)) { - AffineTransformBuilder builder = new AffineTransformBuilder() - .AppendRotationDegrees(45F) - .AppendScale(new SizeF(.25F, .25F)) - .AppendTranslation(new PointF(10, 10)); + Size size = new Size(image.Width * 3 / 4, image.Height * 3 / 4); + Point position = new Point(image.Width / 8, image.Height / 8); + blend.Mutate(x => x.Resize(size.Width, size.Height, KnownResamplers.Bicubic)); + image.Mutate(x => x.DrawImage(blend, position, mode, opacity)); + FormattableString testInfo = $"{System.IO.Path.GetFileNameWithoutExtension(brushImage)}-{mode}-{opacity}"; - // Apply a background color so we can see the translation. - blend.Mutate(x => x.Transform(builder)); - blend.Mutate(x => x.BackgroundColor(Color.HotPink)); + PngEncoder encoder = new PngEncoder(); - // Lets center the matrix so we can tell whether any cut-off issues we may have belong to the drawing processor - var position = new Point((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); - image.Mutate(x => x.DrawImage(blend, position, mode, .75F)); - image.DebugSave(provider, new[] { "Transformed" }); + if (provider.PixelType == PixelTypes.Rgba64) + { + encoder.BitDepth = PngBitDepth.Bit16; + } + + image.DebugSave(provider, testInfo, encoder: encoder); + image.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), + provider, + testInfo); } } [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] - public void ImageShouldHandleNegativeLocation(TestImageProvider provider) + [WithTestPatternImages(200, 200, PixelTypes.Rgba32 | PixelTypes.Bgra32)] + public void DrawImageOfDifferentPixelType(TestImageProvider provider) + where TPixel : struct, IPixel { - using (Image background = provider.GetImage()) - using (var overlay = new Image(50, 50)) - { - overlay.Mutate(x => x.Fill(Rgba32.Black)); - - const int xy = -25; - Rgba32 backgroundPixel = background[0, 0]; - Rgba32 overlayPixel = overlay[Math.Abs(xy) + 1, Math.Abs(xy) + 1]; + byte[] brushData = TestFile.Create(TestImages.Png.Ducky).Bytes; - background.Mutate(x => x.DrawImage(overlay, new Point(xy, xy), PixelColorBlendingMode.Normal, 1F)); - - Assert.Equal(Rgba32.White, backgroundPixel); - Assert.Equal(overlayPixel, background[0, 0]); + using (Image image = provider.GetImage()) + using (Image brushImage = provider.PixelType == PixelTypes.Rgba32 + ? (Image)Image.Load(brushData) + : Image.Load(brushData)) + { + image.Mutate(c => c.DrawImage(brushImage, 0.5f)); - background.DebugSave(provider, testOutputDetails: "Negative"); + image.DebugSave(provider, appendSourceFileOrDescription: false); + image.CompareToReferenceOutput( + ImageComparer.TolerantPercentage(0.01f), + provider, + appendSourceFileOrDescription: false); } } [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] - public void ImageShouldHandlePositiveLocation(TestImageProvider provider) + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 0, 0)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 25, 25)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 75, 50)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, -25, -30)] + public void WorksWithDifferentLocations(TestImageProvider provider, int x, int y) { using (Image background = provider.GetImage()) using (var overlay = new Image(50, 50)) { - overlay.Mutate(x => x.Fill(Rgba32.Black)); - - const int xy = 25; - Rgba32 backgroundPixel = background[xy - 1, xy - 1]; - Rgba32 overlayPixel = overlay[0, 0]; + overlay.Mutate(c => c.Fill(Rgba32.Black)); - background.Mutate(x => x.DrawImage(overlay, new Point(xy, xy), PixelColorBlendingMode.Normal, 1F)); + background.Mutate(c => c.DrawImage(overlay, new Point(x, y), PixelColorBlendingMode.Normal, 1F)); - Assert.Equal(Rgba32.White, backgroundPixel); - Assert.Equal(overlayPixel, background[xy, xy]); + background.DebugSave( + provider, + testOutputDetails: $"{x}_{y}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); - background.DebugSave(provider, testOutputDetails: "Positive"); + background.CompareToReferenceOutput( + provider, + testOutputDetails: $"{x}_{y}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); } } + [Theory] - [WithSolidFilledImages(100, 100, 255, 255, 255, PixelTypes.Rgba32)] - public void ImageShouldHandlePositiveLocationTruncatedOverlay(TestImageProvider provider) + [WithFile(TestImages.Png.Splash, PixelTypes.Rgba32)] + public void DrawTransformed(TestImageProvider provider) + where TPixel : struct, IPixel { - using (Image background = provider.GetImage()) - using (var overlay = new Image(50, 50)) + using (Image image = provider.GetImage()) + using (var blend = Image.Load(TestFile.Create(TestImages.Bmp.Car).Bytes)) { - overlay.Mutate(x => x.Fill(Rgba32.Black)); - - const int xy = 75; - Rgba32 backgroundPixel = background[xy - 1, xy - 1]; - Rgba32 overlayPixel = overlay[0, 0]; + AffineTransformBuilder builder = new AffineTransformBuilder() + .AppendRotationDegrees(45F) + .AppendScale(new SizeF(.25F, .25F)) + .AppendTranslation(new PointF(10, 10)); - background.Mutate(x => x.DrawImage(overlay, new Point(xy, xy), PixelColorBlendingMode.Normal, 1F)); + // Apply a background color so we can see the translation. + blend.Mutate(x => x.Transform(builder)); + blend.Mutate(x => x.BackgroundColor(Color.HotPink)); - Assert.Equal(Rgba32.White, backgroundPixel); - Assert.Equal(overlayPixel, background[xy, xy]); + // Lets center the matrix so we can tell whether any cut-off issues we may have belong to the drawing processor + var position = new Point((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); + image.Mutate(x => x.DrawImage(blend, position, .75F)); - background.DebugSave(provider, testOutputDetails: "PositiveTruncated"); + image.DebugSave(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); + image.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.002f), + provider, + appendSourceFileOrDescription: false, + appendPixelTypeToFileName: false); } } @@ -175,24 +197,6 @@ namespace SixLabors.ImageSharp.Tests.Drawing } } - private static void VerifyImage( - TestImageProvider provider, - PixelColorBlendingMode mode, - Image img) - where TPixel : struct, IPixel - { - img.DebugSave( - provider, - new { mode }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - - var comparer = ImageComparer.TolerantPercentage(0.01F, 3); - img.CompareFirstFrameToReferenceOutput(comparer, - provider, - new { mode }, - appendPixelTypeToFileName: false, - appendSourceFileOrDescription: false); - } + } } \ No newline at end of file From b00b949141495cda083fa6d527f2f373d66f8a0d Mon Sep 17 00:00:00 2001 From: Anton Firsov Date: Thu, 23 May 2019 13:00:48 +0200 Subject: [PATCH 206/223] API cleanup (related to #907) (#911) * temporarily disable target frameworks * drop DelegateProcessor * drop IImageProcessingContext * drop NamedColors * drop ColorBuilder * drop the *Base postfix for clean class hierarchies * re-enable target frameworks * use MathF in gradient brushes * Move PngFilterMethod to the correct namespace. --- .../Processing/EllipticGradientBrush.cs | 11 +- ...{GradientBrushBase.cs => GradientBrush.cs} | 10 +- .../Processing/LinearGradientBrush.cs | 8 +- .../Processing/RadialGradientBrush.cs | 8 +- src/ImageSharp/Color/Color.cs | 48 +- .../Conversion/ColorSpaceConverter.CieXyz.cs | 2 +- .../Conversion/ColorSpaceConverter.cs | 2 +- .../Conversion/ColorSpaceConverterOptions.cs | 2 +- .../Converters/CieXyzToLinearRgbConverter.cs | 4 +- .../LinearRgbAndCieXyzConverterBase.cs | 2 +- .../Converters/LinearRgbToCieXyzConverter.cs | 4 +- .../RGBPrimariesChromaticityCoordinates.cs | 2 +- .../WorkingSpaces/GammaWorkingSpace.cs | 2 +- .../WorkingSpaces/LWorkingSpace.cs | 2 +- .../WorkingSpaces/Rec2020WorkingSpace.cs | 2 +- .../WorkingSpaces/Rec709WorkingSpace.cs | 2 +- ...WorkingSpaceBase.cs => RgbWorkingSpace.cs} | 10 +- .../WorkingSpaces/SRgbWorkingSpace.cs | 2 +- src/ImageSharp/ColorSpaces/LinearRgb.cs | 10 +- src/ImageSharp/ColorSpaces/Rgb.cs | 10 +- .../ColorSpaces/RgbWorkingSpaces.cs | 38 +- .../Formats/{ => Png}/PngFilterMethod.cs | 2 +- .../PixelFormats/ColorBuilder{TPixel}.cs | 104 --- .../PixelFormats/NamedColors{TPixel}.cs | 761 ------------------ .../PixelImplementations/Rgba32.cs | 55 +- .../PixelImplementations/RgbaVector.cs | 2 +- ...ext.cs => DefaultImageProcessorContext.cs} | 14 +- .../Extensions/BinaryDiffuseExtensions.cs | 8 +- .../Extensions/BinaryDitherExtensions.cs | 8 +- .../Extensions/ProcessingExtensions.cs | 37 +- .../IImageProcessingContextFactory.cs | 2 +- .../IImageProcessingContext{TPixel}.cs | 46 -- .../IInternalImageProcessingContext.cs | 22 + .../Processors/DelegateProcessor.cs | 43 - .../Processors/Dithering/AtkinsonDiffuser.cs | 2 +- .../Processors/Dithering/BurksDiffuser.cs | 2 +- ...{ErrorDiffuserBase.cs => ErrorDiffuser.cs} | 6 +- .../Dithering/FloydSteinbergDiffuser.cs | 2 +- .../Dithering/JarvisJudiceNinkeDiffuser.cs | 2 +- .../Processors/Dithering/Sierra2Diffuser.cs | 2 +- .../Processors/Dithering/Sierra3Diffuser.cs | 2 +- .../Dithering/SierraLiteDiffuser.cs | 2 +- .../Dithering/StevensonArceDiffuser.cs | 2 +- .../Processors/Dithering/StuckiDiffuser.cs | 2 +- .../AffineTransformProcessor{TPixel}.cs | 2 +- .../Transforms/CropProcessor{TPixel}.cs | 2 +- .../ProjectiveTransformProcessor{TPixel}.cs | 2 +- .../Resize/ResizeProcessor{TPixel}.cs | 2 +- ...ProcessorBase.cs => TransformProcessor.cs} | 2 +- tests/ImageSharp.Benchmarks/Samplers/Glow.cs | 2 +- .../BaseImageOperationsExtensionTest.cs | 2 +- .../ApproximateColorspaceComparer.cs | 6 +- .../FakeImageOperationsProvider.cs | 21 +- .../Image/ImageProcessingContextTests.cs | 60 -- .../Image/ImageTests.WrapMemory.cs | 8 +- .../PixelFormats/ColorBuilderTests.cs | 40 - .../PixelFormats/ColorDefinitionTests.cs | 46 -- .../Processing/DelegateTest.cs | 25 - .../BasicTestPatternProvider.cs | 10 +- .../ImageProviders/TestPatternProvider.cs | 31 +- 60 files changed, 223 insertions(+), 1347 deletions(-) rename src/ImageSharp.Drawing/Processing/{GradientBrushBase.cs => GradientBrush.cs} (96%) rename src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/{RgbWorkingSpaceBase.cs => RgbWorkingSpace.cs} (91%) rename src/ImageSharp/Formats/{ => Png}/PngFilterMethod.cs (97%) delete mode 100644 src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs delete mode 100644 src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs rename src/ImageSharp/Processing/{DefaultInternalImageProcessorContext.cs => DefaultImageProcessorContext.cs} (85%) delete mode 100644 src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs create mode 100644 src/ImageSharp/Processing/IInternalImageProcessingContext.cs delete mode 100644 src/ImageSharp/Processing/Processors/DelegateProcessor.cs rename src/ImageSharp/Processing/Processors/Dithering/{ErrorDiffuserBase.cs => ErrorDiffuser.cs} (96%) rename src/ImageSharp/Processing/Processors/Transforms/{TransformProcessorBase.cs => TransformProcessor.cs} (89%) delete mode 100644 tests/ImageSharp.Tests/Image/ImageProcessingContextTests.cs delete mode 100644 tests/ImageSharp.Tests/PixelFormats/ColorBuilderTests.cs delete mode 100644 tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs delete mode 100644 tests/ImageSharp.Tests/Processing/DelegateTest.cs diff --git a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs index 4a8ce44db..91da332a1 100644 --- a/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Processing /// a point on the longest extension of the ellipse and /// the ratio between longest and shortest extension. /// - public sealed class EllipticGradientBrush : GradientBrushBase + public sealed class EllipticGradientBrush : GradientBrush { private readonly PointF center; @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Processing private readonly float axisRatio; - /// + /// /// The center of the elliptical gradient and 0 for the color stops. /// The end point of the reference axis of the ellipse. /// @@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.Processing this.RepetitionMode); /// - private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase + private sealed class RadialGradientBrushApplicator : GradientBrushApplicator where TPixel : struct, IPixel { private readonly PointF center; @@ -149,8 +149,7 @@ namespace SixLabors.ImageSharp.Processing { var vA = a - junction; var vB = b - junction; - return (float)(Math.Atan2(vB.Y, vB.X) - - Math.Atan2(vA.Y, vA.X)); + return MathF.Atan2(vB.Y, vB.X) - MathF.Atan2(vA.Y, vA.X); } private float DistanceBetween( @@ -162,7 +161,7 @@ namespace SixLabors.ImageSharp.Processing float dY = p1.Y - p2.Y; float dYsquared = dY * dY; - return (float)Math.Sqrt(dXsquared + dYsquared); + return MathF.Sqrt(dXsquared + dYsquared); } } } diff --git a/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs b/src/ImageSharp.Drawing/Processing/GradientBrush.cs similarity index 96% rename from src/ImageSharp.Drawing/Processing/GradientBrushBase.cs rename to src/ImageSharp.Drawing/Processing/GradientBrush.cs index 39dbcb61a..9826748c4 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrushBase.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrush.cs @@ -13,12 +13,12 @@ namespace SixLabors.ImageSharp.Processing /// /// Base class for Gradient brushes /// - public abstract class GradientBrushBase : IBrush + public abstract class GradientBrush : IBrush { /// /// Defines how the colors are repeated beyond the interval [0..1] /// The gradient colors. - protected GradientBrushBase( + protected GradientBrush( GradientRepetitionMode repetitionMode, params ColorStop[] colorStops) { @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Base class for gradient brush applicators /// - internal abstract class GradientBrushApplicatorBase : BrushApplicator + internal abstract class GradientBrushApplicator : BrushApplicator where TPixel : struct, IPixel { private static readonly TPixel Transparent = Color.Transparent.ToPixel(); @@ -56,13 +56,13 @@ namespace SixLabors.ImageSharp.Processing private readonly GradientRepetitionMode repetitionMode; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The target. /// The options. /// An array of color stops sorted by their position. /// Defines if and how the gradient should be repeated. - protected GradientBrushApplicatorBase( + protected GradientBrushApplicator( ImageFrame target, GraphicsOptions options, ColorStop[] colorStops, diff --git a/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs index 6eeadee5d..bb99eeb26 100644 --- a/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/LinearGradientBrush.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Processing /// Supported right now: /// - a set of colors in relative distances to each other. /// - public sealed class LinearGradientBrush : GradientBrushBase + public sealed class LinearGradientBrush : GradientBrush { private readonly PointF p1; @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The linear gradient brush applicator. /// - private sealed class LinearGradientBrushApplicator : GradientBrushApplicatorBase + private sealed class LinearGradientBrushApplicator : GradientBrushApplicator where TPixel : struct, IPixel { private readonly PointF start; @@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Processing // some helpers: this.alongsSquared = (this.alongX * this.alongX) + (this.alongY * this.alongY); - this.length = (float)Math.Sqrt(this.alongsSquared); + this.length = MathF.Sqrt(this.alongsSquared); } protected override float PositionOnGradient(float x, float y) @@ -145,7 +145,7 @@ namespace SixLabors.ImageSharp.Processing float y4 = y + (k * this.alongX); // get distance from (x4,y4) to start - float distance = (float)Math.Sqrt(Math.Pow(x4 - this.start.X, 2) + Math.Pow(y4 - this.start.Y, 2)); + float distance = MathF.Sqrt(MathF.Pow(x4 - this.start.X, 2) + MathF.Pow(y4 - this.start.Y, 2)); // get and return ratio float ratio = distance / this.length; diff --git a/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs index aac0f2e7b..f4d2dd81f 100644 --- a/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/RadialGradientBrush.cs @@ -11,13 +11,13 @@ namespace SixLabors.ImageSharp.Processing /// /// A Circular Gradient Brush, defined by center point and radius. /// - public sealed class RadialGradientBrush : GradientBrushBase + public sealed class RadialGradientBrush : GradientBrush { private readonly PointF center; private readonly float radius; - /// + /// /// The center of the circular gradient and 0 for the color stops. /// The radius of the circular gradient and 1 for the color stops. /// Defines how the colors in the gradient are repeated. @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Processing this.RepetitionMode); /// - private sealed class RadialGradientBrushApplicator : GradientBrushApplicatorBase + private sealed class RadialGradientBrushApplicator : GradientBrushApplicator where TPixel : struct, IPixel { private readonly PointF center; @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.Processing /// the position on the color gradient. protected override float PositionOnGradient(float x, float y) { - float distance = (float)Math.Sqrt(Math.Pow(this.center.X - x, 2) + Math.Pow(this.center.Y - y, 2)); + float distance = MathF.Sqrt(MathF.Pow(this.center.X - x, 2) + MathF.Pow(this.center.Y - y, 2)); return distance / this.radius; } diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index 0d94ac18c..2547e6d87 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -104,18 +104,11 @@ namespace SixLabors.ImageSharp /// in rgb, rgba, rrggbb, or rrggbbaa format to match web syntax. /// /// Returns a that represents the color defined by the provided RGBA hex string. + [MethodImpl(InliningOptions.ShortMethod)] public static Color FromHex(string hex) { - Guard.NotNullOrWhiteSpace(hex, nameof(hex)); - - hex = ToRgbaHex(hex); - - if (hex is null || !uint.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint packedValue)) - { - throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex)); - } + Rgba32 rgba = Rgba32.FromHex(hex); - var rgba = new Rgba32(BinaryPrimitives.ReverseEndianness(packedValue)); return new Color(rgba); } @@ -189,42 +182,5 @@ namespace SixLabors.ImageSharp ReadOnlySpan rgba64Span = MemoryMarshal.Cast(source); PixelOperations.Instance.FromRgba64(Configuration.Default, rgba64Span, destination); } - - /// - /// Converts the specified hex value to an rrggbbaa hex value. - /// - /// The hex value to convert. - /// - /// A rrggbbaa hex value. - /// - private static string ToRgbaHex(string hex) - { - if (hex[0] == '#') - { - hex = hex.Substring(1); - } - - if (hex.Length == 8) - { - return hex; - } - - if (hex.Length == 6) - { - return hex + "FF"; - } - - if (hex.Length < 3 || hex.Length > 4) - { - return null; - } - - char r = hex[0]; - char g = hex[1]; - char b = hex[2]; - char a = hex.Length == 3 ? 'F' : hex[3]; - - return new string(new[] { r, r, g, g, b, b, a, a }); - } } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs index 2cc8437bb..21d576fb4 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs @@ -465,7 +465,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The source working space /// The - private LinearRgbToCieXyzConverter GetLinearRgbToCieXyzConverter(RgbWorkingSpaceBase workingSpace) + private LinearRgbToCieXyzConverter GetLinearRgbToCieXyzConverter(RgbWorkingSpace workingSpace) { if (this.linearRgbToCieXyzConverter?.SourceWorkingSpace.Equals(workingSpace) == true) { diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs index fe6a57f7a..bcbd64c77 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion private readonly CieXyz targetLuvWhitePoint; private readonly CieXyz targetLabWhitePoint; private readonly CieXyz targetHunterLabWhitePoint; - private readonly RgbWorkingSpaceBase targetRgbWorkingSpace; + private readonly RgbWorkingSpace targetRgbWorkingSpace; private readonly IChromaticAdaptation chromaticAdaptation; private readonly bool performChromaticAdaptation; private readonly CieXyzAndLmsConverter cieXyzAndLmsConverter; diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs index fcd031e26..65fe79994 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// Gets or sets the target working space used *when creating* RGB colors. (RGB colors on the input already contain the working space information) /// Defaults to: . /// - public RgbWorkingSpaceBase TargetRgbWorkingSpace { get; set; } = Rgb.DefaultWorkingSpace; + public RgbWorkingSpace TargetRgbWorkingSpace { get; set; } = Rgb.DefaultWorkingSpace; /// /// Gets or sets the chromatic adaptation method used. When null, no adaptation will be performed. diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs index f166e4c14..6497e3060 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// Initializes a new instance of the class. /// /// The target working space. - public CieXyzToLinearRgbConverter(RgbWorkingSpaceBase workingSpace) + public CieXyzToLinearRgbConverter(RgbWorkingSpace workingSpace) { this.TargetWorkingSpace = workingSpace; @@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// /// Gets the target working space. /// - public RgbWorkingSpaceBase TargetWorkingSpace { get; } + public RgbWorkingSpace TargetWorkingSpace { get; } /// /// Performs the conversion from the input to an instance of type. diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs index a93773262..bdf451cd3 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// /// The Rgb working space. /// The based on the chromaticity and working space. - public static Matrix4x4 GetRgbToCieXyzMatrix(RgbWorkingSpaceBase workingSpace) + public static Matrix4x4 GetRgbToCieXyzMatrix(RgbWorkingSpace workingSpace) { DebugGuard.NotNull(workingSpace, nameof(workingSpace)); RgbPrimariesChromaticityCoordinates chromaticity = workingSpace.ChromaticityCoordinates; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs index 1030ac981..21a96071a 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// Initializes a new instance of the class. /// /// The target working space. - public LinearRgbToCieXyzConverter(RgbWorkingSpaceBase workingSpace) + public LinearRgbToCieXyzConverter(RgbWorkingSpace workingSpace) { this.SourceWorkingSpace = workingSpace; this.conversionMatrix = GetRgbToCieXyzMatrix(workingSpace); @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// /// Gets the source working space /// - public RgbWorkingSpaceBase SourceWorkingSpace { get; } + public RgbWorkingSpace SourceWorkingSpace { get; } /// /// Performs the conversion from the input to an instance of type. diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs index 4c69133e0..e28f3f1a4 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs @@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation { /// /// Represents the chromaticity coordinates of RGB primaries. - /// One of the specifiers of . + /// One of the specifiers of . /// public readonly struct RgbPrimariesChromaticityCoordinates : IEquatable { diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs index c45dea317..6caca54cd 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// /// The gamma working space. /// - public sealed class GammaWorkingSpace : RgbWorkingSpaceBase + public sealed class GammaWorkingSpace : RgbWorkingSpace { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs index 16617ea24..a2eb42ad0 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// /// L* working space. /// - public sealed class LWorkingSpace : RgbWorkingSpaceBase + public sealed class LWorkingSpace : RgbWorkingSpace { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs index 9ba1ff881..a794b3dda 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// /// Rec. 2020 (ITU-R Recommendation BT.2020F) working space. /// - public sealed class Rec2020WorkingSpace : RgbWorkingSpaceBase + public sealed class Rec2020WorkingSpace : RgbWorkingSpace { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs index 88623e958..ffa9699bc 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// /// Rec. 709 (ITU-R Recommendation BT.709) working space. /// - public sealed class Rec709WorkingSpace : RgbWorkingSpaceBase + public sealed class Rec709WorkingSpace : RgbWorkingSpace { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpaceBase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs similarity index 91% rename from src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpaceBase.cs rename to src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs index 6051f5286..a97ae22b1 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpaceBase.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs @@ -6,16 +6,16 @@ using System; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation { /// - /// Base class for all implementations of . + /// Base class for all implementations of . /// - public abstract class RgbWorkingSpaceBase + public abstract class RgbWorkingSpace { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The reference white point. /// The chromaticity of the rgb primaries. - protected RgbWorkingSpaceBase(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) + protected RgbWorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates) { this.WhitePoint = referenceWhite; this.ChromaticityCoordinates = chromaticityCoordinates; @@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation return true; } - if (obj is RgbWorkingSpaceBase other) + if (obj is RgbWorkingSpace other) { return this.WhitePoint.Equals(other.WhitePoint) && this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs index b44db0681..c3d850251 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// /// The sRgb working space. /// - public sealed class SRgbWorkingSpace : RgbWorkingSpaceBase + public sealed class SRgbWorkingSpace : RgbWorkingSpace { /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/ColorSpaces/LinearRgb.cs b/src/ImageSharp/ColorSpaces/LinearRgb.cs index 46b227596..7ef50e9c4 100644 --- a/src/ImageSharp/ColorSpaces/LinearRgb.cs +++ b/src/ImageSharp/ColorSpaces/LinearRgb.cs @@ -9,7 +9,7 @@ using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation; namespace SixLabors.ImageSharp.ColorSpaces { /// - /// Represents an linear Rgb color with specified working space + /// Represents an linear Rgb color with specified working space /// public readonly struct LinearRgb : IEquatable { @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// The default LinearRgb working space. /// - public static readonly RgbWorkingSpaceBase DefaultWorkingSpace = RgbWorkingSpaces.SRgb; + public static readonly RgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb; /// /// Gets the red component. @@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// Gets the LinearRgb color space /// - public readonly RgbWorkingSpaceBase WorkingSpace; + public readonly RgbWorkingSpace WorkingSpace; /// /// Initializes a new instance of the struct. @@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// The blue component ranging between 0 and 1. /// The rgb working space. [MethodImpl(InliningOptions.ShortMethod)] - public LinearRgb(float r, float g, float b, RgbWorkingSpaceBase workingSpace) + public LinearRgb(float r, float g, float b, RgbWorkingSpace workingSpace) : this(new Vector3(r, g, b), workingSpace) { } @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// The vector representing the r, g, b components. /// The LinearRgb working space. [MethodImpl(InliningOptions.ShortMethod)] - public LinearRgb(Vector3 vector, RgbWorkingSpaceBase workingSpace) + public LinearRgb(Vector3 vector, RgbWorkingSpace workingSpace) { // Clamp to 0-1 range. vector = Vector3.Clamp(vector, Min, Max); diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs index 5cb89a293..bb71deba3 100644 --- a/src/ImageSharp/ColorSpaces/Rgb.cs +++ b/src/ImageSharp/ColorSpaces/Rgb.cs @@ -10,14 +10,14 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.ColorSpaces { /// - /// Represents an RGB color with specified working space. + /// Represents an RGB color with specified working space. /// public readonly struct Rgb : IEquatable { /// /// The default rgb working space. /// - public static readonly RgbWorkingSpaceBase DefaultWorkingSpace = RgbWorkingSpaces.SRgb; + public static readonly RgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb; private static readonly Vector3 Min = Vector3.Zero; private static readonly Vector3 Max = Vector3.One; @@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// /// Gets the Rgb color space /// - public readonly RgbWorkingSpaceBase WorkingSpace; + public readonly RgbWorkingSpace WorkingSpace; /// /// Initializes a new instance of the struct. @@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// The blue component ranging between 0 and 1. /// The rgb working space. [MethodImpl(InliningOptions.ShortMethod)] - public Rgb(float r, float g, float b, RgbWorkingSpaceBase workingSpace) + public Rgb(float r, float g, float b, RgbWorkingSpace workingSpace) : this(new Vector3(r, g, b), workingSpace) { } @@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// The vector representing the r, g, b components. /// The rgb working space. [MethodImpl(InliningOptions.ShortMethod)] - public Rgb(Vector3 vector, RgbWorkingSpaceBase workingSpace) + public Rgb(Vector3 vector, RgbWorkingSpace workingSpace) { vector = Vector3.Clamp(vector, Min, Max); this.R = vector.X; diff --git a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs index 7ddcae7ce..3f40fa4f5 100644 --- a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs +++ b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs @@ -19,97 +19,97 @@ namespace SixLabors.ImageSharp.ColorSpaces /// Uses proper companding function, according to: /// /// - public static readonly RgbWorkingSpaceBase SRgb = new SRgbWorkingSpace(Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly RgbWorkingSpace SRgb = new SRgbWorkingSpace(Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// Simplified sRgb working space (uses gamma companding instead of ). /// See also . /// - public static readonly RgbWorkingSpaceBase SRgbSimplified = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly RgbWorkingSpace SRgbSimplified = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// Rec. 709 (ITU-R Recommendation BT.709) working space. /// - public static readonly RgbWorkingSpaceBase Rec709 = new Rec709WorkingSpace(Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.64F, 0.33F), new CieXyChromaticityCoordinates(0.30F, 0.60F), new CieXyChromaticityCoordinates(0.15F, 0.06F))); + public static readonly RgbWorkingSpace Rec709 = new Rec709WorkingSpace(Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.64F, 0.33F), new CieXyChromaticityCoordinates(0.30F, 0.60F), new CieXyChromaticityCoordinates(0.15F, 0.06F))); /// /// Rec. 2020 (ITU-R Recommendation BT.2020F) working space. /// - public static readonly RgbWorkingSpaceBase Rec2020 = new Rec2020WorkingSpace(Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.708F, 0.292F), new CieXyChromaticityCoordinates(0.170F, 0.797F), new CieXyChromaticityCoordinates(0.131F, 0.046F))); + public static readonly RgbWorkingSpace Rec2020 = new Rec2020WorkingSpace(Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.708F, 0.292F), new CieXyChromaticityCoordinates(0.170F, 0.797F), new CieXyChromaticityCoordinates(0.131F, 0.046F))); /// /// ECI Rgb v2 working space. /// - public static readonly RgbWorkingSpaceBase ECIRgbv2 = new LWorkingSpace(Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); + public static readonly RgbWorkingSpace ECIRgbv2 = new LWorkingSpace(Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); /// /// Adobe Rgb (1998) working space. /// - public static readonly RgbWorkingSpaceBase AdobeRgb1998 = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly RgbWorkingSpace AdobeRgb1998 = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// Apple sRgb working space. /// - public static readonly RgbWorkingSpaceBase ApplesRgb = new GammaWorkingSpace(1.8F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6250F, 0.3400F), new CieXyChromaticityCoordinates(0.2800F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); + public static readonly RgbWorkingSpace ApplesRgb = new GammaWorkingSpace(1.8F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6250F, 0.3400F), new CieXyChromaticityCoordinates(0.2800F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); /// /// Best Rgb working space. /// - public static readonly RgbWorkingSpaceBase BestRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.2150F, 0.7750F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); + public static readonly RgbWorkingSpace BestRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.2150F, 0.7750F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); /// /// Beta Rgb working space. /// - public static readonly RgbWorkingSpaceBase BetaRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6888F, 0.3112F), new CieXyChromaticityCoordinates(0.1986F, 0.7551F), new CieXyChromaticityCoordinates(0.1265F, 0.0352F))); + public static readonly RgbWorkingSpace BetaRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6888F, 0.3112F), new CieXyChromaticityCoordinates(0.1986F, 0.7551F), new CieXyChromaticityCoordinates(0.1265F, 0.0352F))); /// /// Bruce Rgb working space. /// - public static readonly RgbWorkingSpaceBase BruceRgb = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2800F, 0.6500F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly RgbWorkingSpace BruceRgb = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2800F, 0.6500F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// CIE Rgb working space. /// - public static readonly RgbWorkingSpaceBase CIERgb = new GammaWorkingSpace(2.2F, Illuminants.E, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.2740F, 0.7170F), new CieXyChromaticityCoordinates(0.1670F, 0.0090F))); + public static readonly RgbWorkingSpace CIERgb = new GammaWorkingSpace(2.2F, Illuminants.E, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.2740F, 0.7170F), new CieXyChromaticityCoordinates(0.1670F, 0.0090F))); /// /// ColorMatch Rgb working space. /// - public static readonly RgbWorkingSpaceBase ColorMatchRgb = new GammaWorkingSpace(1.8F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.2950F, 0.6050F), new CieXyChromaticityCoordinates(0.1500F, 0.0750F))); + public static readonly RgbWorkingSpace ColorMatchRgb = new GammaWorkingSpace(1.8F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.2950F, 0.6050F), new CieXyChromaticityCoordinates(0.1500F, 0.0750F))); /// /// Don Rgb 4 working space. /// - public static readonly RgbWorkingSpaceBase DonRgb4 = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6960F, 0.3000F), new CieXyChromaticityCoordinates(0.2150F, 0.7650F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); + public static readonly RgbWorkingSpace DonRgb4 = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6960F, 0.3000F), new CieXyChromaticityCoordinates(0.2150F, 0.7650F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F))); /// /// Ekta Space PS5 working space. /// - public static readonly RgbWorkingSpaceBase EktaSpacePS5 = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6950F, 0.3050F), new CieXyChromaticityCoordinates(0.2600F, 0.7000F), new CieXyChromaticityCoordinates(0.1100F, 0.0050F))); + public static readonly RgbWorkingSpace EktaSpacePS5 = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6950F, 0.3050F), new CieXyChromaticityCoordinates(0.2600F, 0.7000F), new CieXyChromaticityCoordinates(0.1100F, 0.0050F))); /// /// NTSC Rgb working space. /// - public static readonly RgbWorkingSpaceBase NTSCRgb = new GammaWorkingSpace(2.2F, Illuminants.C, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); + public static readonly RgbWorkingSpace NTSCRgb = new GammaWorkingSpace(2.2F, Illuminants.C, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F))); /// /// PAL/SECAM Rgb working space. /// - public static readonly RgbWorkingSpaceBase PALSECAMRgb = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2900F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); + public static readonly RgbWorkingSpace PALSECAMRgb = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2900F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F))); /// /// ProPhoto Rgb working space. /// - public static readonly RgbWorkingSpaceBase ProPhotoRgb = new GammaWorkingSpace(1.8F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.1596F, 0.8404F), new CieXyChromaticityCoordinates(0.0366F, 0.0001F))); + public static readonly RgbWorkingSpace ProPhotoRgb = new GammaWorkingSpace(1.8F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.1596F, 0.8404F), new CieXyChromaticityCoordinates(0.0366F, 0.0001F))); /// /// SMPTE-C Rgb working space. /// - public static readonly RgbWorkingSpaceBase SMPTECRgb = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.3100F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); + public static readonly RgbWorkingSpace SMPTECRgb = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.3100F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F))); /// /// Wide Gamut Rgb working space. /// - public static readonly RgbWorkingSpaceBase WideGamutRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F))); + public static readonly RgbWorkingSpace WideGamutRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F))); } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/PngFilterMethod.cs b/src/ImageSharp/Formats/Png/PngFilterMethod.cs similarity index 97% rename from src/ImageSharp/Formats/PngFilterMethod.cs rename to src/ImageSharp/Formats/Png/PngFilterMethod.cs index 73c405625..e16c1234f 100644 --- a/src/ImageSharp/Formats/PngFilterMethod.cs +++ b/src/ImageSharp/Formats/Png/PngFilterMethod.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -namespace SixLabors.ImageSharp.Formats +namespace SixLabors.ImageSharp.Formats.Png { /// /// Provides enumeration of available PNG filter methods. diff --git a/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs b/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs deleted file mode 100644 index c1fb13e4d..000000000 --- a/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers.Binary; -using System.Globalization; - -namespace SixLabors.ImageSharp.PixelFormats -{ - /// - /// A set of named colors mapped to the provided Color space. - /// - /// The type of the color. - public static class ColorBuilder - where TPixel : struct, IPixel - { - /// - /// Creates a new representation from the string representing a color. - /// - /// - /// The hexadecimal representation of the combined color components arranged - /// in rgb, rgba, rrggbb, or rrggbbaa format to match web syntax. - /// - /// Returns a that represents the color defined by the provided RGBA hex string. - public static TPixel FromHex(string hex) - { - Guard.NotNullOrWhiteSpace(hex, nameof(hex)); - - hex = ToRgbaHex(hex); - - if (hex is null || !uint.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint packedValue)) - { - throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex)); - } - - TPixel result = default; - var rgba = new Rgba32(BinaryPrimitives.ReverseEndianness(packedValue)); - - result.FromRgba32(rgba); - return result; - } - - /// - /// Creates a new representation from standard RGB bytes with 100% opacity. - /// - /// The red intensity. - /// The green intensity. - /// The blue intensity. - /// Returns a that represents the color defined by the provided RGB values with 100% opacity. - public static TPixel FromRgb(byte red, byte green, byte blue) => FromRgba(red, green, blue, 255); - - /// - /// Creates a new representation from standard RGBA bytes. - /// - /// The red intensity. - /// The green intensity. - /// The blue intensity. - /// The alpha intensity. - /// Returns a that represents the color defined by the provided RGBA values. - public static TPixel FromRgba(byte red, byte green, byte blue, byte alpha) - { - TPixel color = default; - color.FromRgba32(new Rgba32(red, green, blue, alpha)); - return color; - } - - /// - /// Converts the specified hex value to an rrggbbaa hex value. - /// - /// The hex value to convert. - /// - /// A rrggbbaa hex value. - /// - private static string ToRgbaHex(string hex) - { - if (hex[0] == '#') - { - hex = hex.Substring(1); - } - - if (hex.Length == 8) - { - return hex; - } - - if (hex.Length == 6) - { - return hex + "FF"; - } - - if (hex.Length < 3 || hex.Length > 4) - { - return null; - } - - char r = hex[0]; - char g = hex[1]; - char b = hex[2]; - char a = hex.Length == 3 ? 'F' : hex[3]; - - return new string(new[] { r, r, g, g, b, b, a, a }); - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs b/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs deleted file mode 100644 index 2138e2e2f..000000000 --- a/src/ImageSharp/PixelFormats/NamedColors{TPixel}.cs +++ /dev/null @@ -1,761 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Runtime.InteropServices; - -namespace SixLabors.ImageSharp.PixelFormats -{ - /// - /// A set of named colors mapped to the provided color space. - /// - /// The type of the color. - public static class NamedColors - where TPixel : struct, IPixel - { - /// - /// Thread-safe backing field for the constant palettes. - /// - private static readonly Lazy WebSafePaletteLazy = new Lazy(GetWebSafePalette, true); - private static readonly Lazy WernerPaletteLazy = new Lazy(GetWernerPalette, true); - - /// - /// Represents a matching the W3C definition that has an hex value of #F0F8FF. - /// - public static readonly TPixel AliceBlue = ColorBuilder.FromRgba(240, 248, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FAEBD7. - /// - public static readonly TPixel AntiqueWhite = ColorBuilder.FromRgba(250, 235, 215, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00FFFF. - /// - public static readonly TPixel Aqua = ColorBuilder.FromRgba(0, 255, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #7FFFD4. - /// - public static readonly TPixel Aquamarine = ColorBuilder.FromRgba(127, 255, 212, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F0FFFF. - /// - public static readonly TPixel Azure = ColorBuilder.FromRgba(240, 255, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F5F5DC. - /// - public static readonly TPixel Beige = ColorBuilder.FromRgba(245, 245, 220, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFE4C4. - /// - public static readonly TPixel Bisque = ColorBuilder.FromRgba(255, 228, 196, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #000000. - /// - public static readonly TPixel Black = ColorBuilder.FromRgba(0, 0, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFEBCD. - /// - public static readonly TPixel BlanchedAlmond = ColorBuilder.FromRgba(255, 235, 205, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #0000FF. - /// - public static readonly TPixel Blue = ColorBuilder.FromRgba(0, 0, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #8A2BE2. - /// - public static readonly TPixel BlueViolet = ColorBuilder.FromRgba(138, 43, 226, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #A52A2A. - /// - public static readonly TPixel Brown = ColorBuilder.FromRgba(165, 42, 42, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DEB887. - /// - public static readonly TPixel BurlyWood = ColorBuilder.FromRgba(222, 184, 135, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #5F9EA0. - /// - public static readonly TPixel CadetBlue = ColorBuilder.FromRgba(95, 158, 160, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #7FFF00. - /// - public static readonly TPixel Chartreuse = ColorBuilder.FromRgba(127, 255, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #D2691E. - /// - public static readonly TPixel Chocolate = ColorBuilder.FromRgba(210, 105, 30, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF7F50. - /// - public static readonly TPixel Coral = ColorBuilder.FromRgba(255, 127, 80, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #6495ED. - /// - public static readonly TPixel CornflowerBlue = ColorBuilder.FromRgba(100, 149, 237, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFF8DC. - /// - public static readonly TPixel Cornsilk = ColorBuilder.FromRgba(255, 248, 220, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DC143C. - /// - public static readonly TPixel Crimson = ColorBuilder.FromRgba(220, 20, 60, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00FFFF. - /// - public static readonly TPixel Cyan = ColorBuilder.FromRgba(0, 255, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00008B. - /// - public static readonly TPixel DarkBlue = ColorBuilder.FromRgba(0, 0, 139, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #008B8B. - /// - public static readonly TPixel DarkCyan = ColorBuilder.FromRgba(0, 139, 139, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #B8860B. - /// - public static readonly TPixel DarkGoldenrod = ColorBuilder.FromRgba(184, 134, 11, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #A9A9A9. - /// - public static readonly TPixel DarkGray = ColorBuilder.FromRgba(169, 169, 169, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #006400. - /// - public static readonly TPixel DarkGreen = ColorBuilder.FromRgba(0, 100, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #BDB76B. - /// - public static readonly TPixel DarkKhaki = ColorBuilder.FromRgba(189, 183, 107, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #8B008B. - /// - public static readonly TPixel DarkMagenta = ColorBuilder.FromRgba(139, 0, 139, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #556B2F. - /// - public static readonly TPixel DarkOliveGreen = ColorBuilder.FromRgba(85, 107, 47, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF8C00. - /// - public static readonly TPixel DarkOrange = ColorBuilder.FromRgba(255, 140, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #9932CC. - /// - public static readonly TPixel DarkOrchid = ColorBuilder.FromRgba(153, 50, 204, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #8B0000. - /// - public static readonly TPixel DarkRed = ColorBuilder.FromRgba(139, 0, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #E9967A. - /// - public static readonly TPixel DarkSalmon = ColorBuilder.FromRgba(233, 150, 122, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #8FBC8B. - /// - public static readonly TPixel DarkSeaGreen = ColorBuilder.FromRgba(143, 188, 139, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #483D8B. - /// - public static readonly TPixel DarkSlateBlue = ColorBuilder.FromRgba(72, 61, 139, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #2F4F4F. - /// - public static readonly TPixel DarkSlateGray = ColorBuilder.FromRgba(47, 79, 79, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00CED1. - /// - public static readonly TPixel DarkTurquoise = ColorBuilder.FromRgba(0, 206, 209, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #9400D3. - /// - public static readonly TPixel DarkViolet = ColorBuilder.FromRgba(148, 0, 211, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF1493. - /// - public static readonly TPixel DeepPink = ColorBuilder.FromRgba(255, 20, 147, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00BFFF. - /// - public static readonly TPixel DeepSkyBlue = ColorBuilder.FromRgba(0, 191, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #696969. - /// - public static readonly TPixel DimGray = ColorBuilder.FromRgba(105, 105, 105, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #1E90FF. - /// - public static readonly TPixel DodgerBlue = ColorBuilder.FromRgba(30, 144, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #B22222. - /// - public static readonly TPixel Firebrick = ColorBuilder.FromRgba(178, 34, 34, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFAF0. - /// - public static readonly TPixel FloralWhite = ColorBuilder.FromRgba(255, 250, 240, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #228B22. - /// - public static readonly TPixel ForestGreen = ColorBuilder.FromRgba(34, 139, 34, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF00FF. - /// - public static readonly TPixel Fuchsia = ColorBuilder.FromRgba(255, 0, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DCDCDC. - /// - public static readonly TPixel Gainsboro = ColorBuilder.FromRgba(220, 220, 220, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F8F8FF. - /// - public static readonly TPixel GhostWhite = ColorBuilder.FromRgba(248, 248, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFD700. - /// - public static readonly TPixel Gold = ColorBuilder.FromRgba(255, 215, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DAA520. - /// - public static readonly TPixel Goldenrod = ColorBuilder.FromRgba(218, 165, 32, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #808080. - /// - public static readonly TPixel Gray = ColorBuilder.FromRgba(128, 128, 128, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #008000. - /// - public static readonly TPixel Green = ColorBuilder.FromRgba(0, 128, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #ADFF2F. - /// - public static readonly TPixel GreenYellow = ColorBuilder.FromRgba(173, 255, 47, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F0FFF0. - /// - public static readonly TPixel Honeydew = ColorBuilder.FromRgba(240, 255, 240, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF69B4. - /// - public static readonly TPixel HotPink = ColorBuilder.FromRgba(255, 105, 180, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #CD5C5C. - /// - public static readonly TPixel IndianRed = ColorBuilder.FromRgba(205, 92, 92, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #4B0082. - /// - public static readonly TPixel Indigo = ColorBuilder.FromRgba(75, 0, 130, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFFF0. - /// - public static readonly TPixel Ivory = ColorBuilder.FromRgba(255, 255, 240, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F0E68C. - /// - public static readonly TPixel Khaki = ColorBuilder.FromRgba(240, 230, 140, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #E6E6FA. - /// - public static readonly TPixel Lavender = ColorBuilder.FromRgba(230, 230, 250, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFF0F5. - /// - public static readonly TPixel LavenderBlush = ColorBuilder.FromRgba(255, 240, 245, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #7CFC00. - /// - public static readonly TPixel LawnGreen = ColorBuilder.FromRgba(124, 252, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFACD. - /// - public static readonly TPixel LemonChiffon = ColorBuilder.FromRgba(255, 250, 205, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #ADD8E6. - /// - public static readonly TPixel LightBlue = ColorBuilder.FromRgba(173, 216, 230, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F08080. - /// - public static readonly TPixel LightCoral = ColorBuilder.FromRgba(240, 128, 128, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #E0FFFF. - /// - public static readonly TPixel LightCyan = ColorBuilder.FromRgba(224, 255, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FAFAD2. - /// - public static readonly TPixel LightGoldenrodYellow = ColorBuilder.FromRgba(250, 250, 210, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #D3D3D3. - /// - public static readonly TPixel LightGray = ColorBuilder.FromRgba(211, 211, 211, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #90EE90. - /// - public static readonly TPixel LightGreen = ColorBuilder.FromRgba(144, 238, 144, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFB6C1. - /// - public static readonly TPixel LightPink = ColorBuilder.FromRgba(255, 182, 193, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFA07A. - /// - public static readonly TPixel LightSalmon = ColorBuilder.FromRgba(255, 160, 122, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #20B2AA. - /// - public static readonly TPixel LightSeaGreen = ColorBuilder.FromRgba(32, 178, 170, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #87CEFA. - /// - public static readonly TPixel LightSkyBlue = ColorBuilder.FromRgba(135, 206, 250, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #778899. - /// - public static readonly TPixel LightSlateGray = ColorBuilder.FromRgba(119, 136, 153, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #B0C4DE. - /// - public static readonly TPixel LightSteelBlue = ColorBuilder.FromRgba(176, 196, 222, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFFE0. - /// - public static readonly TPixel LightYellow = ColorBuilder.FromRgba(255, 255, 224, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00FF00. - /// - public static readonly TPixel Lime = ColorBuilder.FromRgba(0, 255, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #32CD32. - /// - public static readonly TPixel LimeGreen = ColorBuilder.FromRgba(50, 205, 50, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FAF0E6. - /// - public static readonly TPixel Linen = ColorBuilder.FromRgba(250, 240, 230, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF00FF. - /// - public static readonly TPixel Magenta = ColorBuilder.FromRgba(255, 0, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #800000. - /// - public static readonly TPixel Maroon = ColorBuilder.FromRgba(128, 0, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #66CDAA. - /// - public static readonly TPixel MediumAquamarine = ColorBuilder.FromRgba(102, 205, 170, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #0000CD. - /// - public static readonly TPixel MediumBlue = ColorBuilder.FromRgba(0, 0, 205, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #BA55D3. - /// - public static readonly TPixel MediumOrchid = ColorBuilder.FromRgba(186, 85, 211, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #9370DB. - /// - public static readonly TPixel MediumPurple = ColorBuilder.FromRgba(147, 112, 219, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #3CB371. - /// - public static readonly TPixel MediumSeaGreen = ColorBuilder.FromRgba(60, 179, 113, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #7B68EE. - /// - public static readonly TPixel MediumSlateBlue = ColorBuilder.FromRgba(123, 104, 238, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00FA9A. - /// - public static readonly TPixel MediumSpringGreen = ColorBuilder.FromRgba(0, 250, 154, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #48D1CC. - /// - public static readonly TPixel MediumTurquoise = ColorBuilder.FromRgba(72, 209, 204, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #C71585. - /// - public static readonly TPixel MediumVioletRed = ColorBuilder.FromRgba(199, 21, 133, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #191970. - /// - public static readonly TPixel MidnightBlue = ColorBuilder.FromRgba(25, 25, 112, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F5FFFA. - /// - public static readonly TPixel MintCream = ColorBuilder.FromRgba(245, 255, 250, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFE4E1. - /// - public static readonly TPixel MistyRose = ColorBuilder.FromRgba(255, 228, 225, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFE4B5. - /// - public static readonly TPixel Moccasin = ColorBuilder.FromRgba(255, 228, 181, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFDEAD. - /// - public static readonly TPixel NavajoWhite = ColorBuilder.FromRgba(255, 222, 173, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #000080. - /// - public static readonly TPixel Navy = ColorBuilder.FromRgba(0, 0, 128, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FDF5E6. - /// - public static readonly TPixel OldLace = ColorBuilder.FromRgba(253, 245, 230, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #808000. - /// - public static readonly TPixel Olive = ColorBuilder.FromRgba(128, 128, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #6B8E23. - /// - public static readonly TPixel OliveDrab = ColorBuilder.FromRgba(107, 142, 35, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFA500. - /// - public static readonly TPixel Orange = ColorBuilder.FromRgba(255, 165, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF4500. - /// - public static readonly TPixel OrangeRed = ColorBuilder.FromRgba(255, 69, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DA70D6. - /// - public static readonly TPixel Orchid = ColorBuilder.FromRgba(218, 112, 214, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #EEE8AA. - /// - public static readonly TPixel PaleGoldenrod = ColorBuilder.FromRgba(238, 232, 170, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #98FB98. - /// - public static readonly TPixel PaleGreen = ColorBuilder.FromRgba(152, 251, 152, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #AFEEEE. - /// - public static readonly TPixel PaleTurquoise = ColorBuilder.FromRgba(175, 238, 238, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DB7093. - /// - public static readonly TPixel PaleVioletRed = ColorBuilder.FromRgba(219, 112, 147, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFEFD5. - /// - public static readonly TPixel PapayaWhip = ColorBuilder.FromRgba(255, 239, 213, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFDAB9. - /// - public static readonly TPixel PeachPuff = ColorBuilder.FromRgba(255, 218, 185, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #CD853F. - /// - public static readonly TPixel Peru = ColorBuilder.FromRgba(205, 133, 63, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFC0CB. - /// - public static readonly TPixel Pink = ColorBuilder.FromRgba(255, 192, 203, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #DDA0DD. - /// - public static readonly TPixel Plum = ColorBuilder.FromRgba(221, 160, 221, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #B0E0E6. - /// - public static readonly TPixel PowderBlue = ColorBuilder.FromRgba(176, 224, 230, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #800080. - /// - public static readonly TPixel Purple = ColorBuilder.FromRgba(128, 0, 128, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #663399. - /// - public static readonly TPixel RebeccaPurple = ColorBuilder.FromRgba(102, 51, 153, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF0000. - /// - public static readonly TPixel Red = ColorBuilder.FromRgba(255, 0, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #BC8F8F. - /// - public static readonly TPixel RosyBrown = ColorBuilder.FromRgba(188, 143, 143, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #4169E1. - /// - public static readonly TPixel RoyalBlue = ColorBuilder.FromRgba(65, 105, 225, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #8B4513. - /// - public static readonly TPixel SaddleBrown = ColorBuilder.FromRgba(139, 69, 19, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FA8072. - /// - public static readonly TPixel Salmon = ColorBuilder.FromRgba(250, 128, 114, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F4A460. - /// - public static readonly TPixel SandyBrown = ColorBuilder.FromRgba(244, 164, 96, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #2E8B57. - /// - public static readonly TPixel SeaGreen = ColorBuilder.FromRgba(46, 139, 87, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFF5EE. - /// - public static readonly TPixel SeaShell = ColorBuilder.FromRgba(255, 245, 238, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #A0522D. - /// - public static readonly TPixel Sienna = ColorBuilder.FromRgba(160, 82, 45, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #C0C0C0. - /// - public static readonly TPixel Silver = ColorBuilder.FromRgba(192, 192, 192, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #87CEEB. - /// - public static readonly TPixel SkyBlue = ColorBuilder.FromRgba(135, 206, 235, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #6A5ACD. - /// - public static readonly TPixel SlateBlue = ColorBuilder.FromRgba(106, 90, 205, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #708090. - /// - public static readonly TPixel SlateGray = ColorBuilder.FromRgba(112, 128, 144, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFAFA. - /// - public static readonly TPixel Snow = ColorBuilder.FromRgba(255, 250, 250, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #00FF7F. - /// - public static readonly TPixel SpringGreen = ColorBuilder.FromRgba(0, 255, 127, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #4682B4. - /// - public static readonly TPixel SteelBlue = ColorBuilder.FromRgba(70, 130, 180, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #D2B48C. - /// - public static readonly TPixel Tan = ColorBuilder.FromRgba(210, 180, 140, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #008080. - /// - public static readonly TPixel Teal = ColorBuilder.FromRgba(0, 128, 128, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #D8BFD8. - /// - public static readonly TPixel Thistle = ColorBuilder.FromRgba(216, 191, 216, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FF6347. - /// - public static readonly TPixel Tomato = ColorBuilder.FromRgba(255, 99, 71, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFFFF. - /// - public static readonly TPixel Transparent = ColorBuilder.FromRgba(255, 255, 255, 0); - - /// - /// Represents a matching the W3C definition that has an hex value of #40E0D0. - /// - public static readonly TPixel Turquoise = ColorBuilder.FromRgba(64, 224, 208, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #EE82EE. - /// - public static readonly TPixel Violet = ColorBuilder.FromRgba(238, 130, 238, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F5DEB3. - /// - public static readonly TPixel Wheat = ColorBuilder.FromRgba(245, 222, 179, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFFFF. - /// - public static readonly TPixel White = ColorBuilder.FromRgba(255, 255, 255, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #F5F5F5. - /// - public static readonly TPixel WhiteSmoke = ColorBuilder.FromRgba(245, 245, 245, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #FFFF00. - /// - public static readonly TPixel Yellow = ColorBuilder.FromRgba(255, 255, 0, 255); - - /// - /// Represents a matching the W3C definition that has an hex value of #9ACD32. - /// - public static readonly TPixel YellowGreen = ColorBuilder.FromRgba(154, 205, 50, 255); - - /// - /// Gets a collection of web safe, colors as defined in the CSS Color Module Level 4. - /// - public static TPixel[] WebSafePalette => WebSafePaletteLazy.Value; - - /// - /// Gets a collection of colors as defined in the original second edition of Werner’s Nomenclature of Colours 1821. - /// The hex codes were collected and defined by Nicholas Rougeux - /// - public static TPixel[] WernerPalette => WernerPaletteLazy.Value; - - private static TPixel[] GetWebSafePalette() => GetPalette(ColorConstants.WebSafeColors); - - private static TPixel[] GetWernerPalette() => GetPalette(ColorConstants.WernerColors); - - private static TPixel[] GetPalette(Rgba32[] palette) - { - var converted = new TPixel[palette.Length]; - - Span constantsBytes = MemoryMarshal.Cast(palette.AsSpan()); - PixelOperations.Instance.FromRgba32Bytes( - Configuration.Default, - constantsBytes, - converted, - palette.Length); - - return converted; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs index c58d17ef4..b439ef32c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs @@ -1,6 +1,9 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; +using System.Buffers.Binary; +using System.Globalization; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -233,7 +236,20 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// The . /// - public static Rgba32 FromHex(string hex) => ColorBuilder.FromHex(hex); + public static Rgba32 FromHex(string hex) + { + Guard.NotNullOrWhiteSpace(hex, nameof(hex)); + + hex = ToRgbaHex(hex); + + if (hex is null || !uint.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint packedValue)) + { + throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex)); + } + + packedValue = BinaryPrimitives.ReverseEndianness(packedValue); + return Unsafe.As(ref packedValue); + } /// public PixelOperations CreatePixelOperations() => new PixelOperations(); @@ -426,5 +442,42 @@ namespace SixLabors.ImageSharp.PixelFormats this.B = (byte)vector.Z; this.A = (byte)vector.W; } + + /// + /// Converts the specified hex value to an rrggbbaa hex value. + /// + /// The hex value to convert. + /// + /// A rrggbbaa hex value. + /// + private static string ToRgbaHex(string hex) + { + if (hex[0] == '#') + { + hex = hex.Substring(1); + } + + if (hex.Length == 8) + { + return hex; + } + + if (hex.Length == 6) + { + return hex + "FF"; + } + + if (hex.Length < 3 || hex.Length > 4) + { + return null; + } + + char r = hex[0]; + char g = hex[1]; + char b = hex[2]; + char a = hex.Length == 3 ? 'F' : hex[3]; + + return new string(new[] { r, r, g, g, b, b, a, a }); + } } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs index 96003cc5b..38e75d183 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs @@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// The . /// - public static RgbaVector FromHex(string hex) => ColorBuilder.FromHex(hex); + public static RgbaVector FromHex(string hex) => Color.FromHex(hex).ToPixel(); /// public PixelOperations CreatePixelOperations() => new PixelOperations(); diff --git a/src/ImageSharp/Processing/DefaultInternalImageProcessorContext.cs b/src/ImageSharp/Processing/DefaultImageProcessorContext.cs similarity index 85% rename from src/ImageSharp/Processing/DefaultInternalImageProcessorContext.cs rename to src/ImageSharp/Processing/DefaultImageProcessorContext.cs index 091da003a..d0c4c076f 100644 --- a/src/ImageSharp/Processing/DefaultInternalImageProcessorContext.cs +++ b/src/ImageSharp/Processing/DefaultImageProcessorContext.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Processing /// Performs processor application operations on the source image /// /// The pixel format - internal class DefaultInternalImageProcessorContext : IInternalImageProcessingContext + internal class DefaultImageProcessorContext : IInternalImageProcessingContext where TPixel : struct, IPixel { private readonly bool mutate; @@ -21,11 +21,11 @@ namespace SixLabors.ImageSharp.Processing private Image destination; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The image. /// The mutate. - public DefaultInternalImageProcessorContext(Image source, bool mutate) + public DefaultImageProcessorContext(Image source, bool mutate) { this.mutate = mutate; this.source = source; @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Processing public MemoryAllocator MemoryAllocator => this.source.GetConfiguration().MemoryAllocator; /// - public Image Apply() + public Image GetResultImage() { if (!this.mutate && this.destination is null) { @@ -65,8 +65,7 @@ namespace SixLabors.ImageSharp.Processing return this.ApplyProcessor(processorImplementation); } - /// - public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle) + private IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle) { if (!this.mutate && this.destination is null) { @@ -86,8 +85,7 @@ namespace SixLabors.ImageSharp.Processing return this; } - /// - public IImageProcessingContext ApplyProcessor(IImageProcessor processor) + private IImageProcessingContext ApplyProcessor(IImageProcessor processor) { return this.ApplyProcessor(processor, this.GetCurrentBounds()); } diff --git a/src/ImageSharp/Processing/Extensions/BinaryDiffuseExtensions.cs b/src/ImageSharp/Processing/Extensions/BinaryDiffuseExtensions.cs index 7976daf25..760102aac 100644 --- a/src/ImageSharp/Processing/Extensions/BinaryDiffuseExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/BinaryDiffuseExtensions.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Processing /// The image this method extends. /// The diffusion algorithm to apply. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The to allow chaining of operations. + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDiffuse( this IImageProcessingContext source, IErrorDiffuser diffuser, @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDiffuse( this IImageProcessingContext source, IErrorDiffuser diffuser, @@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold - /// The to allow chaining of operations. + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDiffuse( this IImageProcessingContext source, IErrorDiffuser diffuser, @@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDiffuse( this IImageProcessingContext source, IErrorDiffuser diffuser, diff --git a/src/ImageSharp/Processing/Extensions/BinaryDitherExtensions.cs b/src/ImageSharp/Processing/Extensions/BinaryDitherExtensions.cs index b1e3d562e..e8ce252a2 100644 --- a/src/ImageSharp/Processing/Extensions/BinaryDitherExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/BinaryDitherExtensions.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The image this method extends. /// The ordered ditherer. - /// The to allow chaining of operations. + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDither(this IImageProcessingContext source, IOrderedDither dither) => source.ApplyProcessor(new BinaryOrderedDitherProcessor(dither)); @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing /// The ordered ditherer. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold - /// The to allow chaining of operations. + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDither( this IImageProcessingContext source, IOrderedDither dither, @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDither( this IImageProcessingContext source, IOrderedDither dither, @@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Processing /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The to allow chaining of operations. public static IImageProcessingContext BinaryDither( this IImageProcessingContext source, IOrderedDither dither, diff --git a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs index e469af18b..2304a44c3 100644 --- a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; + using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; @@ -13,18 +14,6 @@ namespace SixLabors.ImageSharp.Processing /// public static class ProcessingExtensions { - /// - /// Applies the given operation to the mutable image. - /// Useful when we need to extract information like Width/Height to parametrize the next operation working on the chain. - /// To achieve this the method actually implements an "inline" with as it's processing logic. - /// - /// The pixel format. - /// The image to mutate. - /// The operation to perform on the source. - /// The to allow chaining of operations. - public static IImageProcessingContext Apply(this IImageProcessingContext source, Action> operation) - where TPixel : struct, IPixel => source.ApplyProcessor(new DelegateProcessor(operation)); - /// /// Mutates the source image by applying the image operation to it. /// @@ -48,9 +37,9 @@ namespace SixLabors.ImageSharp.Processing Guard.NotNull(operation, nameof(operation)); Guard.NotNull(source, nameof(source)); - IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider.CreateImageProcessingContext(source, true); + IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider + .CreateImageProcessingContext(source, true); operation(operationsRunner); - operationsRunner.Apply(); } /// @@ -65,9 +54,9 @@ namespace SixLabors.ImageSharp.Processing Guard.NotNull(operations, nameof(operations)); Guard.NotNull(source, nameof(source)); - IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider.CreateImageProcessingContext(source, true); + IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider + .CreateImageProcessingContext(source, true); operationsRunner.ApplyProcessors(operations); - operationsRunner.Apply(); } /// @@ -96,9 +85,10 @@ namespace SixLabors.ImageSharp.Processing Guard.NotNull(operation, nameof(operation)); Guard.NotNull(source, nameof(source)); - IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider.CreateImageProcessingContext(source, false); + IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider + .CreateImageProcessingContext(source, false); operation(operationsRunner); - return operationsRunner.Apply(); + return operationsRunner.GetResultImage(); } /// @@ -114,9 +104,10 @@ namespace SixLabors.ImageSharp.Processing Guard.NotNull(operations, nameof(operations)); Guard.NotNull(source, nameof(source)); - IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider.CreateImageProcessingContext(source, false); + IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider + .CreateImageProcessingContext(source, false); operationsRunner.ApplyProcessors(operations); - return operationsRunner.Apply(); + return operationsRunner.GetResultImage(); } /// @@ -125,7 +116,9 @@ namespace SixLabors.ImageSharp.Processing /// The image processing context. /// The operations to perform on the source. /// The to allow chaining of operations. - public static IImageProcessingContext ApplyProcessors(this IImageProcessingContext source, params IImageProcessor[] operations) + public static IImageProcessingContext ApplyProcessors( + this IImageProcessingContext source, + params IImageProcessor[] operations) { foreach (IImageProcessor p in operations) { @@ -155,7 +148,7 @@ namespace SixLabors.ImageSharp.Processing IInternalImageProcessingContext operationsRunner = image.GetConfiguration() .ImageOperationsProvider.CreateImageProcessingContext(image, this.mutate); this.operation(operationsRunner); - this.ResultImage = operationsRunner.Apply(); + this.ResultImage = operationsRunner.GetResultImage(); } } } diff --git a/src/ImageSharp/Processing/IImageProcessingContextFactory.cs b/src/ImageSharp/Processing/IImageProcessingContextFactory.cs index 1ec2d191f..948e70b44 100644 --- a/src/ImageSharp/Processing/IImageProcessingContextFactory.cs +++ b/src/ImageSharp/Processing/IImageProcessingContextFactory.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing public IInternalImageProcessingContext CreateImageProcessingContext(Image source, bool mutate) where TPixel : struct, IPixel { - return new DefaultInternalImageProcessorContext(source, mutate); + return new DefaultImageProcessorContext(source, mutate); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs b/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs deleted file mode 100644 index b49cfe215..000000000 --- a/src/ImageSharp/Processing/IImageProcessingContext{TPixel}.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing.Processors; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// A pixel-specific interface to queue up image operations to apply to an image. - /// - /// The pixel format - public interface IImageProcessingContext : IImageProcessingContext - where TPixel : struct, IPixel - { - /// - /// Adds the processor to the current set of image operations to be applied. - /// - /// The processor to apply. - /// The area to apply it to. - /// The current operations class to allow chaining of operations. - IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle); - - /// - /// Adds the processor to the current set of image operations to be applied. - /// - /// The processor to apply - /// The current operations class to allow chaining of operations. - IImageProcessingContext ApplyProcessor(IImageProcessor processor); - } - - /// - /// An internal interface to queue up image operations and have a method to apply them to and return a result - /// - /// The pixel format - internal interface IInternalImageProcessingContext : IImageProcessingContext - where TPixel : struct, IPixel - { - /// - /// Adds the processors to the current image - /// - /// The current image or a new image depending on whether this is allowed to mutate the source image. - Image Apply(); - } -} \ No newline at end of file diff --git a/src/ImageSharp/Processing/IInternalImageProcessingContext.cs b/src/ImageSharp/Processing/IInternalImageProcessingContext.cs new file mode 100644 index 000000000..55303b1ef --- /dev/null +++ b/src/ImageSharp/Processing/IInternalImageProcessingContext.cs @@ -0,0 +1,22 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing +{ + /// + /// An interface for internal operations we don't want to expose on . + /// + /// The pixel type. + internal interface IInternalImageProcessingContext : IImageProcessingContext + where TPixel : struct, IPixel + { + /// + /// Returns the result image to return by + /// (and other overloads). + /// + /// The current image or a new image depending on whether it is requested to mutate the source image. + Image GetResultImage(); + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/DelegateProcessor.cs b/src/ImageSharp/Processing/Processors/DelegateProcessor.cs deleted file mode 100644 index 7a9753d1a..000000000 --- a/src/ImageSharp/Processing/Processors/DelegateProcessor.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing.Processors -{ - /// - /// Allows the application of processing algorithms to images via an action delegate - /// - /// The pixel format. - internal class DelegateProcessor : ImageProcessor - where TPixel : struct, IPixel - { - /// - /// Initializes a new instance of the class. - /// - /// The action. - public DelegateProcessor(Action> action) - { - this.Action = action; - } - - /// - /// Gets the action that will be applied to the image. - /// - internal Action> Action { get; } - - /// - protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) - { - this.Action?.Invoke(source); - } - - /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - // NOP, we did all we wanted to do inside BeforeImageApply - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Dithering/AtkinsonDiffuser.cs b/src/ImageSharp/Processing/Processors/Dithering/AtkinsonDiffuser.cs index 17c97ddc9..0461d179f 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/AtkinsonDiffuser.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/AtkinsonDiffuser.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Applies error diffusion based dithering using the Atkinson image dithering algorithm. /// /// - public sealed class AtkinsonDiffuser : ErrorDiffuserBase + public sealed class AtkinsonDiffuser : ErrorDiffuser { /// /// The diffusion matrix diff --git a/src/ImageSharp/Processing/Processors/Dithering/BurksDiffuser.cs b/src/ImageSharp/Processing/Processors/Dithering/BurksDiffuser.cs index 84455b24a..23d4321e9 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/BurksDiffuser.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/BurksDiffuser.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Applies error diffusion based dithering using the Burks image dithering algorithm. /// /// - public sealed class BurksDiffuser : ErrorDiffuserBase + public sealed class BurksDiffuser : ErrorDiffuser { /// /// The diffusion matrix diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuser.cs similarity index 96% rename from src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs rename to src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuser.cs index 327828c39..1c8156bf5 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuserBase.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDiffuser.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// /// The base class for performing error diffusion based dithering. /// - public abstract class ErrorDiffuserBase : IErrorDiffuser + public abstract class ErrorDiffuser : IErrorDiffuser { /// /// The vector to perform division. @@ -41,11 +41,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering private readonly DenseMatrix matrix; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The dithering matrix. /// The divisor. - internal ErrorDiffuserBase(in DenseMatrix matrix, byte divisor) + internal ErrorDiffuser(in DenseMatrix matrix, byte divisor) { Guard.MustBeGreaterThan(divisor, 0, nameof(divisor)); diff --git a/src/ImageSharp/Processing/Processors/Dithering/FloydSteinbergDiffuser.cs b/src/ImageSharp/Processing/Processors/Dithering/FloydSteinbergDiffuser.cs index 6a7655b59..78a28a693 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/FloydSteinbergDiffuser.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/FloydSteinbergDiffuser.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Applies error diffusion based dithering using the Floyd–Steinberg image dithering algorithm. /// /// - public sealed class FloydSteinbergDiffuser : ErrorDiffuserBase + public sealed class FloydSteinbergDiffuser : ErrorDiffuser { /// /// The diffusion matrix diff --git a/src/ImageSharp/Processing/Processors/Dithering/JarvisJudiceNinkeDiffuser.cs b/src/ImageSharp/Processing/Processors/Dithering/JarvisJudiceNinkeDiffuser.cs index a69557d6d..64c861083 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/JarvisJudiceNinkeDiffuser.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/JarvisJudiceNinkeDiffuser.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Applies error diffusion based dithering using the JarvisJudiceNinke image dithering algorithm. /// /// - public sealed class JarvisJudiceNinkeDiffuser : ErrorDiffuserBase + public sealed class JarvisJudiceNinkeDiffuser : ErrorDiffuser { /// /// The diffusion matrix diff --git a/src/ImageSharp/Processing/Processors/Dithering/Sierra2Diffuser.cs b/src/ImageSharp/Processing/Processors/Dithering/Sierra2Diffuser.cs index ebde2ceaf..b489f8f28 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/Sierra2Diffuser.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/Sierra2Diffuser.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Applies error diffusion based dithering using the Sierra2 image dithering algorithm. /// /// - public sealed class Sierra2Diffuser : ErrorDiffuserBase + public sealed class Sierra2Diffuser : ErrorDiffuser { /// /// The diffusion matrix diff --git a/src/ImageSharp/Processing/Processors/Dithering/Sierra3Diffuser.cs b/src/ImageSharp/Processing/Processors/Dithering/Sierra3Diffuser.cs index 144a83a82..04abc782a 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/Sierra3Diffuser.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/Sierra3Diffuser.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Applies error diffusion based dithering using the Sierra3 image dithering algorithm. /// /// - public sealed class Sierra3Diffuser : ErrorDiffuserBase + public sealed class Sierra3Diffuser : ErrorDiffuser { /// /// The diffusion matrix diff --git a/src/ImageSharp/Processing/Processors/Dithering/SierraLiteDiffuser.cs b/src/ImageSharp/Processing/Processors/Dithering/SierraLiteDiffuser.cs index d71fba9f2..2ac69cf45 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/SierraLiteDiffuser.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/SierraLiteDiffuser.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Applies error diffusion based dithering using the SierraLite image dithering algorithm. /// /// - public sealed class SierraLiteDiffuser : ErrorDiffuserBase + public sealed class SierraLiteDiffuser : ErrorDiffuser { /// /// The diffusion matrix diff --git a/src/ImageSharp/Processing/Processors/Dithering/StevensonArceDiffuser.cs b/src/ImageSharp/Processing/Processors/Dithering/StevensonArceDiffuser.cs index 4b1323065..b929a28d3 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/StevensonArceDiffuser.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/StevensonArceDiffuser.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// /// Applies error diffusion based dithering using the Stevenson-Arce image dithering algorithm. /// - public sealed class StevensonArceDiffuser : ErrorDiffuserBase + public sealed class StevensonArceDiffuser : ErrorDiffuser { /// /// The diffusion matrix diff --git a/src/ImageSharp/Processing/Processors/Dithering/StuckiDiffuser.cs b/src/ImageSharp/Processing/Processors/Dithering/StuckiDiffuser.cs index 1dd510a5e..bb3aebc3f 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/StuckiDiffuser.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/StuckiDiffuser.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// Applies error diffusion based dithering using the Stucki image dithering algorithm. /// /// - public sealed class StuckiDiffuser : ErrorDiffuserBase + public sealed class StuckiDiffuser : ErrorDiffuser { /// /// The diffusion matrix diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs index 5a043cb20..9625ca216 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// Provides the base methods to perform affine transforms on an image. /// /// The pixel format. - internal class AffineTransformProcessor : TransformProcessorBase + internal class AffineTransformProcessor : TransformProcessor where TPixel : struct, IPixel { public AffineTransformProcessor(AffineTransformProcessor definition) diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs index 9bddda382..4c4c27def 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// Provides methods to allow the cropping of an image. /// /// The pixel format. - internal class CropProcessor : TransformProcessorBase + internal class CropProcessor : TransformProcessor where TPixel : struct, IPixel { private readonly CropProcessor definition; diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs index ab07040f7..15d8141ba 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// Provides the base methods to perform non-affine transforms on an image. /// /// The pixel format. - internal class ProjectiveTransformProcessor : TransformProcessorBase + internal class ProjectiveTransformProcessor : TransformProcessor where TPixel : struct, IPixel { private readonly ProjectiveTransformProcessor definition; diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index cf99f28dd..fdd1d339d 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The original code has been adapted from . /// /// The pixel format. - internal class ResizeProcessor : TransformProcessorBase + internal class ResizeProcessor : TransformProcessor where TPixel : struct, IPixel { // The following fields are not immutable but are optionally created on demand. diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorBase.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessor.cs similarity index 89% rename from src/ImageSharp/Processing/Processors/Transforms/TransformProcessorBase.cs rename to src/ImageSharp/Processing/Processors/Transforms/TransformProcessor.cs index 286ada2e5..ef508549a 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorBase.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessor.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The base class for all transform processors. Any processor that changes the dimensions of the image should inherit from this. /// /// The pixel format. - internal abstract class TransformProcessorBase : CloningImageProcessor + internal abstract class TransformProcessor : CloningImageProcessor where TPixel : struct, IPixel { /// diff --git a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs index 29f69cdd5..263ce6a7e 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Benchmarks public void Setup() { this.bulk = new GlowProcessor(Color.Beige, 800 * .5f, GraphicsOptions.Default); - this.parallel = new GlowProcessorParallel(NamedColors.Beige) { Radius = 800 * .5f, }; + this.parallel = new GlowProcessorParallel(Color.Beige) { Radius = 800 * .5f, }; } [Benchmark(Description = "ImageSharp Glow - Bulk")] diff --git a/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs b/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs index 857c19d87..d3de04354 100644 --- a/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs +++ b/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Tests { public abstract class BaseImageOperationsExtensionTest { - protected readonly IImageProcessingContext operations; + protected readonly IImageProcessingContext operations; private readonly FakeImageOperationsProvider.FakeImageOperations internalOperations; protected readonly Rectangle rect; protected readonly GraphicsOptions options; diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/ApproximateColorspaceComparer.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/ApproximateColorspaceComparer.cs index 57da2ff17..7bf84dd0a 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/ApproximateColorspaceComparer.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/ApproximateColorspaceComparer.cs @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion IEqualityComparer, IEqualityComparer, IEqualityComparer, - IEqualityComparer + IEqualityComparer { private readonly float Epsilon; @@ -222,14 +222,14 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion public int GetHashCode(GammaWorkingSpace obj) => obj.GetHashCode(); /// - public bool Equals(RgbWorkingSpaceBase x, RgbWorkingSpaceBase y) + public bool Equals(RgbWorkingSpace x, RgbWorkingSpace y) { return this.Equals(x.WhitePoint, y.WhitePoint) && this.Equals(x.ChromaticityCoordinates, y.ChromaticityCoordinates); } /// - public int GetHashCode(RgbWorkingSpaceBase obj) => obj.GetHashCode(); + public int GetHashCode(RgbWorkingSpace obj) => obj.GetHashCode(); private bool Equals(float x, float y) { diff --git a/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs b/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs index c91cb16d4..c3ae0cddf 100644 --- a/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs +++ b/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Tests public MemoryAllocator MemoryAllocator => this.Source.GetConfiguration().MemoryAllocator; - public Image Apply() + public Image GetResultImage() { return this.Source; } @@ -86,25 +86,6 @@ namespace SixLabors.ImageSharp.Tests return this; } - public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle) - { - this.Applied.Add(new AppliedOperation - { - GenericProcessor = processor, - Rectangle = rectangle - }); - return this; - } - - public IImageProcessingContext ApplyProcessor(IImageProcessor processor) - { - this.Applied.Add(new AppliedOperation - { - GenericProcessor = processor - }); - return this; - } - public struct AppliedOperation { public Rectangle? Rectangle { get; set; } diff --git a/tests/ImageSharp.Tests/Image/ImageProcessingContextTests.cs b/tests/ImageSharp.Tests/Image/ImageProcessingContextTests.cs deleted file mode 100644 index 6dadc6e7a..000000000 --- a/tests/ImageSharp.Tests/Image/ImageProcessingContextTests.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using SixLabors.Primitives; -using Xunit; - -namespace SixLabors.ImageSharp.Tests -{ - public class ImageProcessingContextTests - { - // [Fact] - // public void MutatedSizeIsAccuratePerOperation() - // { - // var x500 = new Size(500, 500); - // var x400 = new Size(400, 400); - // var x300 = new Size(300, 300); - // var x200 = new Size(200, 200); - // var x100 = new Size(100, 100); - // using (var image = new Image(500, 500)) - // { - // image.Mutate(x => - // x.AssertSize(x500) - // .Resize(x400).AssertSize(x400) - // .Resize(x300).AssertSize(x300) - // .Resize(x200).AssertSize(x200) - // .Resize(x100).AssertSize(x100)); - // } - // } - // - // [Fact] - // public void ClonedSizeIsAccuratePerOperation() - // { - // var x500 = new Size(500, 500); - // var x400 = new Size(400, 400); - // var x300 = new Size(300, 300); - // var x200 = new Size(200, 200); - // var x100 = new Size(100, 100); - // using (var image = new Image(500, 500)) - // { - // image.Clone(x => - // x.AssertSize(x500) - // .Resize(x400).AssertSize(x400) - // .Resize(x300).AssertSize(x300) - // .Resize(x200).AssertSize(x200) - // .Resize(x100).AssertSize(x100)); - // } - // } - } - - public static class SizeAssertationExtensions - { - public static IImageProcessingContext AssertSize(this IImageProcessingContext context, Size size) - { - Assert.Equal(size, context.GetCurrentSize()); - return context; - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs index d51470292..ea9957314 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs @@ -113,8 +113,8 @@ namespace SixLabors.ImageSharp.Tests using (var memoryManager = new BitmapMemoryManager(bmp)) { Memory memory = memoryManager.Memory; - Bgra32 bg = NamedColors.Red; - Bgra32 fg = NamedColors.Green; + Bgra32 bg = Color.Red; + Bgra32 fg = Color.Green; using (var image = Image.WrapMemory(memory, bmp.Width, bmp.Height)) { @@ -144,8 +144,8 @@ namespace SixLabors.ImageSharp.Tests using (var bmp = new Bitmap(51, 23)) { var memoryManager = new BitmapMemoryManager(bmp); - Bgra32 bg = NamedColors.Red; - Bgra32 fg = NamedColors.Green; + Bgra32 bg = Color.Red; + Bgra32 fg = Color.Green; using (var image = Image.WrapMemory(memoryManager, bmp.Width, bmp.Height)) { diff --git a/tests/ImageSharp.Tests/PixelFormats/ColorBuilderTests.cs b/tests/ImageSharp.Tests/PixelFormats/ColorBuilderTests.cs deleted file mode 100644 index e56cac279..000000000 --- a/tests/ImageSharp.Tests/PixelFormats/ColorBuilderTests.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Colors -{ - public class ColorBuilderTests - { - [Fact] - public void ParseShortHex() - { - Assert.Equal(new Rgb24(255, 255, 255), ColorBuilder.FromHex("#fff")); - Assert.Equal(new Rgb24(255, 255, 255), ColorBuilder.FromHex("fff")); - Assert.Equal(new Rgba32(0, 0, 0, 255), ColorBuilder.FromHex("000f")); - } - - [Fact] - public void ParseHexLeadingPoundIsOptional() - { - Assert.Equal(new Rgb24(0, 128, 128), ColorBuilder.FromHex("#008080")); - Assert.Equal(new Rgb24(0, 128, 128), ColorBuilder.FromHex("008080")); - } - - [Fact] - public void ParseHexThrowsOnEmpty() - { - Assert.Throws(() => ColorBuilder.FromHex("")); - } - - [Fact] - public void ParseHexThrowsOnNull() - { - Assert.Throws(() => ColorBuilder.FromHex(null)); - } - } -} diff --git a/tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs b/tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs deleted file mode 100644 index 302e56ec7..000000000 --- a/tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using SixLabors.ImageSharp.PixelFormats; -using Xunit; - -namespace SixLabors.ImageSharp.Tests -{ - public class ColorDefinitionTests - { - public static TheoryData ColorNames - { - get - { - var result = new TheoryData(); - foreach (string name in typeof(NamedColors).GetTypeInfo() - .GetFields().Where(x => x.Name != nameof(NamedColors.WebSafePalette)).Select(x => x.Name)) - { - result.Add(name); - } - return result; - } - } - - [Theory] - [MemberData(nameof(ColorNames))] - public void AllColorsAreOnGenericAndBaseColor(string name) - { - FieldInfo generic = typeof(NamedColors).GetTypeInfo().GetField(name); - FieldInfo specific = typeof(Rgba32).GetTypeInfo().GetField(name); - - Assert.NotNull(specific); - Assert.NotNull(generic); - Assert.True(specific.Attributes.HasFlag(FieldAttributes.Public), "specific must be public"); - Assert.True(specific.Attributes.HasFlag(FieldAttributes.Static), "specific must be static"); - Assert.True(generic.Attributes.HasFlag(FieldAttributes.Public), "generic must be public"); - Assert.True(generic.Attributes.HasFlag(FieldAttributes.Static), "generic must be static"); - Rgba32 expected = (Rgba32)generic.GetValue(null); - Rgba32 actual = (Rgba32)specific.GetValue(null); - Assert.Equal(expected, actual); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/DelegateTest.cs b/tests/ImageSharp.Tests/Processing/DelegateTest.cs deleted file mode 100644 index 73d3c8023..000000000 --- a/tests/ImageSharp.Tests/Processing/DelegateTest.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Processing -{ - using SixLabors.ImageSharp.Processing.Processors; - - public class DelegateTest : BaseImageOperationsExtensionTest - { - [Fact] - public void Run_CreatedDelegateProcessor() - { - Action> action = (i) => { }; - this.operations.Apply(action); - - DelegateProcessor processor = this.Verify>(); - Assert.Equal(action, processor.Action); - } - } -} diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs index de203535c..752f8e18b 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs @@ -31,9 +31,9 @@ namespace SixLabors.ImageSharp.Tests { var result = new Image(this.Configuration, this.Width, this.Height); - TPixel topLeftColor = NamedColors.Red; - TPixel topRightColor = NamedColors.Green; - TPixel bottomLeftColor = NamedColors.Blue; + TPixel topLeftColor = Color.Red.ToPixel(); + TPixel topRightColor = Color.Green.ToPixel(); + TPixel bottomLeftColor = Color.Blue.ToPixel(); // Transparent purple: TPixel bottomRightColor = default; @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Tests Span row = result.GetPixelRowSpan(y); row.Slice(0, midX).Fill(topLeftColor); - row.Slice(midX, this.Width-midX).Fill(topRightColor); + row.Slice(midX, this.Width - midX).Fill(topRightColor); } for (int y = midY; y < this.Height; y++) @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Tests Span row = result.GetPixelRowSpan(y); row.Slice(0, midX).Fill(bottomLeftColor); - row.Slice(midX, this.Width-midX).Fill(bottomRightColor); + row.Slice(midX, this.Width - midX).Fill(bottomRightColor); } return result; diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs index 6df8c8501..94b2b3391 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs @@ -21,6 +21,16 @@ namespace SixLabors.ImageSharp.Tests { static readonly Dictionary> TestImages = new Dictionary>(); + private static TPixel[] BlackWhitePixels = new[] { + Color.Black.ToPixel(), + Color.White.ToPixel() + }; + + private static TPixel[] PinkBluePixels = new[] { + Color.HotPink.ToPixel(), + Color.Blue.ToPixel() + }; + public TestPatternProvider(int width, int height) : base(width, height) { @@ -80,12 +90,6 @@ namespace SixLabors.ImageSharp.Tests stride = 1; } - TPixel[] c = - { - NamedColors.HotPink, - NamedColors.Blue - }; - for (int y = top; y < bottom; y++) { int p = 0; @@ -94,9 +98,9 @@ namespace SixLabors.ImageSharp.Tests if (x % stride == 0) { p++; - p = p % c.Length; + p = p % PinkBluePixels.Length; } - pixels[x, y] = c[p]; + pixels[x, y] = PinkBluePixels[p]; } } } @@ -113,11 +117,6 @@ namespace SixLabors.ImageSharp.Tests int top = 0; int bottom = pixels.Height / 2; int stride = pixels.Width / 6; - TPixel[] c = - { - NamedColors.Black, - NamedColors.White - }; int p = 0; for (int y = top; y < bottom; y++) @@ -125,7 +124,7 @@ namespace SixLabors.ImageSharp.Tests if (y % stride == 0) { p++; - p = p % c.Length; + p = p % BlackWhitePixels.Length; } int pstart = p; for (int x = left; x < right; x++) @@ -133,9 +132,9 @@ namespace SixLabors.ImageSharp.Tests if (x % stride == 0) { p++; - p = p % c.Length; + p = p % BlackWhitePixels.Length; } - pixels[x, y] = c[p]; + pixels[x, y] = BlackWhitePixels[p]; } p = pstart; } From 10c834bb947f9446b025d4f6fb9e9519c49af480 Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Sat, 25 May 2019 02:35:02 +0200 Subject: [PATCH 207/223] Fix for Issue #871 and #914 (#915) --- .../PixelFormats/PixelImplementations/Rgba32.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs index b439ef32c..ba259ca8e 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs @@ -136,13 +136,16 @@ namespace SixLabors.ImageSharp.PixelFormats /// public Rgb24 Rgb { - // If this is changed to ShortMethod then several jpeg encoding tests fail - // on 32 bit Net 4.6.2 and NET 4.7.1 - [MethodImpl(InliningOptions.ColdPath)] - get => Unsafe.As(ref this); + [MethodImpl(InliningOptions.ShortMethod)] + get => new Rgb24(this.R, this.G, this.B); [MethodImpl(InliningOptions.ShortMethod)] - set => Unsafe.As(ref this) = value; + set + { + this.R = value.R; + this.G = value.G; + this.B = value.B; + } } /// From 32d919e5eeb2eb67cf7798730dcf0a0069b5efdc Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 25 May 2019 22:43:14 +1000 Subject: [PATCH 208/223] Fix #466 (#916) --- .../Processing/Extensions/PadExtensions.cs | 14 ++++++-- .../Processors/Transforms/PadTest.cs | 33 ++++++++++++++++--- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/ImageSharp/Processing/Extensions/PadExtensions.cs b/src/ImageSharp/Processing/Extensions/PadExtensions.cs index 29f80b43f..270380084 100644 --- a/src/ImageSharp/Processing/Extensions/PadExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/PadExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing @@ -20,6 +19,17 @@ namespace SixLabors.ImageSharp.Processing /// The new height. /// The to allow chaining of operations. public static IImageProcessingContext Pad(this IImageProcessingContext source, int width, int height) + => source.Pad(width, height, default); + + /// + /// Evenly pads an image to fit the new dimensions with the given background color. + /// + /// The source image to pad. + /// The new width. + /// The new height. + /// The background color with which to pad the image. + /// The to allow chaining of operations. + public static IImageProcessingContext Pad(this IImageProcessingContext source, int width, int height, Color color) { var options = new ResizeOptions { @@ -28,7 +38,7 @@ namespace SixLabors.ImageSharp.Processing Sampler = KnownResamplers.NearestNeighbor, }; - return source.Resize(options); + return color.Equals(default) ? source.Resize(options) : source.Resize(options).BackgroundColor(color); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs index 750d67c32..f56827870 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs @@ -10,10 +10,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms public class PadTest { public static readonly string[] CommonTestImages = - { - TestImages.Png.CalliphoraPartial, TestImages.Png.Bike - }; - + { + TestImages.Png.CalliphoraPartial, TestImages.Png.Bike + }; + [Theory] [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)] public void ImageShouldPad(TestImageProvider provider) @@ -29,7 +29,30 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { for (int x = 0; x < 25; x++) { - Assert.Equal(default(TPixel), image[x, y]); + Assert.Equal(default, image[x, y]); + } + } + } + } + + [Theory] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)] + public void ImageShouldPadWithBackgroundColor(TestImageProvider provider) + where TPixel : struct, IPixel + { + Color color = Color.Red; + TPixel expected = color.ToPixel(); + using (Image image = provider.GetImage()) + { + image.Mutate(x => x.Pad(image.Width + 50, image.Height + 50, color)); + image.DebugSave(provider); + + // Check pixels are filled + for (int y = 0; y < 25; y++) + { + for (int x = 0; x < 25; x++) + { + Assert.Equal(expected, image[x, y]); } } } From b4deb292219c00a62a85dcf9d052ad29033d688d Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Sat, 25 May 2019 23:24:44 +0200 Subject: [PATCH 209/223] Added funding file with a link to open collective. --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..ee7a10862 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +open_collective: imagesharp \ No newline at end of file From 07ec651190354966d927a6b1cbb59fe28ec8b23d Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 27 May 2019 20:55:15 +1000 Subject: [PATCH 210/223] Removes usage of linq in several critical paths (#918) * Remove linq usage from jpeg + formatting * png * ICC + formattiing * Resize * Fix base class comparison. --- .../Components/Decoder/ProfileResolver.cs | 8 ++-- .../Formats/Jpeg/JpegDecoderCore.cs | 3 +- .../Formats/Jpeg/JpegEncoderCore.cs | 36 +++++++------- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 5 +- .../ICC/Curves/IccOneDimensionalCurve.cs | 3 +- .../Profiles/ICC/Curves/IccResponseCurve.cs | 8 +--- .../DataWriter/IccDataWriter.TagDataEntry.cs | 48 +++++-------------- .../MetaData/Profiles/ICC/IccWriter.cs | 1 + .../IccCurveSetProcessElement.cs | 12 ++--- .../IccChromaticityTagDataEntry.cs | 12 ++--- .../IccColorantTableTagDataEntry.cs | 18 ++----- .../TagDataEntries/IccLut16TagDataEntry.cs | 19 +++----- .../ICC/TagDataEntries/IccLut8TagDataEntry.cs | 14 ++---- .../TagDataEntries/IccLutAToBTagDataEntry.cs | 44 +++++++---------- .../TagDataEntries/IccLutBToATagDataEntry.cs | 37 +++++--------- .../IccMultiLocalizedUnicodeTagDataEntry.cs | 3 +- .../IccMultiProcessElementsTagDataEntry.cs | 12 ++--- .../IccNamedColor2TagDataEntry.cs | 2 +- .../IccProfileSequenceDescTagDataEntry.cs | 15 ++---- .../IccResponseCurveSet16TagDataEntry.cs | 12 ++--- .../IccUInt64ArrayTagDataEntry.cs | 16 ++----- .../MetaData/Profiles/ICC/Various/IccClut.cs | 5 +- .../Profiles/ICC/Various/IccNamedColor.cs | 20 ++------ .../ICC/Various/IccProfileDescription.cs | 18 +++---- .../Various/IccProfileSequenceIdentifier.cs | 10 ++-- src/ImageSharp/Processing/ResizeOptions.cs | 4 +- 26 files changed, 122 insertions(+), 263 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs index abfd6f556..54633a5d7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ProfileResolver.cs @@ -12,17 +12,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder internal static class ProfileResolver { /// - /// Describes the EXIF specific markers. + /// Describes the JFIF specific markers. /// public static readonly byte[] JFifMarker = Encoding.ASCII.GetBytes("JFIF\0"); /// - /// Describes the EXIF specific markers. + /// Describes the ICC specific markers. /// public static readonly byte[] IccMarker = Encoding.ASCII.GetBytes("ICC_PROFILE\0"); /// - /// Describes the ICC specific markers. + /// Describes the EXIF specific markers. /// public static readonly byte[] ExifMarker = Encoding.ASCII.GetBytes("Exif\0\0"); @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// /// The bytes to check. /// The profile identifier. - /// The + /// The . public static bool IsProfile(ReadOnlySpan bytesToCheck, ReadOnlySpan profileIdentifier) { return bytesToCheck.Length >= profileIdentifier.Length diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 8bd6514e0..fd0c289b8 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -4,7 +4,6 @@ using System; using System.Buffers.Binary; using System.IO; -using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Common.Helpers; @@ -726,7 +725,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.InputStream.Read(this.temp, 0, length); // We only support 8-bit and 12-bit precision. - if (!this.supportedPrecisions.Contains(this.temp[0])) + if (Array.IndexOf(this.supportedPrecisions, this.temp[0]) == -1) { JpegThrowHelper.ThrowImageFormatException("Only 8-Bit and 12-Bit precision supported."); } diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index d4ce28107..0b9eeb609 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -4,7 +4,6 @@ using System; using System.Buffers.Binary; using System.IO; -using System.Linq; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Formats.Jpeg.Components; @@ -197,7 +196,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); - ushort max = JpegConstants.MaxLength; + const ushort max = JpegConstants.MaxLength; if (image.Width >= max || image.Height >= max) { throw new ImageFormatException($"Image is too large to encode at {image.Width}x{image.Height}."); @@ -226,7 +225,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg InitQuantizationTable(1, scale, ref this.chrominanceQuantTable); // Compute number of components based on input image type. - int componentCount = 3; + const int componentCount = 3; // Write the Start Of Image marker. this.WriteApplicationHeader(metadata); @@ -278,7 +277,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg private static void InitQuantizationTable(int i, int scale, ref Block8x8F quant) { DebugGuard.MustBeBetweenOrEqualTo(i, 0, 1, nameof(i)); - var unscaledQuant = (i == 0) ? UnscaledQuant_Luminance : UnscaledQuant_Chrominance; + ReadOnlySpan unscaledQuant = (i == 0) ? UnscaledQuant_Luminance : UnscaledQuant_Chrominance; for (int j = 0; j < Block8x8F.Size; j++) { @@ -653,8 +652,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg return; } - const int MaxBytesApp1 = 65533; - const int MaxBytesWithExifId = 65527; + const int MaxBytesApp1 = 65533; // 64k - 2 padding bytes + const int MaxBytesWithExifId = 65527; // Max - 6 bytes for EXIF header. byte[] data = exifProfile?.ToByteArray(); @@ -663,31 +662,30 @@ namespace SixLabors.ImageSharp.Formats.Jpeg return; } - data = ProfileResolver.ExifMarker.Concat(data).ToArray(); - - int remaining = data.Length; + // We can write up to a maximum of 64 data to the initial marker so calculate boundaries. + int exifMarkerLength = ProfileResolver.ExifMarker.Length; + int remaining = exifMarkerLength + data.Length; int bytesToWrite = remaining > MaxBytesApp1 ? MaxBytesApp1 : remaining; int app1Length = bytesToWrite + 2; + // Write the app marker, EXIF marker, and data this.WriteApp1Header(app1Length); - - // write the exif data - this.outputStream.Write(data, 0, bytesToWrite); + this.outputStream.Write(ProfileResolver.ExifMarker); + this.outputStream.Write(data, 0, bytesToWrite - exifMarkerLength); remaining -= bytesToWrite; - // if the exif data exceeds 64K, write it in multiple APP1 Markers - for (int idx = MaxBytesApp1; idx < data.Length; idx += MaxBytesWithExifId) + // If the exif data exceeds 64K, write it in multiple APP1 Markers + for (int idx = MaxBytesWithExifId; idx < data.Length; idx += MaxBytesWithExifId) { bytesToWrite = remaining > MaxBytesWithExifId ? MaxBytesWithExifId : remaining; - app1Length = bytesToWrite + 2 + 6; + app1Length = bytesToWrite + 2 + exifMarkerLength; this.WriteApp1Header(app1Length); - // write Exif00 marker - ProfileResolver.ExifMarker.AsSpan().CopyTo(this.buffer.AsSpan()); - this.outputStream.Write(this.buffer, 0, 6); + // Write Exif00 marker + this.outputStream.Write(ProfileResolver.ExifMarker); - // write the exif data + // Write the exif data this.outputStream.Write(data, idx, bytesToWrite); remaining -= bytesToWrite; diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index cbc35f3c3..def57c3b0 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -6,7 +6,6 @@ using System.Buffers; using System.Buffers.Binary; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; @@ -231,7 +230,7 @@ namespace SixLabors.ImageSharp.Formats.Png if (this.pngColorType == PngColorType.Palette) { byte bits = (byte)this.pngBitDepth; - if (!ColorTypes[this.pngColorType.Value].Contains(bits)) + if (Array.IndexOf(ColorTypes[this.pngColorType.Value], bits) == -1) { throw new NotSupportedException("Bit depth is not supported or not valid."); } @@ -268,7 +267,7 @@ namespace SixLabors.ImageSharp.Formats.Png else { this.bitDepth = (byte)this.pngBitDepth; - if (!ColorTypes[this.pngColorType.Value].Contains(this.bitDepth)) + if (Array.IndexOf(ColorTypes[this.pngColorType.Value], this.bitDepth) == -1) { throw new NotSupportedException("Bit depth is not supported or not valid."); } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs index e1d362a7f..cbb433012 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -52,7 +51,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } return this.BreakPoints.AsSpan().SequenceEqual(other.BreakPoints) - && this.Segments.SequenceEqual(other.Segments); + && this.Segments.AsSpan().SequenceEqual(other.Segments); } } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs index 4f0345d35..b9a50acd4 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; using System.Numerics; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc @@ -65,10 +64,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } /// - public override bool Equals(object obj) - { - return obj is IccResponseCurve other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccResponseCurve other && this.Equals(other); /// public override int GetHashCode() @@ -88,7 +84,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc for (int i = 0; i < this.ResponseArrays.Length; i++) { - if (!this.ResponseArrays[i].SequenceEqual(other.ResponseArrays[i])) + if (!this.ResponseArrays[i].AsSpan().SequenceEqual(other.ResponseArrays[i])) { return false; } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs index 13fb023d3..f3c632a86 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs @@ -163,10 +163,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The entry to write /// The number of bytes written - public int WriteUnknownTagDataEntry(IccUnknownTagDataEntry value) - { - return this.WriteArray(value.Data); - } + public int WriteUnknownTagDataEntry(IccUnknownTagDataEntry value) => this.WriteArray(value.Data); /// /// Writes a @@ -269,10 +266,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The entry to write /// The number of bytes written - public int WriteDateTimeTagDataEntry(IccDateTimeTagDataEntry value) - { - return this.WriteDateTime(value.Value); - } + public int WriteDateTimeTagDataEntry(IccDateTimeTagDataEntry value) => this.WriteDateTime(value.Value); /// /// Writes a @@ -563,6 +557,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc long tpos = this.dataStream.Position; this.dataStream.Position += cultureCount * 12; + // TODO: Investigate cost of Linq GroupBy IGrouping[] texts = value.Texts.GroupBy(t => t.Text).ToArray(); uint[] offset = new uint[texts.Length]; @@ -625,7 +620,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc long tpos = this.dataStream.Position; this.dataStream.Position += value.Data.Length * 8; - IccPositionNumber[] posTable = new IccPositionNumber[value.Data.Length]; + var posTable = new IccPositionNumber[value.Data.Length]; for (int i = 0; i < value.Data.Length; i++) { uint offset = (uint)(this.dataStream.Position - start); @@ -673,10 +668,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The entry to write /// The number of bytes written - public int WriteParametricCurveTagDataEntry(IccParametricCurveTagDataEntry value) - { - return this.WriteParametricCurve(value.Curve); - } + public int WriteParametricCurveTagDataEntry(IccParametricCurveTagDataEntry value) => this.WriteParametricCurve(value.Curve); /// /// Writes a @@ -793,20 +785,14 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The entry to write /// The number of bytes written - public int WriteSignatureTagDataEntry(IccSignatureTagDataEntry value) - { - return this.WriteAsciiString(value.SignatureData, 4, false); - } + public int WriteSignatureTagDataEntry(IccSignatureTagDataEntry value) => this.WriteAsciiString(value.SignatureData, 4, false); /// /// Writes a /// /// The entry to write /// The number of bytes written - public int WriteTextTagDataEntry(IccTextTagDataEntry value) - { - return this.WriteAsciiString(value.Text); - } + public int WriteTextTagDataEntry(IccTextTagDataEntry value) => this.WriteAsciiString(value.Text); /// /// Writes a @@ -829,40 +815,28 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// The entry to write /// The number of bytes written - public int WriteUInt16ArrayTagDataEntry(IccUInt16ArrayTagDataEntry value) - { - return this.WriteArray(value.Data); - } + public int WriteUInt16ArrayTagDataEntry(IccUInt16ArrayTagDataEntry value) => this.WriteArray(value.Data); /// /// Writes a /// /// The entry to write /// The number of bytes written - public int WriteUInt32ArrayTagDataEntry(IccUInt32ArrayTagDataEntry value) - { - return this.WriteArray(value.Data); - } + public int WriteUInt32ArrayTagDataEntry(IccUInt32ArrayTagDataEntry value) => this.WriteArray(value.Data); /// /// Writes a /// /// The entry to write /// The number of bytes written - public int WriteUInt64ArrayTagDataEntry(IccUInt64ArrayTagDataEntry value) - { - return this.WriteArray(value.Data); - } + public int WriteUInt64ArrayTagDataEntry(IccUInt64ArrayTagDataEntry value) => this.WriteArray(value.Data); /// /// Writes a /// /// The entry to write /// The number of bytes written - public int WriteUInt8ArrayTagDataEntry(IccUInt8ArrayTagDataEntry value) - { - return this.WriteArray(value.Data); - } + public int WriteUInt8ArrayTagDataEntry(IccUInt8ArrayTagDataEntry value) => this.WriteArray(value.Data); /// /// Writes a diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs index b5a7c830d..186f06df0 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs @@ -70,6 +70,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc private IccTagTableEntry[] WriteTagData(IccDataWriter writer, IccTagDataEntry[] entries) { + // TODO: Investigate cost of Linq GroupBy IEnumerable> grouped = entries.GroupBy(t => t); // (Header size) + (entry count) + (nr of entries) * (size of table entry) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs index d72aff3c9..c6409e3c1 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -17,9 +16,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// An array with one dimensional curves public IccCurveSetProcessElement(IccOneDimensionalCurve[] curves) : base(IccMultiProcessElementSignature.CurveSet, curves?.Length ?? 1, curves?.Length ?? 1) - { - this.Curves = curves ?? throw new ArgumentNullException(nameof(curves)); - } + => this.Curves = curves ?? throw new ArgumentNullException(nameof(curves)); /// /// Gets an array of one dimensional curves @@ -31,16 +28,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { if (base.Equals(other) && other is IccCurveSetProcessElement element) { - return this.Curves.SequenceEqual(element.Curves); + return this.Curves.AsSpan().SequenceEqual(element.Curves); } return false; } /// - public bool Equals(IccCurveSetProcessElement other) - { - return this.Equals((IccMultiProcessElement)other); - } + public bool Equals(IccCurveSetProcessElement other) => this.Equals((IccMultiProcessElement)other); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs index b4d711f59..813271d48 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs @@ -80,10 +80,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc public double[][] ChannelValues { get; } /// - public override bool Equals(IccTagDataEntry other) - { - return other is IccChromaticityTagDataEntry entry && this.Equals(entry); - } + public override bool Equals(IccTagDataEntry other) => other is IccChromaticityTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccChromaticityTagDataEntry other) @@ -102,10 +99,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } /// - public override bool Equals(object obj) - { - return obj is IccChromaticityTagDataEntry other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccChromaticityTagDataEntry other && this.Equals(other); /// public override int GetHashCode() @@ -162,7 +156,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc for (int i = 0; i < this.ChannelValues.Length; i++) { - if (!this.ChannelValues[i].SequenceEqual(entry.ChannelValues[i])) + if (!this.ChannelValues[i].AsSpan().SequenceEqual(entry.ChannelValues[i])) { return false; } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs index 28d01450c..aff33ff82 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -42,10 +41,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc public IccColorantTableEntry[] ColorantData { get; } /// - public override bool Equals(IccTagDataEntry other) - { - return other is IccColorantTableTagDataEntry entry && this.Equals(entry); - } + public override bool Equals(IccTagDataEntry other) => other is IccColorantTableTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccColorantTableTagDataEntry other) @@ -60,19 +56,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return true; } - return base.Equals(other) && this.ColorantData.SequenceEqual(other.ColorantData); + return base.Equals(other) && this.ColorantData.AsSpan().SequenceEqual(other.ColorantData); } /// - public override bool Equals(object obj) - { - return obj is IccColorantTableTagDataEntry other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccColorantTableTagDataEntry other && this.Equals(other); /// - public override int GetHashCode() - { - return HashCode.Combine(this.Signature, this.ColorantData); - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.ColorantData); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs index d84fc1431..8f7db49ad 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; using System.Numerics; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc @@ -71,7 +70,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc bool is3By3 = matrix.GetLength(0) == 3 && matrix.GetLength(1) == 3; Guard.IsTrue(is3By3, nameof(matrix), "Matrix must have a size of three by three"); - this.Matrix = this.CreateMatrix(matrix); + this.Matrix = CreateMatrix(matrix); this.InputValues = inputValues ?? throw new ArgumentNullException(nameof(inputValues)); this.ClutValues = clutValues ?? throw new ArgumentNullException(nameof(clutValues)); this.OutputValues = outputValues ?? throw new ArgumentNullException(nameof(outputValues)); @@ -111,10 +110,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc public IccLut[] OutputValues { get; } /// - public override bool Equals(IccTagDataEntry other) - { - return other is IccLut16TagDataEntry entry && this.Equals(entry); - } + public override bool Equals(IccTagDataEntry other) => other is IccLut16TagDataEntry entry && this.Equals(entry); /// public bool Equals(IccLut16TagDataEntry other) @@ -131,16 +127,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return base.Equals(other) && this.Matrix.Equals(other.Matrix) - && this.InputValues.SequenceEqual(other.InputValues) + && this.InputValues.AsSpan().SequenceEqual(other.InputValues) && this.ClutValues.Equals(other.ClutValues) - && this.OutputValues.SequenceEqual(other.OutputValues); + && this.OutputValues.AsSpan().SequenceEqual(other.OutputValues); } /// - public override bool Equals(object obj) - { - return obj is IccLut16TagDataEntry other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccLut16TagDataEntry other && this.Equals(other); /// public override int GetHashCode() @@ -153,7 +146,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc this.OutputValues); } - private Matrix4x4 CreateMatrix(float[,] matrix) + private static Matrix4x4 CreateMatrix(float[,] matrix) { return new Matrix4x4( matrix[0, 0], diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs index 5c8ce2d2c..3a1859a1c 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs @@ -114,10 +114,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc public IccLut[] OutputValues { get; } /// - public override bool Equals(IccTagDataEntry other) - { - return other is IccLut8TagDataEntry entry && this.Equals(entry); - } + public override bool Equals(IccTagDataEntry other) => other is IccLut8TagDataEntry entry && this.Equals(entry); /// public bool Equals(IccLut8TagDataEntry other) @@ -134,16 +131,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return base.Equals(other) && this.Matrix.Equals(other.Matrix) - && this.InputValues.SequenceEqual(other.InputValues) + && this.InputValues.AsSpan().SequenceEqual(other.InputValues) && this.ClutValues.Equals(other.ClutValues) - && this.OutputValues.SequenceEqual(other.OutputValues); + && this.OutputValues.AsSpan().SequenceEqual(other.OutputValues); } /// - public override bool Equals(object obj) - { - return obj is IccLut8TagDataEntry other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccLut8TagDataEntry other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs index 4cee555e5..88e3c4cae 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using System.Numerics; +// TODO: Review the use of base IccTagDataEntry comparison. namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// @@ -15,12 +16,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// Initializes a new instance of the class. /// - /// A Curve - /// CLUT - /// M Curve + /// B Curve /// Two dimensional conversion matrix (3x3) /// One dimensional conversion matrix (3x1) - /// B Curve + /// M Curve + /// CLUT + /// A Curve public IccLutAToBTagDataEntry( IccTagDataEntry[] curveB, float[,] matrix3x3, @@ -35,12 +36,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// Initializes a new instance of the class. /// - /// A Curve - /// CLUT - /// M Curve + /// B Curve /// Two dimensional conversion matrix (3x3) /// One dimensional conversion matrix (3x1) - /// B Curve + /// M Curve + /// CLUT + /// A Curve /// Tag Signature public IccLutAToBTagDataEntry( IccTagDataEntry[] curveB, @@ -145,10 +146,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc public IccTagDataEntry[] CurveA { get; } /// - public override bool Equals(IccTagDataEntry other) - { - return other is IccLutAToBTagDataEntry entry && this.Equals(entry); - } + public override bool Equals(IccTagDataEntry other) => other is IccLutAToBTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccLutAToBTagDataEntry other) @@ -169,23 +167,18 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc && this.Matrix3x3.Equals(other.Matrix3x3) && this.Matrix3x1.Equals(other.Matrix3x1) && this.ClutValues.Equals(other.ClutValues) - && this.EqualsCurve(this.CurveB, other.CurveB) - && this.EqualsCurve(this.CurveM, other.CurveM) - && this.EqualsCurve(this.CurveA, other.CurveA); + && EqualsCurve(this.CurveB, other.CurveB) + && EqualsCurve(this.CurveM, other.CurveM) + && EqualsCurve(this.CurveA, other.CurveA); } /// - public override bool Equals(object obj) - { - return obj is IccLutAToBTagDataEntry other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccLutAToBTagDataEntry other && this.Equals(other); /// public override int GetHashCode() { -#pragma warning disable SA1129 // Do not use default value type constructor - var hashCode = new HashCode(); -#pragma warning restore SA1129 // Do not use default value type constructor + HashCode hashCode = default; hashCode.Add(this.Signature); hashCode.Add(this.InputChannelCount); @@ -200,7 +193,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return hashCode.ToHashCode(); } - private bool EqualsCurve(IccTagDataEntry[] thisCurves, IccTagDataEntry[] entryCurves) + private static bool EqualsCurve(IccTagDataEntry[] thisCurves, IccTagDataEntry[] entryCurves) { bool thisNull = thisCurves is null; bool entryNull = entryCurves is null; @@ -243,10 +236,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc && this.CurveA != null; } - private bool IsB() - { - return this.CurveB != null; - } + private bool IsB() => this.CurveB != null; private void VerifyCurve(IccTagDataEntry[] curves, string name) { diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs index 8e9479ff8..f8bf3f042 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using System.Numerics; +// TODO: Review the use of base IccTagDataEntry comparison. namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { /// @@ -15,12 +16,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// Initializes a new instance of the class. /// - /// A Curve - /// CLUT - /// M Curve + /// B Curve /// Two dimensional conversion matrix (3x3) /// One dimensional conversion matrix (3x1) - /// B Curve + /// M Curve + /// CLUT + /// A Curve public IccLutBToATagDataEntry( IccTagDataEntry[] curveB, float[,] matrix3x3, @@ -35,12 +36,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// Initializes a new instance of the class. /// - /// A Curve - /// CLUT - /// M Curve + /// B Curve /// Two dimensional conversion matrix (3x3) /// One dimensional conversion matrix (3x1) - /// B Curve + /// M Curve + /// CLUT + /// A Curve /// Tag Signature public IccLutBToATagDataEntry( IccTagDataEntry[] curveB, @@ -145,10 +146,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc public IccTagDataEntry[] CurveA { get; } /// - public override bool Equals(IccTagDataEntry other) - { - return other is IccLutBToATagDataEntry entry && this.Equals(entry); - } + public override bool Equals(IccTagDataEntry other) => other is IccLutBToATagDataEntry entry && this.Equals(entry); /// public bool Equals(IccLutBToATagDataEntry other) @@ -175,18 +173,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } /// - public override bool Equals(object obj) - { - return obj is IccLutBToATagDataEntry other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccLutBToATagDataEntry other && this.Equals(other); /// public override int GetHashCode() { -#pragma warning disable SA1129 // Do not use default value type constructor - var hashCode = new HashCode(); -#pragma warning restore SA1129 // Do not use default value type constructor - + HashCode hashCode = default; hashCode.Add(this.Signature); hashCode.Add(this.InputChannelCount); hashCode.Add(this.OutputChannelCount); @@ -243,10 +235,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc && this.CurveA != null; } - private bool IsB() - { - return this.CurveB != null; - } + private bool IsB() => this.CurveB != null; private void VerifyCurve(IccTagDataEntry[] curves, string name) { diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs index 3084ff612..34a027126 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -56,7 +55,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return true; } - return base.Equals(other) && this.Texts.SequenceEqual(other.Texts); + return base.Equals(other) && this.Texts.AsSpan().SequenceEqual(other.Texts); } /// diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs index dc78e7520..f2713e8ce 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs @@ -57,10 +57,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override bool Equals(IccTagDataEntry other) - { - var entry = other as IccMultiProcessElementsTagDataEntry; - return entry != null && this.Equals(entry); - } + => other is IccMultiProcessElementsTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccMultiProcessElementsTagDataEntry other) @@ -78,14 +75,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return base.Equals(other) && this.InputChannelCount == other.InputChannelCount && this.OutputChannelCount == other.OutputChannelCount - && this.Data.SequenceEqual(other.Data); + && this.Data.AsSpan().SequenceEqual(other.Data); } /// - public override bool Equals(object obj) - { - return obj is IccMultiProcessElementsTagDataEntry other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccMultiProcessElementsTagDataEntry other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs index 30516578f..4fd0cfcfb 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc && string.Equals(this.Prefix, other.Prefix) && string.Equals(this.Suffix, other.Suffix) && this.VendorFlags == other.VendorFlags - && this.Colors.SequenceEqual(other.Colors); + && this.Colors.AsSpan().SequenceEqual(other.Colors); } /// diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs index 3c3a6c761..7897c394f 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -29,9 +28,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// Tag Signature public IccProfileSequenceDescTagDataEntry(IccProfileDescription[] descriptions, IccProfileTag tagSignature) : base(IccTypeSignature.ProfileSequenceDesc, tagSignature) - { - this.Descriptions = descriptions ?? throw new ArgumentNullException(nameof(descriptions)); - } + => this.Descriptions = descriptions ?? throw new ArgumentNullException(nameof(descriptions)); /// /// Gets the profile descriptions @@ -40,9 +37,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public override bool Equals(IccTagDataEntry other) - { - return other is IccProfileSequenceDescTagDataEntry entry && this.Equals(entry); - } + => other is IccProfileSequenceDescTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccProfileSequenceDescTagDataEntry other) @@ -57,14 +52,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return true; } - return base.Equals(other) && this.Descriptions.SequenceEqual(other.Descriptions); + return base.Equals(other) && this.Descriptions.AsSpan().SequenceEqual(other.Descriptions); } /// public override bool Equals(object obj) - { - return obj is IccProfileSequenceDescTagDataEntry other && this.Equals(other); - } + => obj is IccProfileSequenceDescTagDataEntry other && this.Equals(other); /// public override int GetHashCode() => HashCode.Combine(this.Signature, this.Descriptions); diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs index 6051bf841..e9c8af9be 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs @@ -51,10 +51,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc public IccResponseCurve[] Curves { get; } /// - public override bool Equals(IccTagDataEntry other) - { - return other is IccResponseCurveSet16TagDataEntry entry && this.Equals(entry); - } + public override bool Equals(IccTagDataEntry other) => other is IccResponseCurveSet16TagDataEntry entry && this.Equals(entry); /// public bool Equals(IccResponseCurveSet16TagDataEntry other) @@ -71,14 +68,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc return base.Equals(other) && this.ChannelCount == other.ChannelCount - && this.Curves.SequenceEqual(other.Curves); + && this.Curves.AsSpan().SequenceEqual(other.Curves); } /// - public override bool Equals(object obj) - { - return obj is IccResponseCurveSet16TagDataEntry other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccResponseCurveSet16TagDataEntry other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs index 053181a26..09bec9b7a 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -26,10 +25,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// The array data /// Tag Signature public IccUInt64ArrayTagDataEntry(ulong[] data, IccProfileTag tagSignature) - : base(IccTypeSignature.UInt64Array, tagSignature) - { - this.Data = data ?? throw new ArgumentNullException(nameof(data)); - } + : base(IccTypeSignature.UInt64Array, tagSignature) => this.Data = data ?? throw new ArgumentNullException(nameof(data)); /// /// Gets the array data @@ -37,10 +33,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc public ulong[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) - { - return other is IccUInt64ArrayTagDataEntry entry && this.Equals(entry); - } + public override bool Equals(IccTagDataEntry other) => other is IccUInt64ArrayTagDataEntry entry && this.Equals(entry); /// public bool Equals(IccUInt64ArrayTagDataEntry other) @@ -59,10 +52,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } /// - public override bool Equals(object obj) - { - return obj is IccUInt64ArrayTagDataEntry other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccUInt64ArrayTagDataEntry other && this.Equals(other); /// public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data); diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs index c53ba9520..bd8f784ae 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs @@ -134,10 +134,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc } /// - public override bool Equals(object obj) - { - return obj is IccClut other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccClut other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs index 22bf1bb76..3c640ab03 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -55,10 +54,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// True if the parameter is equal to the parameter; otherwise, false. /// - public static bool operator ==(IccNamedColor left, IccNamedColor right) - { - return left.Equals(right); - } + public static bool operator ==(IccNamedColor left, IccNamedColor right) => left.Equals(right); /// /// Compares two objects for equality. @@ -68,23 +64,17 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// /// True if the parameter is not equal to the parameter; otherwise, false. /// - public static bool operator !=(IccNamedColor left, IccNamedColor right) - { - return !left.Equals(right); - } + public static bool operator !=(IccNamedColor left, IccNamedColor right) => !left.Equals(right); /// - public override bool Equals(object obj) - { - return obj is IccNamedColor other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccNamedColor other && this.Equals(other); /// public bool Equals(IccNamedColor other) { return this.Name.Equals(other.Name) - && this.PcsCoordinates.SequenceEqual(other.PcsCoordinates) - && this.DeviceCoordinates.SequenceEqual(other.DeviceCoordinates); + && this.PcsCoordinates.AsSpan().SequenceEqual(other.PcsCoordinates) + && this.DeviceCoordinates.AsSpan().SequenceEqual(other.DeviceCoordinates); } /// diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs index 76ac5961d..d630f015e 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -68,18 +67,15 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public bool Equals(IccProfileDescription other) => - this.DeviceManufacturer == other.DeviceManufacturer && - this.DeviceModel == other.DeviceModel && - this.DeviceAttributes == other.DeviceAttributes && - this.TechnologyInformation == other.TechnologyInformation && - this.DeviceManufacturerInfo.SequenceEqual(other.DeviceManufacturerInfo) && - this.DeviceModelInfo.SequenceEqual(other.DeviceModelInfo); + this.DeviceManufacturer == other.DeviceManufacturer + && this.DeviceModel == other.DeviceModel + && this.DeviceAttributes == other.DeviceAttributes + && this.TechnologyInformation == other.TechnologyInformation + && this.DeviceManufacturerInfo.AsSpan().SequenceEqual(other.DeviceManufacturerInfo) + && this.DeviceModelInfo.AsSpan().SequenceEqual(other.DeviceModelInfo); /// - public override bool Equals(object obj) - { - return obj is IccProfileDescription other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccProfileDescription other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs index 9eb9fc7c3..6bf420b49 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Linq; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { @@ -34,14 +33,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// public bool Equals(IccProfileSequenceIdentifier other) => - this.Id.Equals(other.Id) && - this.Description.SequenceEqual(other.Description); + this.Id.Equals(other.Id) + && this.Description.AsSpan().SequenceEqual(other.Description); /// - public override bool Equals(object obj) - { - return obj is IccProfileSequenceIdentifier other && this.Equals(other); - } + public override bool Equals(object obj) => obj is IccProfileSequenceIdentifier other && this.Equals(other); /// public override int GetHashCode() => HashCode.Combine(this.Id, this.Description); diff --git a/src/ImageSharp/Processing/ResizeOptions.cs b/src/ImageSharp/Processing/ResizeOptions.cs index 0d5bfe38b..ee0dde6b2 100644 --- a/src/ImageSharp/Processing/ResizeOptions.cs +++ b/src/ImageSharp/Processing/ResizeOptions.cs @@ -1,8 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Collections.Generic; -using System.Linq; using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.Primitives; @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Gets or sets the center coordinates. /// - public IEnumerable CenterCoordinates { get; set; } = Enumerable.Empty(); + public IEnumerable CenterCoordinates { get; set; } = Array.Empty(); /// /// Gets or sets the target size. From e2651e7f45cda13280472bdd42f55ea2391a1832 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 1 Jun 2019 05:14:03 -0700 Subject: [PATCH 211/223] Updating the repo to use Directory.Build.props/targets files (#920) * Updating the repo to use Directory.Build.props/targets files * Adding an InternalsVisibleTo for DynamicProxyGenAssembly2, PublicKeyToken=null * Removing duplicate includes from the ImageSharp.csproj * Updating the .gitattributes file to explicitly list the line endings * Removing the ImageSharp.ruleset file, as the one from standards should be used instead * Updating the package version management to use `PackageReference Update` --- .editorconfig | 369 +++++++++++++++++- .gitattributes | 151 ++++--- Directory.Build.props | 77 ++++ Directory.Build.targets | 47 +++ ImageSharp.ruleset | 15 - ImageSharp.sln | 361 ++++++++++++++++- NuGet.config | 9 - src/Directory.Build.props | 41 ++ src/Directory.Build.targets | 55 +++ .../ImageSharp.Drawing.csproj | 50 +-- .../Properties/AssemblyInfo.cs | 4 - src/ImageSharp/ImageSharp.csproj | 204 +++++----- src/ImageSharp/Properties/AssemblyInfo.cs | 5 +- src/Shared/AssemblyInfo.Common.cs | 15 - tests/Directory.Build.props | 30 ++ tests/Directory.Build.targets | 19 + .../ImageSharp.Benchmarks.csproj | 36 +- .../ImageSharp.Sandbox46.csproj | 36 +- .../Properties/AssemblyInfo.cs | 15 - .../ImageSharp.Tests/ImageSharp.Tests.csproj | 57 +-- 20 files changed, 1236 insertions(+), 360 deletions(-) create mode 100644 Directory.Build.props create mode 100644 Directory.Build.targets delete mode 100644 ImageSharp.ruleset delete mode 100644 NuGet.config create mode 100644 src/Directory.Build.props create mode 100644 src/Directory.Build.targets delete mode 100644 src/ImageSharp.Drawing/Properties/AssemblyInfo.cs delete mode 100644 src/Shared/AssemblyInfo.Common.cs create mode 100644 tests/Directory.Build.props create mode 100644 tests/Directory.Build.targets delete mode 100644 tests/ImageSharp.Sandbox46/Properties/AssemblyInfo.cs diff --git a/.editorconfig b/.editorconfig index b725c5cce..8f0e28eec 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,20 +1,371 @@ -# top-most EditorConfig file +############################################################################### +# EditorConfig is awesome: http://EditorConfig.org +############################################################################### + +############################################################################### +# Top-most EditorConfig file +############################################################################### root = true -[*.cs] +############################################################################### +# Set default behavior to: +# a UTF-8 encoding, +# Unix-style line endings, +# a newline ending the file, +# 4 space indentation, and +# trimming of trailing whitespace +############################################################################### +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true indent_style = space indent_size = 4 -csharp_style_var_for_built_in_types = false:warning -csharp_style_var_elsewhere = false:warning -csharp_style_var_when_type_is_apparent = true:warning +trim_trailing_whitespace = true + +############################################################################### +# Set file behavior to: +# 2 space indentation +############################################################################### +[*.{cmd,config,csproj,json,props,ps1,resx,sh,targets}] +indent_size = 2 + +############################################################################### +# Set file behavior to: +# Windows-style line endings, and +# tabular indentation +############################################################################### +[*.sln] end_of_line = crlf +indent_style = tab + +############################################################################### +# Set dotnet naming rules to: +# suggest async members be pascal case suffixed with Async +# suggest const declarations be pascal case +# suggest interfaces be pascal case prefixed with I +# suggest parameters be camel case +# suggest private and internal static fields be camel case +# suggest private and internal fields be camel case +# suggest public and protected declarations be pascal case +# suggest static readonly declarations be pascal case +# suggest type parameters be prefixed with T +############################################################################### +[*.cs] +dotnet_naming_rule.async_members_should_be_pascal_case_suffixed_with_async.severity = suggestion +dotnet_naming_rule.async_members_should_be_pascal_case_suffixed_with_async.style = pascal_case_suffixed_with_async +dotnet_naming_rule.async_members_should_be_pascal_case_suffixed_with_async.symbols = async_members + +dotnet_naming_rule.const_declarations_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.const_declarations_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.const_declarations_should_be_pascal_case.symbols = const_declarations + +dotnet_naming_rule.interfaces_should_be_pascal_case_prefixed_with_i.severity = suggestion +dotnet_naming_rule.interfaces_should_be_pascal_case_prefixed_with_i.style = pascal_case_prefixed_with_i +dotnet_naming_rule.interfaces_should_be_pascal_case_prefixed_with_i.symbols = interfaces + +dotnet_naming_rule.parameters_should_be_camel_case.severity = suggestion +dotnet_naming_rule.parameters_should_be_camel_case.style = camel_case +dotnet_naming_rule.parameters_should_be_camel_case.symbols = parameters + +dotnet_naming_rule.private_and_internal_static_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.private_and_internal_static_fields_should_be_camel_case.style = camel_case +dotnet_naming_rule.private_and_internal_static_fields_should_be_camel_case.symbols = private_and_internal_static_fields + +dotnet_naming_rule.private_and_internal_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.private_and_internal_fields_should_be_camel_case.style = camel_case +dotnet_naming_rule.private_and_internal_fields_should_be_camel_case.symbols = private_and_internal_fields + +dotnet_naming_rule.public_and_protected_declarations_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.public_and_protected_declarations_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.public_and_protected_declarations_should_be_pascal_case.symbols = public_and_protected_declarations + +dotnet_naming_rule.static_readonly_declarations_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.static_readonly_declarations_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.static_readonly_declarations_should_be_pascal_case.symbols = static_readonly_declarations + +dotnet_naming_rule.type_parameters_should_be_pascal_case_prefixed_with_t.severity = suggestion +dotnet_naming_rule.type_parameters_should_be_pascal_case_prefixed_with_t.style = pascal_case_prefixed_with_t +dotnet_naming_rule.type_parameters_should_be_pascal_case_prefixed_with_t.symbols = type_parameters + +############################################################################### +# Set dotnet naming styles to define: +# camel case +# pascal case +# pascal case suffixed with Async +# pascal case prefixed with I +# pascal case prefixed with T +############################################################################### +[*.cs] +dotnet_naming_style.camel_case.capitalization = camel_case + +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case_suffixed_with_async.capitalization = pascal_case +dotnet_naming_style.pascal_case_suffixed_with_async.required_suffix = Async + +dotnet_naming_style.pascal_case_prefixed_with_i.capitalization = pascal_case +dotnet_naming_style.pascal_case_prefixed_with_i.required_prefix = I + +dotnet_naming_style.pascal_case_prefixed_with_t.capitalization = pascal_case +dotnet_naming_style.pascal_case_prefixed_with_t.required_prefix = T + +############################################################################### +# Set dotnet naming symbols to: +# async members +# const declarations +# interfaces +# private and internal fields +# private and internal static fields +# public and protected declarations +# static readonly declarations +# type parameters +############################################################################### +[*.cs] +dotnet_naming_symbols.async_members.required_modifiers = async + +dotnet_naming_symbols.const_declarations.required_modifiers = const + +dotnet_naming_symbols.interfaces.applicable_kinds = interface + +dotnet_naming_symbols.parameters.applicable_kinds = parameter + +dotnet_naming_symbols.private_and_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_symbols.private_and_internal_fields.applicable_kinds = field + +dotnet_naming_symbols.private_and_internal_static_fields.applicable_accessibilities = private, internal +dotnet_naming_symbols.private_and_internal_static_fields.applicable_kinds = field +dotnet_naming_symbols.private_and_internal_static_fields.required_modifiers = static + +dotnet_naming_symbols.public_and_protected_declarations.applicable_accessibilities = public, protected + +dotnet_naming_symbols.static_readonly_declarations.required_modifiers = static, readonly + +dotnet_naming_symbols.type_parameters.applicable_kinds = type_parameter + +############################################################################### +# Set dotnet sort options to: +# do not separate import directives into groups, and +# sort system directives first +############################################################################### +[*.cs] +dotnet_separate_import_directive_groups = false dotnet_sort_system_directives_first = true + +############################################################################### +# Set dotnet style options to: +# suggest null-coalescing expressions, +# suggest collection-initializers, +# suggest explicit tuple names, +# suggest null-propogation +# suggest object-initializers, +# generate parentheses in arithmetic binary operators for clarity, +# generate parentheses in other binary operators for clarity, +# don't generate parentheses in other operators if unnecessary, +# generate parentheses in relational binary operators for clarity, +# warn when not using predefined-types for locals, parameters, and members, +# generate predefined-types of type names for member access, +# generate auto properties, +# suggest compound assignment, +# generate conditional expression over assignment, +# generate conditional expression over return, +# suggest inferred anonymous types, +# suggest inferred tuple names, +# suggest 'is null' checks over '== null', +# don't generate 'this.' and 'Me.' for events, +# warn when not using 'this.' and 'Me.' for fields, +# warn when not using 'this.' and 'Me.' for methods, +# warn when not using 'this.' and 'Me.' for properties, +# suggest readonly fields, and +# generate accessibility modifiers for non interface members +############################################################################### +[*.cs] +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_object_initializer = true:suggestion + +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent + dotnet_style_predefined_type_for_locals_parameters_members = true:warning -dotnet_style_predefined_type_for_member_access = true:warning +dotnet_style_predefined_type_for_member_access = true:silent + +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion + +dotnet_style_qualification_for_event = false:silent dotnet_style_qualification_for_field = true:warning dotnet_style_qualification_for_method = true:warning dotnet_style_qualification_for_property = true:warning -[*.tt] -indent_style = space -indent_size = 4 \ No newline at end of file +dotnet_style_readonly_field = true:suggestion +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent + +############################################################################### +# Set dotnet style options to: +# suggest removing all unused parameters +############################################################################### +[*.cs] +dotnet_code_quality_unused_parameters = all:suggestion + +############################################################################### +# Set csharp indent options to: +# indent block contents, +# not indent braces, +# indent case contents, +# not indent case contents when block, +# indent labels one less than the current, and +# indent switch labels +############################################################################### +[*.cs] +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = false +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +############################################################################### +# Set csharp new-line options to: +# insert a new-line before "catch", +# insert a new-line before "else", +# insert a new-line before "finally", +# insert a new-line before members in anonymous-types, +# insert a new-line before members in object-initializers, and +# insert a new-line before all open braces +############################################################################### +[*.cs] +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true + +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true + +csharp_new_line_before_open_brace = all + +############################################################################### +# Set csharp preserve options to: +# preserve single-line blocks, and +# preserve single-line statements +############################################################################### +[*.cs] +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +############################################################################### +# Set csharp space options to: +# remove any space after a cast, +# add a space after the colon in an inheritance clause, +# add a space after a comma, +# remove any space after a dot, +# add a space after keywords in control flow statements, +# add a space after a semicolon in a "for" statement, +# add a space before and after binary operators, +# remove space around declaration statements, +# add a space before the colon in an inheritance clause, +# remove any space before a comma, +# remove any space before a dot, +# remove any space before an open square-bracket, +# remove any space before a semicolon in a "for" statement, +# remove any space between empty square-brackets, +# remove any space between a method call's empty parameter list parenthesis, +# remove any space between a method call's name and its opening parenthesis, +# remove any space between a method call's parameter list parenthesis, +# remove any space between a method declaration's empty parameter list parenthesis, +# remove any space between a method declaration's name and its openening parenthesis, +# remove any space between a method declaration's parameter list parenthesis, +# remove any space between parentheses, and +# remove any space between square brackets +############################################################################### +[*.cs] +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true + +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = do_not_ignore + +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false + +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +############################################################################### +# Set csharp style options to: +# generate braces, +# suggest simple default expressions, +# generate a preferred modifier order, +# suggest conditional delegate calls, +# suggest deconstructed variable declarations, +# generate expression-bodied accessors, +# don't generate expression-bodied constructors, +# generate expression-bodied indexers, +# generate expression-bodied lambdas, +# don't generate expression-bodied methods, +# don't generate expression-bodied operators, +# generate expression-bodied properties, +# suggest inlined variable declarations, +# suggest local over anonymous functions, +# suggest pattern-matching over "as" with "null" check, +# suggest pattern-matching over "is" with "cast" check, +# suggest throw expressions, +# generate a discard variable for unused value expression statements, +# suggest a discard variable for unused assignments, +# warn when using var for built-in types, +# warn when using var when the type is not apparent, and +# warn when not using var when the type is apparent +############################################################################### +[*.cs] +csharp_prefer_braces = true:silent +csharp_prefer_simple_default_expression = true:suggestion +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent + +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion + +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent + +csharp_style_inlined_variable_declaration = true:suggestion + +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion + +csharp_style_throw_expression = true:suggestion + +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_unused_value_assignment_preference = discard_variable:suggestion + +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_elsewhere = false:warning +csharp_style_var_when_type_is_apparent = true:warning diff --git a/.gitattributes b/.gitattributes index a664be3a8..adef3cc9e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,49 +1,108 @@ -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain +############################################################################### +# Set default behavior to: +# treat as text and +# normalize to Unix-style line endings +############################################################################### +* text eol=lf -*.jpg binary -*.png binary -*.gif binary +############################################################################### +# Set explicit file behavior to: +# treat as text and +# normalize to Unix-style line endings +############################################################################### +*.asm text eol=lf +*.c text eol=lf +*.clj text eol=lf +*.cmd text eol=lf +*.cpp text eol=lf +*.css text eol=lf +*.cxx text eol=lf +*.config text eol=lf +*.DotSettings text eol=lf +*.erl text eol=lf +*.fs text eol=lf +*.fsx text eol=lf +*.h text eol=lf +*.htm text eol=lf +*.html text eol=lf +*.hs text eol=lf +*.hxx text eol=lf +*.java text eol=lf +*.js text eol=lf +*.json text eol=lf +*.less text eol=lf +*.lisp text eol=lf +*.lua text eol=lf +*.m text eol=lf +*.md text eol=lf +*.php text eol=lf +*.props text eol=lf +*.ps1 text eol=lf +*.py text eol=lf +*.rb text eol=lf +*.resx text eol=lf +*.runsettings text eol=lf +*.ruleset text eol=lf +*.sass text eol=lf +*.scss text eol=lf +*.sh text eol=lf +*.sql text eol=lf +*.svg text eol=lf +*.targets text eol=lf +*.tt text eol=lf +*.ttinclude text eol=lf +*.txt text eol=lf +*.vb text eol=lf +*.yml text eol=lf -*.cs text=auto diff=csharp -*.vb text=auto -*.c text=auto -*.cpp text=auto -*.cxx text=auto -*.h text=auto -*.hxx text=auto -*.py text=auto -*.rb text=auto -*.java text=auto -*.html text=auto -*.htm text=auto -*.css text=auto -*.scss text=auto -*.sass text=auto -*.less text=auto -*.js text=auto -*.lisp text=auto -*.clj text=auto -*.sql text=auto -*.php text=auto -*.lua text=auto -*.m text=auto -*.asm text=auto -*.erl text=auto -*.fs text=auto -*.fsx text=auto -*.hs text=auto +############################################################################### +# Set explicit file behavior to: +# treat as text +# normalize to Unix-style line endings and +# diff as csharp +############################################################################### +*.cs text eol=lf diff=csharp -*.csproj text=auto merge=union -*.vbproj text=auto merge=union -*.fsproj text=auto merge=union -*.dbproj text=auto merge=union -*.sln text=auto eol=crlf merge=union +############################################################################### +# Set explicit file behavior to: +# treat as text +# normalize to Unix-style line endings and +# use a union merge when resoling conflicts +############################################################################### +*.csproj text eol=lf merge=union +*.dbproj text eol=lf merge=union +*.fsproj text eol=lf merge=union +*.ncrunchproject text eol=lf merge=union +*.vbproj text eol=lf merge=union + +############################################################################### +# Set explicit file behavior to: +# treat as text +# normalize to Windows-style line endings and +# use a union merge when resoling conflicts +############################################################################### +*.sln text eol=crlf merge=union + +############################################################################### +# Set explicit file behavior to: +# treat as binary +############################################################################### +*.bmp binary +*.dll binary +*.exe binary +*.gif binary +*.jpg binary +*.png binary +*.ttf binary +*.snk binary + +############################################################################### +# Set explicit file behavior to: +# diff as plain text +############################################################################### +*.doc diff=astextplain +*.docx diff=astextplain +*.dot diff=astextplain +*.pdf diff=astextplain +*.pptx diff=astextplain +*.rtf diff=astextplain diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 000000000..9c92c14b8 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,77 @@ + + + + + + + + $(MSBuildThisFileDirectory)artifacts/ + $(ImageSharpProjectCategory)/$(MSBuildProjectName) + https://github.com/SixLabors/ImageSharp/ + + + + + true + $(BaseArtifactsPath)obj/$(BaseArtifactsPathSuffix)/ + portable + full + disable + true + false + true + true + + + + true + + + + + Six Labors and contributors + $(BaseArtifactsPath)bin/$(BaseArtifactsPathSuffix)/ + Six Labors + $(BaseArtifactsPath)pkg/$(BaseArtifactsPathSuffix)/$(Configuration)/ + SixLabors.ImageSharp + 0.0.1 + $(PackageVersion) + + + + + + $(MSBuildThisFileDirectory)standards/SixLabors.snk + Copyright © Six Labors and Contributors + strict;IOperation + true + 7.3 + en + true + https://raw.githubusercontent.com/SixLabors/Branding/master/icons/imagesharp/sixlabors.imagesharp.128.png + Apache-2.0 + $(RepositoryUrl) + true + git + + https://www.myget.org/F/sixlabors/api/v3/index.json; + https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; + https://api.nuget.org/v3/index.json; + + 002400000c8000009400000006020000002400005253413100040000010001000147e6fe6766715eec6cfed61f1e7dcdbf69748a3e355c67e9d8dfd953acab1d5e012ba34b23308166fdc61ee1d0390d5f36d814a6091dd4b5ed9eda5a26afced924c683b4bfb4b3d64b0586a57eff9f02b1f84e3cb0ddd518bd1697f2c84dcbb97eb8bb5c7801be12112ed0ec86db934b0e9a5171e6bb1384b6d2f7d54dfa97 + true + + + + + + + + diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 000000000..350439879 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,47 @@ + + + + + + + + $(DefineConstants);$(OS) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ImageSharp.ruleset b/ImageSharp.ruleset deleted file mode 100644 index d318b75c2..000000000 --- a/ImageSharp.ruleset +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/ImageSharp.sln b/ImageSharp.sln index 3c3817bf6..1fd5e2d8b 100644 --- a/ImageSharp.sln +++ b/ImageSharp.sln @@ -1,47 +1,356 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.12 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28902.138 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{C317F1B1-D75E-4C6D-83EB-80367343E0D7}" ProjectSection(SolutionItems) = preProject - standards\.editorconfig = standards\.editorconfig + .editorconfig = .editorconfig + .gitattributes = .gitattributes + .gitignore = .gitignore + .gitmodules = .gitmodules .travis.yml = .travis.yml appveyor.yml = appveyor.yml - .github\ISSUE_TEMPLATE\ask-question.md = .github\ISSUE_TEMPLATE\ask-question.md - .github\ISSUE_TEMPLATE\bug-report.md = .github\ISSUE_TEMPLATE\bug-report.md + build.cmd = build.cmd + build.ps1 = build.ps1 codecov.yml = codecov.yml CodeCoverage.runsettings = CodeCoverage.runsettings - .github\CONTRIBUTING.md = .github\CONTRIBUTING.md - .github\ISSUE_TEMPLATE\feature-request.md = .github\ISSUE_TEMPLATE\feature-request.md - features.md = features.md + Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets ImageSharp.sln.DotSettings = ImageSharp.sln.DotSettings - NuGet.config = NuGet.config - .github\PULL_REQUEST_TEMPLATE.md = .github\PULL_REQUEST_TEMPLATE.md + LICENSE = LICENSE README.md = README.md run-tests.ps1 = run-tests.ps1 - standards\SixLabors.ruleset = standards\SixLabors.ruleset - standards\stylecop.json = standards\stylecop.json + stylecop.json = stylecop.json EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{815C0625-CD3D-440F-9F80-2D83856AB7AE}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{1799C43E-5C54-4A8F-8D64-B1475241DB0D}" ProjectSection(SolutionItems) = preProject - src\README.md = src\README.md + .github\CONTRIBUTING.md = .github\CONTRIBUTING.md + .github\PULL_REQUEST_TEMPLATE.md = .github\PULL_REQUEST_TEMPLATE.md EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{56801022-D71A-4FBE-BC5B-CBA08E2284EC}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEMPLATE", "{FBE8C1AD-5AEC-4514-9B64-091D8E145865}" + ProjectSection(SolutionItems) = preProject + .github\ISSUE_TEMPLATE\ask-question.md = .github\ISSUE_TEMPLATE\ask-question.md + .github\ISSUE_TEMPLATE\bug-report.md = .github\ISSUE_TEMPLATE\bug-report.md + .github\ISSUE_TEMPLATE\feature-request.md = .github\ISSUE_TEMPLATE\feature-request.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".vscode", ".vscode", "{0274D4CF-9932-47CC-8E89-54DC05B8F06E}" + ProjectSection(SolutionItems) = preProject + .vscode\launch.json = .vscode\launch.json + .vscode\tasks.json = .vscode\tasks.json + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{E919DF0B-2607-4462-8FC0-5C98FE50F8C9}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{9E574A07-F879-4811-9C41-5CBDC6BAFDB7}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "icons", "icons", "{2B02E303-7CC6-4E15-97EE-DBE86B287553}" ProjectSection(SolutionItems) = preProject - src\Shared\AssemblyInfo.Common.cs = src\Shared\AssemblyInfo.Common.cs + build\icons\imagesharp-logo-128.png = build\icons\imagesharp-logo-128.png + build\icons\imagesharp-logo-256.png = build\icons\imagesharp-logo-256.png + build\icons\imagesharp-logo-32.png = build\icons\imagesharp-logo-32.png + build\icons\imagesharp-logo-512.png = build\icons\imagesharp-logo-512.png + build\icons\imagesharp-logo-64.png = build\icons\imagesharp-logo-64.png + build\icons\imagesharp-logo.png = build\icons\imagesharp-logo.png + build\icons\imagesharp-logo.svg = build\icons\imagesharp-logo.svg + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{815C0625-CD3D-440F-9F80-2D83856AB7AE}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + src\Directory.Build.targets = src\Directory.Build.targets + src\README.md = src\README.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp", "src\ImageSharp\ImageSharp.csproj", "{2AA31A1F-142C-43F4-8687-09ABCA4B3A26}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Drawing", "src\ImageSharp.Drawing\ImageSharp.Drawing.csproj", "{2E33181E-6E28-4662-A801-E2E7DC206029}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{56801022-D71A-4FBE-BC5B-CBA08E2284EC}" + ProjectSection(SolutionItems) = preProject + tests\Directory.Build.props = tests\Directory.Build.props + tests\Directory.Build.targets = tests\Directory.Build.targets + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CodeCoverage", "CodeCoverage", "{D4C5EC58-F8E6-4636-B9EE-C99D2578E5C6}" + ProjectSection(SolutionItems) = preProject + tests\CodeCoverage\CodeCoverage.cmd = tests\CodeCoverage\CodeCoverage.cmd + tests\CodeCoverage\packages.config = tests\CodeCoverage\packages.config + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Images", "Images", "{FA55F5DE-11A6-487D-ABA4-BC93A02717DD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Input", "Input", "{9DA226A1-8656-49A8-A58A-A8B5C081AD66}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bmp", "Bmp", "{1A82C5F6-90E0-4E97-BE16-A825C046B493}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Bmp\BitmapCoreHeaderQR.bmp = tests\Images\Input\Bmp\BitmapCoreHeaderQR.bmp + tests\Images\Input\Bmp\BITMAPV5HEADER.bmp = tests\Images\Input\Bmp\BITMAPV5HEADER.bmp + tests\Images\Input\Bmp\Car.bmp = tests\Images\Input\Bmp\Car.bmp + tests\Images\Input\Bmp\F.bmp = tests\Images\Input\Bmp\F.bmp + tests\Images\Input\Bmp\issue735.bmp = tests\Images\Input\Bmp\issue735.bmp + tests\Images\Input\Bmp\neg_height.bmp = tests\Images\Input\Bmp\neg_height.bmp + tests\Images\Input\Bmp\pal1.bmp = tests\Images\Input\Bmp\pal1.bmp + tests\Images\Input\Bmp\pal1p1.bmp = tests\Images\Input\Bmp\pal1p1.bmp + tests\Images\Input\Bmp\pal4.bmp = tests\Images\Input\Bmp\pal4.bmp + tests\Images\Input\Bmp\pal4rle.bmp = tests\Images\Input\Bmp\pal4rle.bmp + tests\Images\Input\Bmp\pal8-0.bmp = tests\Images\Input\Bmp\pal8-0.bmp + tests\Images\Input\Bmp\pal8gs.bmp = tests\Images\Input\Bmp\pal8gs.bmp + tests\Images\Input\Bmp\pal8offs.bmp = tests\Images\Input\Bmp\pal8offs.bmp + tests\Images\Input\Bmp\pal8os2sp.bmp = tests\Images\Input\Bmp\pal8os2sp.bmp + tests\Images\Input\Bmp\pal8os2v1_winv2.bmp = tests\Images\Input\Bmp\pal8os2v1_winv2.bmp + tests\Images\Input\Bmp\pal8os2v2-16.bmp = tests\Images\Input\Bmp\pal8os2v2-16.bmp + tests\Images\Input\Bmp\pal8os2v2.bmp = tests\Images\Input\Bmp\pal8os2v2.bmp + tests\Images\Input\Bmp\pal8v4.bmp = tests\Images\Input\Bmp\pal8v4.bmp + tests\Images\Input\Bmp\pal8v5.bmp = tests\Images\Input\Bmp\pal8v5.bmp + tests\Images\Input\Bmp\rgb16-565.bmp = tests\Images\Input\Bmp\rgb16-565.bmp + tests\Images\Input\Bmp\rgb16-565pal.bmp = tests\Images\Input\Bmp\rgb16-565pal.bmp + tests\Images\Input\Bmp\rgb16.bmp = tests\Images\Input\Bmp\rgb16.bmp + tests\Images\Input\Bmp\rgb16bfdef.bmp = tests\Images\Input\Bmp\rgb16bfdef.bmp + tests\Images\Input\Bmp\rgb24.bmp = tests\Images\Input\Bmp\rgb24.bmp + tests\Images\Input\Bmp\rgb32.bmp = tests\Images\Input\Bmp\rgb32.bmp + tests\Images\Input\Bmp\rgb32bf.bmp = tests\Images\Input\Bmp\rgb32bf.bmp + tests\Images\Input\Bmp\rgb32bfdef.bmp = tests\Images\Input\Bmp\rgb32bfdef.bmp + tests\Images\Input\Bmp\rgba32-1010102.bmp = tests\Images\Input\Bmp\rgba32-1010102.bmp + tests\Images\Input\Bmp\rgba32.bmp = tests\Images\Input\Bmp\rgba32.bmp + tests\Images\Input\Bmp\rgba32abf.bmp = tests\Images\Input\Bmp\rgba32abf.bmp + tests\Images\Input\Bmp\rgba32h56.bmp = tests\Images\Input\Bmp\rgba32h56.bmp + tests\Images\Input\Bmp\RunLengthEncoded-inverted.bmp = tests\Images\Input\Bmp\RunLengthEncoded-inverted.bmp + tests\Images\Input\Bmp\RunLengthEncoded.bmp = tests\Images\Input\Bmp\RunLengthEncoded.bmp + tests\Images\Input\Bmp\test16-inverted.bmp = tests\Images\Input\Bmp\test16-inverted.bmp + tests\Images\Input\Bmp\test16.bmp = tests\Images\Input\Bmp\test16.bmp + tests\Images\Input\Bmp\test8-inverted.bmp = tests\Images\Input\Bmp\test8-inverted.bmp + tests\Images\Input\Bmp\test8.bmp = tests\Images\Input\Bmp\test8.bmp + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gif", "Gif", "{EE3FB0B3-1C31-41E9-93AB-BA800560A868}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Gif\base_1x4.gif = tests\Images\Input\Gif\base_1x4.gif + tests\Images\Input\Gif\base_4x1.gif = tests\Images\Input\Gif\base_4x1.gif + tests\Images\Input\Gif\cheers.gif = tests\Images\Input\Gif\cheers.gif + tests\Images\Input\Gif\giphy.gif = tests\Images\Input\Gif\giphy.gif + tests\Images\Input\Gif\kumin.gif = tests\Images\Input\Gif\kumin.gif + tests\Images\Input\Gif\leo.gif = tests\Images\Input\Gif\leo.gif + tests\Images\Input\Gif\rings.gif = tests\Images\Input\Gif\rings.gif + tests\Images\Input\Gif\trans.gif = tests\Images\Input\Gif\trans.gif + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "issues", "issues", "{BF8DFDC1-CEE5-4A37-B216-D3085360C776}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Gif\issues\issue403_baddescriptorwidth.gif = tests\Images\Input\Gif\issues\issue403_baddescriptorwidth.gif + tests\Images\Input\Gif\issues\issue405_badappextlength252-2.gif = tests\Images\Input\Gif\issues\issue405_badappextlength252-2.gif + tests\Images\Input\Gif\issues\issue405_badappextlength252.gif = tests\Images\Input\Gif\issues\issue405_badappextlength252.gif + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Jpg", "Jpg", "{DB21FED7-E8CB-4B00-9EB2-9144D32A590A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "baseline", "baseline", "{195BA3D3-3E9F-4BC5-AB40-5F9FEB638146}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Jpg\baseline\AsianCarvingLowContrast.jpg = tests\Images\Input\Jpg\baseline\AsianCarvingLowContrast.jpg + tests\Images\Input\Jpg\baseline\badeof.jpg = tests\Images\Input\Jpg\baseline\badeof.jpg + tests\Images\Input\Jpg\baseline\badrst.jpg = tests\Images\Input\Jpg\baseline\badrst.jpg + tests\Images\Input\Jpg\baseline\Calliphora.jpg = tests\Images\Input\Jpg\baseline\Calliphora.jpg + tests\Images\Input\Jpg\baseline\cmyk.jpg = tests\Images\Input\Jpg\baseline\cmyk.jpg + tests\Images\Input\Jpg\baseline\exif.jpg = tests\Images\Input\Jpg\baseline\exif.jpg + tests\Images\Input\Jpg\baseline\Floorplan.jpg = tests\Images\Input\Jpg\baseline\Floorplan.jpg + tests\Images\Input\Jpg\baseline\gamma_dalai_lama_gray.jpg = tests\Images\Input\Jpg\baseline\gamma_dalai_lama_gray.jpg + tests\Images\Input\Jpg\baseline\Hiyamugi.jpg = tests\Images\Input\Jpg\baseline\Hiyamugi.jpg + tests\Images\Input\Jpg\baseline\jpeg400jfif.jpg = tests\Images\Input\Jpg\baseline\jpeg400jfif.jpg + tests\Images\Input\Jpg\baseline\jpeg420exif.jpg = tests\Images\Input\Jpg\baseline\jpeg420exif.jpg + tests\Images\Input\Jpg\baseline\jpeg420small.jpg = tests\Images\Input\Jpg\baseline\jpeg420small.jpg + tests\Images\Input\Jpg\baseline\jpeg444.jpg = tests\Images\Input\Jpg\baseline\jpeg444.jpg + tests\Images\Input\Jpg\baseline\Lake.jpg = tests\Images\Input\Jpg\baseline\Lake.jpg + tests\Images\Input\Jpg\baseline\MultiScanBaselineCMYK.jpg = tests\Images\Input\Jpg\baseline\MultiScanBaselineCMYK.jpg + tests\Images\Input\Jpg\baseline\ratio-1x1.jpg = tests\Images\Input\Jpg\baseline\ratio-1x1.jpg + tests\Images\Input\Jpg\baseline\Snake.jpg = tests\Images\Input\Jpg\baseline\Snake.jpg + tests\Images\Input\Jpg\baseline\testimgint.jpg = tests\Images\Input\Jpg\baseline\testimgint.jpg + tests\Images\Input\Jpg\baseline\testorig.jpg = tests\Images\Input\Jpg\baseline\testorig.jpg + tests\Images\Input\Jpg\baseline\testorig12.jpg = tests\Images\Input\Jpg\baseline\testorig12.jpg + tests\Images\Input\Jpg\baseline\turtle.jpg = tests\Images\Input\Jpg\baseline\turtle.jpg + tests\Images\Input\Jpg\baseline\ycck-subsample-1222.jpg = tests\Images\Input\Jpg\baseline\ycck-subsample-1222.jpg + tests\Images\Input\Jpg\baseline\ycck.jpg = tests\Images\Input\Jpg\baseline\ycck.jpg + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "JpegSnoopReports", "JpegSnoopReports", "{538F0EBD-4084-4EDB-93DD-6D35B733CA48}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Jpg\baseline\JpegSnoopReports\badeof.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\badeof.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\badrst.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\badrst.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\Calliphora.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\Calliphora.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\cmyk.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\cmyk.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\exif.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\exif.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\Floorplan.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\Floorplan.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\gamma_dalai_lama_gray.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\gamma_dalai_lama_gray.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\Hiyamugi.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\Hiyamugi.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\jpeg400jfif.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\jpeg400jfif.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\jpeg420exif.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\jpeg420exif.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\jpeg420small.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\jpeg420small.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\jpeg444.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\jpeg444.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\Lake.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\Lake.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\MultiScanBaselineCMYK.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\MultiScanBaselineCMYK.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\ratio-1x1.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\ratio-1x1.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\Snake.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\Snake.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\testimgint.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\testimgint.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\testorig.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\testorig.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\turtle.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\turtle.jpg.txt + tests\Images\Input\Jpg\baseline\JpegSnoopReports\ycck.jpg.txt = tests\Images\Input\Jpg\baseline\JpegSnoopReports\ycck.jpg.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "issues", "issues", "{5C9B689F-B96D-47BE-A208-C23B1B2A8570}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Jpg\issues\Issue159-MissingFF00-Progressive-Bedroom.jpg = tests\Images\Input\Jpg\issues\Issue159-MissingFF00-Progressive-Bedroom.jpg + tests\Images\Input\Jpg\issues\Issue159-MissingFF00-Progressive-Girl.jpg = tests\Images\Input\Jpg\issues\Issue159-MissingFF00-Progressive-Girl.jpg + tests\Images\Input\Jpg\issues\Issue178-BadCoeffsProgressive-Lemon.jpg = tests\Images\Input\Jpg\issues\Issue178-BadCoeffsProgressive-Lemon.jpg + tests\Images\Input\Jpg\issues\Issue214-CriticalEOF.jpg = tests\Images\Input\Jpg\issues\Issue214-CriticalEOF.jpg + tests\Images\Input\Jpg\issues\Issue385-BadZigZag-Progressive.jpg = tests\Images\Input\Jpg\issues\Issue385-BadZigZag-Progressive.jpg + tests\Images\Input\Jpg\issues\Issue394-MultiHuffmanBaseline-Speakers.jpg = tests\Images\Input\Jpg\issues\Issue394-MultiHuffmanBaseline-Speakers.jpg + tests\Images\Input\Jpg\issues\Issue517-No-EOI-Progressive.jpg = tests\Images\Input\Jpg\issues\Issue517-No-EOI-Progressive.jpg + tests\Images\Input\Jpg\issues\Issue518-Bad-RST-Progressive.jpg = tests\Images\Input\Jpg\issues\Issue518-Bad-RST-Progressive.jpg + tests\Images\Input\Jpg\issues\Issue520-InvalidCast.jpg = tests\Images\Input\Jpg\issues\Issue520-InvalidCast.jpg + tests\Images\Input\Jpg\issues\Issue624-DhtHasWrongLength-Progressive-N.jpg = tests\Images\Input\Jpg\issues\Issue624-DhtHasWrongLength-Progressive-N.jpg + tests\Images\Input\Jpg\issues\Issue694-Decode-Exif-OutOfRange.jpg = tests\Images\Input\Jpg\issues\Issue694-Decode-Exif-OutOfRange.jpg + tests\Images\Input\Jpg\issues\Issue695-Invalid-EOI.jpg = tests\Images\Input\Jpg\issues\Issue695-Invalid-EOI.jpg + tests\Images\Input\Jpg\issues\Issue696-Resize-Exif-OutOfRange.jpg = tests\Images\Input\Jpg\issues\Issue696-Resize-Exif-OutOfRange.jpg + tests\Images\Input\Jpg\issues\Issue721-InvalidAPP0.jpg = tests\Images\Input\Jpg\issues\Issue721-InvalidAPP0.jpg + tests\Images\Input\Jpg\issues\Issue723-Ordered-Interleaved-Progressive-A.jpg = tests\Images\Input\Jpg\issues\Issue723-Ordered-Interleaved-Progressive-A.jpg + tests\Images\Input\Jpg\issues\Issue723-Ordered-Interleaved-Progressive-B.jpg = tests\Images\Input\Jpg\issues\Issue723-Ordered-Interleaved-Progressive-B.jpg + tests\Images\Input\Jpg\issues\Issue723-Ordered-Interleaved-Progressive-C.jpg = tests\Images\Input\Jpg\issues\Issue723-Ordered-Interleaved-Progressive-C.jpg + tests\Images\Input\Jpg\issues\issue750-exif-load.jpg = tests\Images\Input\Jpg\issues\issue750-exif-load.jpg + tests\Images\Input\Jpg\issues\issue750-exif-tranform.jpg = tests\Images\Input\Jpg\issues\issue750-exif-tranform.jpg + tests\Images\Input\Jpg\issues\Issue845-Incorrect-Quality99.jpg = tests\Images\Input\Jpg\issues\Issue845-Incorrect-Quality99.jpg + tests\Images\Input\Jpg\issues\issue855-incorrect-colorspace.jpg = tests\Images\Input\Jpg\issues\issue855-incorrect-colorspace.jpg + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fuzz", "fuzz", "{516A3532-6AC2-417B-AD79-9BD5D0D378A0}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Jpg\issues\fuzz\Issue797-NullReferenceException.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue797-NullReferenceException.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue798-AccessViolationException.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue798-AccessViolationException.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue821-DivideByZeroException.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue821-DivideByZeroException.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue822-DivideByZeroException.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue822-DivideByZeroException.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue823-NullReferenceException.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue823-NullReferenceException.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-A.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-A.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-B.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-B.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-C.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-C.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-D.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-D.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-E.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-E.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-F.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-F.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-G.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-G.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-H.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue824-IndexOutOfRangeException-H.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue825-ArgumentOutOfRangeException-A.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue825-ArgumentOutOfRangeException-A.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue825-ArgumentOutOfRangeException-B.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue825-ArgumentOutOfRangeException-B.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue825-ArgumentOutOfRangeException-C.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue825-ArgumentOutOfRangeException-C.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue825-ArgumentOutOfRangeException-D.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue825-ArgumentOutOfRangeException-D.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue826-ArgumentException-A.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue826-ArgumentException-A.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue826-ArgumentException-B.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue826-ArgumentException-B.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue826-ArgumentException-C.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue826-ArgumentException-C.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue827-AccessViolationException.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue827-AccessViolationException.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue839-ExecutionEngineException.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue839-ExecutionEngineException.jpg + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "JpegSnoopReports", "JpegSnoopReports", "{714CDEA1-9AE6-4F76-B8B1-A7DB8C1DB82F}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue159-MissingFF00-Progressive-Bedroom.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue159-MissingFF00-Progressive-Bedroom.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue159-MissingFF00-Progressive-Girl.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue159-MissingFF00-Progressive-Girl.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue178-BadCoeffsProgressive-Lemon.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue178-BadCoeffsProgressive-Lemon.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue214-CriticalEOF .jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue214-CriticalEOF .jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue385-BadZigZag-Progressive.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue385-BadZigZag-Progressive.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue394-MultiHuffmanBaseline-Speakers.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue394-MultiHuffmanBaseline-Speakers.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue517-No-EOI-Progressive.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue517-No-EOI-Progressive.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue518-Bad-RST-Progressive.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue518-Bad-RST-Progressive.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue520-InvalidCast.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue520-InvalidCast.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue624-DhtHasWrongLength-Progressive-N.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue624-DhtHasWrongLength-Progressive-N.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue694-Decode-Exif-OutOfRange.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue694-Decode-Exif-OutOfRange.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue695-Invalid-EOI.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue695-Invalid-EOI.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue696-Resize-Exif-OutOfRange.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue696-Resize-Exif-OutOfRange.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue721-InvalidAPP0.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue721-InvalidAPP0.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue723-Ordered-Interleaved-Progressive-A.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue723-Ordered-Interleaved-Progressive-A.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue723-Ordered-Interleaved-Progressive-B.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue723-Ordered-Interleaved-Progressive-B.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue723-Ordered-Interleaved-Progressive-C.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\Issue723-Ordered-Interleaved-Progressive-C.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\issue750-exif-load.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\issue750-exif-load.jpg.txt + tests\Images\Input\Jpg\issues\JpegSnoopReports\issue750-exif-tranform.jpg.txt = tests\Images\Input\Jpg\issues\JpegSnoopReports\issue750-exif-tranform.jpg.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "progressive", "progressive", "{6458AFCB-A159-47D5-8F2B-50C95C0915E0}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Jpg\progressive\BadEofProgressive.jpg = tests\Images\Input\Jpg\progressive\BadEofProgressive.jpg + tests\Images\Input\Jpg\progressive\ExifUndefType.jpg = tests\Images\Input\Jpg\progressive\ExifUndefType.jpg + tests\Images\Input\Jpg\progressive\fb.jpg = tests\Images\Input\Jpg\progressive\fb.jpg + tests\Images\Input\Jpg\progressive\Festzug.jpg = tests\Images\Input\Jpg\progressive\Festzug.jpg + tests\Images\Input\Jpg\progressive\progress.jpg = tests\Images\Input\Jpg\progressive\progress.jpg + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "JpegSnoopReports", "JpegSnoopReports", "{39F5197B-CF6C-41A5-9739-7F97E78BB104}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Jpg\progressive\JpegSnoopReports\BadEofProgressive.jpg.txt = tests\Images\Input\Jpg\progressive\JpegSnoopReports\BadEofProgressive.jpg.txt + tests\Images\Input\Jpg\progressive\JpegSnoopReports\ExifUndefType.jpg.txt = tests\Images\Input\Jpg\progressive\JpegSnoopReports\ExifUndefType.jpg.txt + tests\Images\Input\Jpg\progressive\JpegSnoopReports\fb.jpg.txt = tests\Images\Input\Jpg\progressive\JpegSnoopReports\fb.jpg.txt + tests\Images\Input\Jpg\progressive\JpegSnoopReports\Festzug.jpg.txt = tests\Images\Input\Jpg\progressive\JpegSnoopReports\Festzug.jpg.txt + tests\Images\Input\Jpg\progressive\JpegSnoopReports\progress.jpg.txt = tests\Images\Input\Jpg\progressive\JpegSnoopReports\progress.jpg.txt + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Png", "Png", "{E1C42A6F-913B-4A7B-B1A8-2BB62843B254}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Png\banner7-adam.png = tests\Images\Input\Png\banner7-adam.png + tests\Images\Input\Png\banner8-index.png = tests\Images\Input\Png\banner8-index.png + tests\Images\Input\Png\big-corrupted-chunk.png = tests\Images\Input\Png\big-corrupted-chunk.png + tests\Images\Input\Png\Bike.png = tests\Images\Input\Png\Bike.png + tests\Images\Input\Png\BikeGrayscale.png = tests\Images\Input\Png\BikeGrayscale.png + tests\Images\Input\Png\blur.png = tests\Images\Input\Png\blur.png + tests\Images\Input\Png\bpp1.png = tests\Images\Input\Png\bpp1.png + tests\Images\Input\Png\CalliphoraPartial.png = tests\Images\Input\Png\CalliphoraPartial.png + tests\Images\Input\Png\CalliphoraPartialGrayscale.png = tests\Images\Input\Png\CalliphoraPartialGrayscale.png + tests\Images\Input\Png\chunklength1.png = tests\Images\Input\Png\chunklength1.png + tests\Images\Input\Png\chunklength2.png = tests\Images\Input\Png\chunklength2.png + tests\Images\Input\Png\cross.png = tests\Images\Input\Png\cross.png + tests\Images\Input\Png\ducky.png = tests\Images\Input\Png\ducky.png + tests\Images\Input\Png\filter0.png = tests\Images\Input\Png\filter0.png + tests\Images\Input\Png\filter1.png = tests\Images\Input\Png\filter1.png + tests\Images\Input\Png\filter2.png = tests\Images\Input\Png\filter2.png + tests\Images\Input\Png\filter3.png = tests\Images\Input\Png\filter3.png + tests\Images\Input\Png\filter4.png = tests\Images\Input\Png\filter4.png + tests\Images\Input\Png\filterVar.png = tests\Images\Input\Png\filterVar.png + tests\Images\Input\Png\gray-1-trns.png = tests\Images\Input\Png\gray-1-trns.png + tests\Images\Input\Png\gray-16-tRNS-interlaced.png = tests\Images\Input\Png\gray-16-tRNS-interlaced.png + tests\Images\Input\Png\gray-16.png = tests\Images\Input\Png\gray-16.png + tests\Images\Input\Png\gray-2-tRNS.png = tests\Images\Input\Png\gray-2-tRNS.png + tests\Images\Input\Png\gray-4-tRNS.png = tests\Images\Input\Png\gray-4-tRNS.png + tests\Images\Input\Png\gray-8-tRNS.png = tests\Images\Input\Png\gray-8-tRNS.png + tests\Images\Input\Png\gray-alpha-16.png = tests\Images\Input\Png\gray-alpha-16.png + tests\Images\Input\Png\gray-alpha-8.png = tests\Images\Input\Png\gray-alpha-8.png + tests\Images\Input\Png\gray_4bpp.png = tests\Images\Input\Png\gray_4bpp.png + tests\Images\Input\Png\icon.png = tests\Images\Input\Png\icon.png + tests\Images\Input\Png\iftbbn0g01.png = tests\Images\Input\Png\iftbbn0g01.png + tests\Images\Input\Png\iftbbn0g02.png = tests\Images\Input\Png\iftbbn0g02.png + tests\Images\Input\Png\iftbbn0g04.png = tests\Images\Input\Png\iftbbn0g04.png + tests\Images\Input\Png\indexed.png = tests\Images\Input\Png\indexed.png + tests\Images\Input\Png\interlaced.png = tests\Images\Input\Png\interlaced.png + tests\Images\Input\Png\kaboom.png = tests\Images\Input\Png\kaboom.png + tests\Images\Input\Png\low-variance.png = tests\Images\Input\Png\low-variance.png + tests\Images\Input\Png\palette-8bpp.png = tests\Images\Input\Png\palette-8bpp.png + tests\Images\Input\Png\pd-dest.png = tests\Images\Input\Png\pd-dest.png + tests\Images\Input\Png\pd-source.png = tests\Images\Input\Png\pd-source.png + tests\Images\Input\Png\pd.png = tests\Images\Input\Png\pd.png + tests\Images\Input\Png\pl.png = tests\Images\Input\Png\pl.png + tests\Images\Input\Png\pp.png = tests\Images\Input\Png\pp.png + tests\Images\Input\Png\rainbow.png = tests\Images\Input\Png\rainbow.png + tests\Images\Input\Png\ratio-1x4.png = tests\Images\Input\Png\ratio-1x4.png + tests\Images\Input\Png\ratio-4x1.png = tests\Images\Input\Png\ratio-4x1.png + tests\Images\Input\Png\rgb-16-alpha.png = tests\Images\Input\Png\rgb-16-alpha.png + tests\Images\Input\Png\rgb-16-tRNS.png = tests\Images\Input\Png\rgb-16-tRNS.png + tests\Images\Input\Png\rgb-48bpp-interlaced.png = tests\Images\Input\Png\rgb-48bpp-interlaced.png + tests\Images\Input\Png\rgb-48bpp.png = tests\Images\Input\Png\rgb-48bpp.png + tests\Images\Input\Png\rgb-8-tRNS.png = tests\Images\Input\Png\rgb-8-tRNS.png + tests\Images\Input\Png\rollsroyce.png = tests\Images\Input\Png\rollsroyce.png + tests\Images\Input\Png\SnakeGame.png = tests\Images\Input\Png\SnakeGame.png + tests\Images\Input\Png\splash-interlaced.png = tests\Images\Input\Png\splash-interlaced.png + tests\Images\Input\Png\splash.png = tests\Images\Input\Png\splash.png + tests\Images\Input\Png\versioning-1_1.png = tests\Images\Input\Png\versioning-1_1.png + tests\Images\Input\Png\versioning-1_2.png = tests\Images\Input\Png\versioning-1_2.png + tests\Images\Input\Png\vim16x16_1.png = tests\Images\Input\Png\vim16x16_1.png + tests\Images\Input\Png\vim16x16_2.png = tests\Images\Input\Png\vim16x16_2.png + tests\Images\Input\Png\zlib-overflow.png = tests\Images\Input\Png\zlib-overflow.png + EndProjectSection +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Tests", "tests\ImageSharp.Tests\ImageSharp.Tests.csproj", "{EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Benchmarks", "tests\ImageSharp.Benchmarks\ImageSharp.Benchmarks.csproj", "{2BF743D8-2A06-412D-96D7-F448F00C5EA5}" @@ -123,9 +432,25 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {9E574A07-F879-4811-9C41-5CBDC6BAFDB7} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} + {FBE8C1AD-5AEC-4514-9B64-091D8E145865} = {1799C43E-5C54-4A8F-8D64-B1475241DB0D} + {2B02E303-7CC6-4E15-97EE-DBE86B287553} = {E919DF0B-2607-4462-8FC0-5C98FE50F8C9} {2AA31A1F-142C-43F4-8687-09ABCA4B3A26} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} {2E33181E-6E28-4662-A801-E2E7DC206029} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} + {D4C5EC58-F8E6-4636-B9EE-C99D2578E5C6} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} + {FA55F5DE-11A6-487D-ABA4-BC93A02717DD} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} + {9DA226A1-8656-49A8-A58A-A8B5C081AD66} = {FA55F5DE-11A6-487D-ABA4-BC93A02717DD} + {1A82C5F6-90E0-4E97-BE16-A825C046B493} = {9DA226A1-8656-49A8-A58A-A8B5C081AD66} + {EE3FB0B3-1C31-41E9-93AB-BA800560A868} = {9DA226A1-8656-49A8-A58A-A8B5C081AD66} + {BF8DFDC1-CEE5-4A37-B216-D3085360C776} = {EE3FB0B3-1C31-41E9-93AB-BA800560A868} + {DB21FED7-E8CB-4B00-9EB2-9144D32A590A} = {9DA226A1-8656-49A8-A58A-A8B5C081AD66} + {195BA3D3-3E9F-4BC5-AB40-5F9FEB638146} = {DB21FED7-E8CB-4B00-9EB2-9144D32A590A} + {538F0EBD-4084-4EDB-93DD-6D35B733CA48} = {195BA3D3-3E9F-4BC5-AB40-5F9FEB638146} + {5C9B689F-B96D-47BE-A208-C23B1B2A8570} = {DB21FED7-E8CB-4B00-9EB2-9144D32A590A} + {516A3532-6AC2-417B-AD79-9BD5D0D378A0} = {5C9B689F-B96D-47BE-A208-C23B1B2A8570} + {714CDEA1-9AE6-4F76-B8B1-A7DB8C1DB82F} = {5C9B689F-B96D-47BE-A208-C23B1B2A8570} + {6458AFCB-A159-47D5-8F2B-50C95C0915E0} = {DB21FED7-E8CB-4B00-9EB2-9144D32A590A} + {39F5197B-CF6C-41A5-9739-7F97E78BB104} = {6458AFCB-A159-47D5-8F2B-50C95C0915E0} + {E1C42A6F-913B-4A7B-B1A8-2BB62843B254} = {9DA226A1-8656-49A8-A58A-A8B5C081AD66} {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} {2BF743D8-2A06-412D-96D7-F448F00C5EA5} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} {561B880A-D9EE-44EF-90F5-817C54A9D9AB} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} diff --git a/NuGet.config b/NuGet.config deleted file mode 100644 index 322105d4d..000000000 --- a/NuGet.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 000000000..cd3d5e8cb --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,41 @@ + + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.props + src + + + + + + $(MSBuildThisFileDirectory)..\standards\SixLabors.ruleset + true + + + + + + + + + + + + + + + + + + + diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets new file mode 100644 index 000000000..c0e01ae58 --- /dev/null +++ b/src/Directory.Build.targets @@ -0,0 +1,55 @@ + + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.targets + + + + + + $(IntermediateOutputPath)$(MSBuildProjectName).InternalsVisibleTo$(DefaultLanguageSourceExtension) + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index f9181b45d..a092e3604 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -1,55 +1,23 @@ - + + + + SixLabors.ImageSharp.Drawing SixLabors.ImageSharp.Drawing - SixLabors and contributors - Six Labors - Copyright (c) Six Labors and contributors. - SixLabors.ImageSharp An extension to ImageSharp that allows the drawing of images, paths, and text. - en - - $(packageversion) - 0.0.1 - - netcoreapp2.1;netstandard1.3;netstandard2.0 - - 7.3 - true - true - SixLabors.ImageSharp.Drawing SixLabors.ImageSharp.Drawing Image Draw Shape Path Font - https://raw.githubusercontent.com/SixLabors/Branding/master/icons/imagesharp/sixlabors.imagesharp.128.png - https://github.com/SixLabors/ImageSharp - http://www.apache.org/licenses/LICENSE-2.0 - git - https://github.com/SixLabors/ImageSharp - full - portable - True + SixLabors.ImageSharp + netcoreapp2.1;netstandard1.3;netstandard2.0 - + + - - - - - - - - - ..\..\standards\SixLabors.ruleset - SixLabors.ImageSharp - - - - true - - \ No newline at end of file + diff --git a/src/ImageSharp.Drawing/Properties/AssemblyInfo.cs b/src/ImageSharp.Drawing/Properties/AssemblyInfo.cs deleted file mode 100644 index 2891598b9..000000000 --- a/src/ImageSharp.Drawing/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -// Common values read from `AssemblyInfo.Common.cs` diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 832a6ce3f..a3d614a06 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -1,33 +1,14 @@ - + + + + SixLabors.ImageSharp SixLabors.ImageSharp - Six Labors and contributors - Six Labors - Copyright (c) Six Labors and contributors. - SixLabors.ImageSharp A cross-platform library for the processing of image files; written in C# - en - - $(packageversion) - 0.0.1 - - netcoreapp2.1;netstandard1.3;netstandard2.0;net472 - - true - true - SixLabors.ImageSharp SixLabors.ImageSharp Image Resize Crop Gif Jpg Jpeg Bitmap Png Core - https://raw.githubusercontent.com/SixLabors/Branding/master/icons/imagesharp/sixlabors.imagesharp.128.png - https://github.com/SixLabors/ImageSharp - http://www.apache.org/licenses/LICENSE-2.0 - git - https://github.com/SixLabors/ImageSharp - full - portable - True - IOperation - 7.3 + SixLabors.ImageSharp + netcoreapp2.1;netstandard1.3;netstandard2.0;net472 @@ -35,93 +16,7 @@ - - - - - - - - - - - - - - - - - - - ..\..\standards\SixLabors.ruleset - SixLabors.ImageSharp - - - - true - - - - - TextTemplatingFileGenerator - Block8x8F.Generated.cs - - - TextTemplatingFileGenerator - GenericBlock8x8.Generated.cs - - - TextTemplatingFileGenerator - Block8x8F.Generated.cs - - - TextTemplatingFileGenerator - PixelOperations{TPixel}.Generated.cs - - - TextTemplatingFileGenerator - Argb32.PixelOperations.Generated.cs - - - TextTemplatingFileGenerator - Bgr24.PixelOperations.Generated.cs - - - TextTemplatingFileGenerator - Bgra32.PixelOperations.Generated.cs - - - TextTemplatingFileGenerator - Gray8.PixelOperations.Generated.cs - - - TextTemplatingFileGenerator - Gray16.PixelOperations.Generated.cs - - - TextTemplatingFileGenerator - Rgb24.PixelOperations.Generated.cs - - - TextTemplatingFileGenerator - Rgba32.PixelOperations.Generated.cs - - - TextTemplatingFileGenerator - Rgb48.PixelOperations.Generated.cs - - - TextTemplatingFileGenerator - Rgba64.PixelOperations.Generated.cs - - - PorterDuffFunctions.Generated.cs - TextTemplatingFileGenerator - - - DefaultPixelBlenders.Generated.cs - TextTemplatingFileGenerator - + @@ -203,6 +98,87 @@ - + + + + + + TextTemplatingFileGenerator + Block8x8F.Generated.cs + + + TextTemplatingFileGenerator + GenericBlock8x8.Generated.cs + + + TextTemplatingFileGenerator + Block8x8F.Generated.cs + + + TextTemplatingFileGenerator + PixelOperations{TPixel}.Generated.cs + + + TextTemplatingFileGenerator + Argb32.PixelOperations.Generated.cs + + + TextTemplatingFileGenerator + Bgr24.PixelOperations.Generated.cs + + + TextTemplatingFileGenerator + Bgra32.PixelOperations.Generated.cs + + + TextTemplatingFileGenerator + Gray8.PixelOperations.Generated.cs + + + TextTemplatingFileGenerator + Gray16.PixelOperations.Generated.cs + + + TextTemplatingFileGenerator + Rgb24.PixelOperations.Generated.cs + + + TextTemplatingFileGenerator + Rgba32.PixelOperations.Generated.cs + + + TextTemplatingFileGenerator + Rgb48.PixelOperations.Generated.cs + + + TextTemplatingFileGenerator + Rgba64.PixelOperations.Generated.cs + + + PorterDuffFunctions.Generated.cs + TextTemplatingFileGenerator + + + DefaultPixelBlenders.Generated.cs + TextTemplatingFileGenerator + + + + + + + + + + + + + + - \ No newline at end of file + + + + + + diff --git a/src/ImageSharp/Properties/AssemblyInfo.cs b/src/ImageSharp/Properties/AssemblyInfo.cs index f4459887f..2862b4585 100644 --- a/src/ImageSharp/Properties/AssemblyInfo.cs +++ b/src/ImageSharp/Properties/AssemblyInfo.cs @@ -3,12 +3,9 @@ using System.Runtime.CompilerServices; -// Ensure the other projects can see the internal helpers -[assembly: InternalsVisibleTo("SixLabors.ImageSharp.Drawing")] - // Redundant suppressing of SA1413 for Rider. [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage( "StyleCop.CSharp.MaintainabilityRules", "SA1413:UseTrailingCommasInMultiLineInitializers", - Justification = "Follows SixLabors.ruleset")] \ No newline at end of file + Justification = "Follows SixLabors.ruleset")] diff --git a/src/Shared/AssemblyInfo.Common.cs b/src/Shared/AssemblyInfo.Common.cs deleted file mode 100644 index 82e1dac6c..000000000 --- a/src/Shared/AssemblyInfo.Common.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; - -// Ensure the internals can be built and tested. -[assembly: InternalsVisibleTo("SixLabors.ImageSharp.Drawing")] -[assembly: InternalsVisibleTo("ImageSharp.Benchmarks")] -[assembly: InternalsVisibleTo("SixLabors.ImageSharp.Tests")] -[assembly: InternalsVisibleTo("SixLabors.ImageSharp.Sandbox46")] - -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKeyToken=null")] diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props new file mode 100644 index 000000000..97bd9b6e7 --- /dev/null +++ b/tests/Directory.Build.props @@ -0,0 +1,30 @@ + + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.props + tests + + + + CS0618;$(NoWarn) + + + + + + + + + + + diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets new file mode 100644 index 000000000..f8a4936e2 --- /dev/null +++ b/tests/Directory.Build.targets @@ -0,0 +1,19 @@ + + + + + + + $(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.targets + + + + + diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index 2a5408da1..1e951f5d0 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -1,29 +1,37 @@ - + + + - - netcoreapp2.1 + ImageSharp.Benchmarks Exe - True SixLabors.ImageSharp.Benchmarks - ImageSharp.Benchmarks - 7.3 + netcoreapp2.1;net472 - + + win7-x64 false + - - - - - + + + + + + + + + + + - + - \ No newline at end of file + + diff --git a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj index 6569dc002..fc94668e1 100644 --- a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj +++ b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj @@ -1,30 +1,28 @@ - + + + - Exe - net472 - win7-x64 - True - false SixLabors.ImageSharp.Sandbox46 A cross-platform library for processing of image files written in C# - Copyright © James Jackson-South and contributors. - James Jackson-South and contributors - James Jackson-South + Exe + false SixLabors.ImageSharp.Sandbox46 - 7.3 + win7-x64 + net472 + - - + + - - - + + + - - - + + - \ No newline at end of file + + diff --git a/tests/ImageSharp.Sandbox46/Properties/AssemblyInfo.cs b/tests/ImageSharp.Sandbox46/Properties/AssemblyInfo.cs deleted file mode 100644 index a10fc12fe..000000000 --- a/tests/ImageSharp.Sandbox46/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("96188137-5fa6-4924-ab6e-4eff79c6e0bb")] diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 0b727f30c..406719ab4 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -1,48 +1,24 @@ - + + + - netcoreapp2.1;net462;net472 - True - latest - full - portable - True - SixLabors.ImageSharp.Tests SixLabors.ImageSharp.Tests AnyCPU;x64;x86 + SixLabors.ImageSharp.Tests + netcoreapp2.1;net462;net472 - - false - - - - false - - - - false - - + - + + + + - + - - - - - - - - - - - - - - - + + PreserveNewest @@ -54,4 +30,11 @@ PreserveNewest + + + + + + + From 47852eb2555a71158d62ac5f4b96f014edc011c8 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 4 Jun 2019 13:26:39 +1000 Subject: [PATCH 212/223] Fix build/test (#923) --- Directory.Build.props | 3 ++- Directory.Build.targets | 2 +- standards | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 9c92c14b8..6e3cc9b3b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -30,8 +30,9 @@ true + - true + false diff --git a/Directory.Build.targets b/Directory.Build.targets index 350439879..d1183e5d4 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -25,7 +25,7 @@ - + diff --git a/standards b/standards index dd83f6496..8b085c0ec 160000 --- a/standards +++ b/standards @@ -1 +1 @@ -Subproject commit dd83f649638c6333984a757c01be6ec294e6b63c +Subproject commit 8b085c0ec4fb64797b9965741f7138f8f66a6b44 From dcbcf3c4282c3b0c784b48d88280e70f1673aede Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 4 Jun 2019 15:41:45 +1000 Subject: [PATCH 213/223] Prevent zigzag overflow. Fix #922 --- .../Formats/Jpeg/Components/ZigZag.cs | 45 +++++++++++-------- .../Formats/Jpg/ZigZagTests.cs | 44 ++++++++++++++++++ 2 files changed, 70 insertions(+), 19 deletions(-) create mode 100644 tests/ImageSharp.Tests/Formats/Jpg/ZigZagTests.cs diff --git a/src/ImageSharp/Formats/Jpeg/Components/ZigZag.cs b/src/ImageSharp/Formats/Jpeg/Components/ZigZag.cs index a3701f2c1..250e98c02 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ZigZag.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ZigZag.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -19,30 +19,37 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Copy of in a value type /// - public fixed byte Data[64]; + public fixed byte Data[64 + 16]; /// + /// /// Unzig maps from the zigzag ordering to the natural ordering. For example, /// unzig[3] is the column and row of the fourth element in zigzag order. The /// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2). + /// + /// + /// When reading corrupted data, the Huffman decoders could attempt + /// to reference an entry beyond the end of this array (if the decoded + /// zero run length reaches past the end of the block). To prevent + /// wild stores without adding an inner-loop test, we put some extra + /// "63"s after the real entries. This will cause the extra coefficient + /// to be stored in location 63 of the block, not somewhere random. + /// The worst case would be a run-length of 15, which means we need 16 + /// fake entries. + /// /// private static readonly byte[] Unzig = { - 0, - 1, 8, - 16, 9, 2, - 3, 10, 17, 24, - 32, 25, 18, 11, 4, - 5, 12, 19, 26, 33, 40, - 48, 41, 34, 27, 20, 13, 6, - 7, 14, 21, 28, 35, 42, 49, 56, - 57, 50, 43, 36, 29, 22, 15, - 23, 30, 37, 44, 51, 58, - 59, 52, 45, 38, 31, - 39, 46, 53, 60, - 61, 54, 47, - 55, 62, - 63 + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, // Extra entries for safety in decoder + 63, 63, 63, 63, 63, 63, 63, 63 }; /// @@ -68,7 +75,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { ZigZag result = default; byte* unzigPtr = result.Data; - Marshal.Copy(Unzig, 0, (IntPtr)unzigPtr, 64); + Marshal.Copy(Unzig, 0, (IntPtr)unzigPtr, 64 + 16); return result; } @@ -87,4 +94,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components return result; } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ZigZagTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/ZigZagTests.cs new file mode 100644 index 000000000..e59584991 --- /dev/null +++ b/tests/ImageSharp.Tests/Formats/Jpg/ZigZagTests.cs @@ -0,0 +1,44 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.Formats.Jpeg.Components; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Formats.Jpg +{ + public class ZigZagTests + { + [Fact] + public void ZigZagCanHandleAllPossibleCoefficients() + { + // Mimic the behaviour of the huffman scan decoder using all possible byte values + short[] block = new short[64]; + var zigzag = ZigZag.CreateUnzigTable(); + + for (int h = 0; h < 255; h++) + { + for (int i = 1; i < 64; i++) + { + int s = h; + int r = s >> 4; + s &= 15; + + if (s != 0) + { + i += r; + block[zigzag[i++]] = (short)s; + } + else + { + if (r == 0) + { + break; + } + + i += 16; + } + } + } + } + } +} From 06d0fd44f002be3de905e18a2a76e6f570dd5ac5 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 4 Jun 2019 20:39:55 +1000 Subject: [PATCH 214/223] Add test image and use constants --- .../Formats/Jpeg/Components/ZigZag.cs | 29 +++++++++--------- .../Formats/Jpg/JpegDecoderTests.Images.cs | 3 +- tests/ImageSharp.Tests/TestImages.cs | 3 +- .../Issue922-AccessViolationException.jpg | Bin 0 -> 1768097 bytes 4 files changed, 19 insertions(+), 16 deletions(-) create mode 100644 tests/Images/Input/Jpg/issues/fuzz/Issue922-AccessViolationException.jpg diff --git a/src/ImageSharp/Formats/Jpeg/Components/ZigZag.cs b/src/ImageSharp/Formats/Jpeg/Components/ZigZag.cs index 250e98c02..059e2052b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ZigZag.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ZigZag.cs @@ -17,17 +17,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components internal unsafe struct ZigZag { /// - /// Copy of in a value type - /// - public fixed byte Data[64 + 16]; - - /// - /// - /// Unzig maps from the zigzag ordering to the natural ordering. For example, - /// unzig[3] is the column and row of the fourth element in zigzag order. The - /// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2). - /// - /// /// When reading corrupted data, the Huffman decoders could attempt /// to reference an entry beyond the end of this array (if the decoded /// zero run length reaches past the end of the block). To prevent @@ -36,9 +25,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// to be stored in location 63 of the block, not somewhere random. /// The worst case would be a run-length of 15, which means we need 16 /// fake entries. - /// + /// + private const int Size = 64 + 16; + + /// + /// Copy of in a value type + /// + public fixed byte Data[Size]; + + /// + /// Unzig maps from the zigzag ordering to the natural ordering. For example, + /// unzig[3] is the column and row of the fourth element in zigzag order. The + /// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2). /// private static readonly byte[] Unzig = + new byte[Size] { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, @@ -75,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { ZigZag result = default; byte* unzigPtr = result.Data; - Marshal.Copy(Unzig, 0, (IntPtr)unzigPtr, 64 + 16); + Marshal.Copy(Unzig, 0, (IntPtr)unzigPtr, Size); return result; } @@ -86,7 +87,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { Block8x8F result = default; - for (int i = 0; i < 64; i++) + for (int i = 0; i < Block8x8F.Size; i++) { result[Unzig[i]] = qt[i]; } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index 442fcb3d1..d428000ef 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -17,6 +17,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg // BUG: The following image has a high difference compared to the expected output: // TestImages.Jpeg.Baseline.Jpeg420Small, + // TestImages.Jpeg.Issues.Fuzz.AccessViolationException922, TestImages.Jpeg.Baseline.Jpeg444, TestImages.Jpeg.Baseline.Bad.BadEOF, @@ -106,4 +107,4 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [TestImages.Jpeg.Progressive.Bad.ExifUndefType] = 0.011f / 100, }; } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 62b7ae2ec..d8e8719ba 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System.Linq; @@ -202,6 +202,7 @@ namespace SixLabors.ImageSharp.Tests public const string ArgumentException826C = "Jpg/issues/fuzz/Issue826-ArgumentException-C.jpg"; public const string AccessViolationException827 = "Jpg/issues/fuzz/Issue827-AccessViolationException.jpg"; public const string ExecutionEngineException839 = "Jpg/issues/fuzz/Issue839-ExecutionEngineException.jpg"; + public const string AccessViolationException922 = "Jpg/issues/fuzz/Issue922-AccessViolationException.jpg"; } } diff --git a/tests/Images/Input/Jpg/issues/fuzz/Issue922-AccessViolationException.jpg b/tests/Images/Input/Jpg/issues/fuzz/Issue922-AccessViolationException.jpg new file mode 100644 index 0000000000000000000000000000000000000000..69f1906295457355e7339140e46d61a2a34c336f GIT binary patch literal 1768097 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%0A=9f$5&b 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 z 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 V9{4Tzp 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

smb9j4n3YgC3C(jW>&uo|yS=z| zOt_Ux&KEnr`#=y>R8W#c6%1qwD79g<5~i7H8l)WnBr8Zbsy^)_#025fMRPCpC#JO2 z)HIluC6eo~%5o<-MMgJ2^5ENcJJUvPkVwYuxm10lUYZBS0xxj-kNm=W#SLN0#BqUp~|Y4UGb^2P;GgW)yw^$=rqIgb#mgAx^yHB>Z_ zc@jMgv=GF;V$7rTWqh*BC6wdkzU|pvX9#Z7IC&{`vJ~>6X7YB0SZc|#0XE@hSFjpHiAoTIqCNrIim+q1Z!xi@e`mv^ktqhq?Pg11N7gFxw_V> zh|h1%+)Hl{EIZ66*@Zlt+j5x=+U*!&@hI}9+U~LR393v(HsJCCNKf>9MO=?$k}BTl z4xR&3?6niR7V=2XuA>dDz3Yaf5_a^*3SoClY%SYPBM6*2!gzbANX7A~oV^sq=lYWV@Lfn!#0#09Oyy00}xuxkrXgHU^ zP@Ew_X;Q(BSSLs)Z0w;k)&Ut>b5@(TDDOL^i3du_IznMHFa+v9#FKzD3Ab21J*392 ze8Cu+aDrIrsjBCPYOrr8M9LHb2Geay+;=zRz`f1g@d&uiZwv#9T2hW9`bA0DdToJBX)b%WFT%NkL|i}@17>KQOiKxR9H zkX$R5VhbDh)OX@HH(PYjk`tI_Dpc$#WDjn#c6(_WGfR-MEhkS%LxlS@^z_oC^~2Nn zse+=iTKFQ5?If9ENQB`RV!VqChW7-5r$MHc;C-#u-Gmr7SIQh@w=uWEtzI8tp$fBf zs})G-{{Sak9({3etx=b-4Cc=&2#NAA*pW`crDF{vkOi&?wY4_vI3fPY zo=)RfMQ>UXGXeQxW#U0#pBG` zrx&TpRFF}_iskxU%})wdOk*fgp}~FnG@?MuqVfRAJ3RnpK$^cJdT*|l%c-<1vfE@W zI@X~IQne65zoL9Fl93piZ09W~Mu!f`fHlCFN`dfzlZ1>+@uEYPv-S_v++bx~yM$vn z1bZj*>oE~V@CbxkV@H-G3?x<~Rk7MFYhJ?*_TAeog@io9911G}99UGwJ^+-DS;HDt zWtkht3IJLJ6DkRa;0YW-=;)-TRLxj-O|lIndCojv5_;L|u!&eEq)=FPm8!f(+1h$W~C@xBraPc6eCle7ued4vd%GSY39wEjM>6URi z=V49)BM_k@WYM|xO_{Pz0qFbFwiOmw$Fnq2V9$s{O%Kbv;ju{@M?M?nEN|sSB}r< zWT+4ZD#ODw5!HndfuE_ToBa=^S)sPYX#+fgUvU6C?WZA4><9{YhUW(1nKekExVqcfdMloGEGAH>SNU8oR1Zu*#0_NOu`_ z0eb_qcpe6BH)nKS#l{u17&oYiPR;{lm>qm+aQ8bceWzPLd z#VV+=yqldN`7Ao7riE*%;G%)*B0gk`EmKn}hMEOrP0lp~Q@Y%a?`(HlA-QVgCT)t6 zmzqVwR`Jy!C=sdv&46?bv)iq^Ps4qLisZ4uVKX)TGEsDgt(z z96d7nhRz)x=+9O%bq7oOiH74D_XMS&!Cwi(;F6A{M(^jviTuSeB8}057Kk&w?1etp z0$b;iZq|96Wp|dn-{ozV;;$Nd@E2T4f=gwG5E5H(C_;jzAVwQ#8EcnkmaRJ5*3X9m zfJqk1gpsKv5fQhK5g<`fhLf#NQ1o$hZ#1<-#-YHas0_##aJWc8AnM0LO}pvLr*8Xj zR;?+vQll6-k`E8@N4v^`E6TTpB73Jt3H-X^vVS}3jSV|dR&N&f(-_+EIyV6Uh7 z8AKSI(X_P7AgK9gD;3OQQM@SbMb5Y372Z#|_l8``ZB>koS1MPCh>!^aU`LfOSD2II zb?i1va71zYdd))2UZ*$5%|iB`FZCB>em z&A1R!V^1huyKcR#ZUF>o#96oYPSVv%Zzi)*ZWXCcEov~KJ`kjg2FQXAGc^8HXPIXg zE!wkla8~Kkk==-r2^fG+4n+ukAk95@&b>dz@m`jHJEoSlIpJ(RlM|Yb>l&7w*$s|p>nl{c z=_G-Mf}KBh0tAmjae!)Wc+7a$Lo&t%Nkxn1ywRC)D5`&&{{Sqgs%514NkYKWRfe>W zEQV6C+Ukg`-N4}cv*qNkrRC;%b*;l{Deim4cWQ2CbR{YR6g2882OqbM2D29L(xi)b z-$4NC&@}}S{USj)8Gt=$BmUDJVZ~|8Sj{g`E9m6AS=y>qvYi>XJ&Cv*PN&&nVaep9 za+x}llv%YA1Su2NB&(UmgZgu&Vfl-dPxp)Y4m6{}eMj`{6Yhp@mDuL(UOw9{G?x~`w&XXYhWr7~3?L#D7L^PZkW(c>hZ&PM zmkf6(OQ~4^gN~r1{33isK!OT(gBV3sW?jeGC83MF65Y!XL8(n!XC zh!c+csX^X5d!%a#8C%+7UuMrq-EO0N*Z-ll5iiht0i2OP;6f-8HnENLkqnHz0_@*&H2 zqbssyEG^4PbjsXTp79AuB_Xwct?HdCD<@e11ArAFe`K>up7G>cT@rxsh8tVj1(IipgqVC}vDk=& zeV-k`6t?nfEcLAKFU&34J_et*aTe=o)&L=4Dbs_l7$s&(Oerb^K_+u1&Ms|>3$?f@ z1eB;HVCy>!&kh1&Fey7hAjER-th(9?S}Gq*wbaV!ZzPnMyGZ`&j5#eLm22uPb8rrt z-!)q8Pj;Cx+~u%N#T1>KCr&*EqebpMbmC)0-pC{ahhI_ip(m+*Nc=#$gXzm6^aH4! z70oz}W=F&;zn05c^O3_vhR+Hl7D8;eN?~LKgry|J6s9K}eCVFk z^zYU!M04!v24SU+nOroD6+^5RHfc-MBL!7I9lsAAPeFmMVQESn|sE>rcj>o!y^gt6&UD@2E!DuYHw88FDYRVb+@8e6&_N;s%iY(TNS{~ z9Ys76%CSD`_~(V&+ypAV5p0PeyZZRt21TCqQfY$ z972N+#2OhRppuq1c2AZ`Hiv{kXN)S@u1UG#9JhL`^Gg;Q4~4iGY^fT7bQ82Jq(D}( zK_tl8F;Cp?_4TU1Ft!wiij)%JNe!rfdnXa65Cs~~M4qI&*XZ}uj#tMaMg3+t11))m?DO%wuQJp{!z78UA#8GnfBk7B%T^98toVo=?M7WhL7C&0! z5~WE8&Lg|jQ$n{Od+{=sOEDKwrr->%yL;7bf0wg%r!*euAhu2brVypL0q_Ji9QuMYX-dP|AXosfH!xVAL zBLeE=_vk9ff9gO}bT{6Mf2aY^eiisc2j*_OLhII_*XPX^8TRHd6 zmkYJLE;$ot8J_Lu?zsKu^4HvO_}oiD3n!0_gtr|hVB&3GN&;t)T>W{)@95NN{WE)W09c|LINZtd53Wui6k2X$hy}l z-J2B~#*&`y6)p>luIVy3OOSuP+ZYO2b7h?B7Opm+>4Q4*PakduMX6hSH&DIzrZOqxRFo^O}JuJyJRARpPmP{s)o zJow{2S=W45o8c z3Ck@lX2JeKlYM0SqanE0&pi9c^O`P zWP979p6xiQ3j~qC3^AUpV-ZPgLn8hu8Sa)mcMZfV;leSIB-lkO)!_8=%|<0EzFjut zk(GVbW(#IKLvMSzd4KHPN;}5jI-uL@NOCci;sH32Ck_;q%MIm!6lw`pDM?dlQBMd? z9aBN3Yv}jlCUM2c8Q&1iapD3fQSil`11d1QQTa6Ug>_&7QEMLd(~@RQpKg7)7k2Bn zNwVxI9hk07YVkXdii&#QXe%Ug$J>U_vC zcw?xByUKqeSfg0Xl~L4B=cq&xt=SpCVWqh{-gcvrGTIz-F(n=nf?L!HRsgn~PTT(BK?D2ZOiAdPUG+kv@jdG_G+C29;J7oa zfqjM6S!B}f?~!iUDp5y(9Y|4`B%~CXI{}E<6lnfaeR{OJYu>m*KvW;KU_k@Lh>kJ0 z3JP(0H$Zf zFgToG;nj{5Pkm>YHHFYv223hHhiUYY?ZS+oOFD(uoChMuFHiH%Cx+p8d^I?(B^6ZW zvO3C-Gs~u?ik6^0$s}R0rqDKqb~YS^bF8l|e&~yvX4bW-EjCh}1+>JiWod~C9w20y zgp6r*yY~&Xt)~c-WS>qGL1+h zRtau2^^Kr)5GlVa^=P!y>Z9xsOA)Une$?@%MCp=EkSBsJP(k`gQd zH*PESnQ0yOdG^X>cJIoz ziGb6cNdygF#l+BB;j3VL8g{{ixQsaQQhdlbaHMTlPyIXKUTkL&#vLLq>~Mi!G>qND zZ>geWMSJc~NTZEf8W~5i>|CPM-P>inS8I7sumvW{+X3guH8UV&p;% z!0x+s`;P@K?*{Zbh|Hw^W=re^OYR4@H60y^W+t-CG>#)y4Rd~x|7-nV8 z64q}0Bu<7S?kE!ZZv{C}tzovv2vB!xW5Aj&cZ~?pwrxUq5suxG6uBgE#DY#86e0Y+ zR804ePevnV-HGH=U0ylp4k+m2d@D3#%~0@~m zRC~*2w1E(W0!(&*B>6J*lc`OKW!i{i zsH&F)rdleP%ghmAtBx3;DB-n4uo@TFPA%R1m-F&3EW%v`gol(|NrcH#3Y57K_bVNs zQRUuX!zfONR8zG@2>`_GAOVc*75tcMPyIY}(;Vsl08*&)T+w5dw79BQ#W0>a z+La>lS1i&fnvu|hV#T*AumsqE&h_?rbG+A0+*+#G7SN`O2+~_mN;IVDa2zBEfgA_sp;XB zJ=m%PZHh!OlOqvgHj+W=&2u|clITeU zY73qRWF7=z=T*6v@EqY=fyF`nUaH4wD&%oCD>yA%1w#NFy2)|nLI#)nRvz&CJj$Dk zrWHV;E0KuuN8iFLi4K znktN;Q1Gl2*xVlTS7qwbqUvXlaf+pgv)KSUugq}IE#KX|#TUp*-L!C#aDYnG(&7;E zI=_WYfP5!WA_YxW`N6!iO|j6GqyUl<5=wduZG*L3Nuy(gV^uzov&J!#X({8wu*}HQ zVl;H&gkfTs-ONtbD$vNL`+&WzZQAg!IUmk$68nlOQbKV!$j48i9||x=RPB>^z)Iyq zpE^DMkUB|+=PbKd)}E(LG!Wu72@Nz$BhybLTZ5S+k+oRl0Nt*>;(>b`@)6$5=vydT zGDM~|Y&&p>=^K3LCh8VsaD(ux0mHCKG3u(^yI8SB4MepOkpA)rr;MveRYu}AZ2$wf zj>h`(Icc411Iyh}*1aM}3e$7eCq(G_W9llar@8W9_tylE@{>(}Dmd2Rnl#WNl-R@( zxc>FX=5FquYx%2UyI^E06eGlXC#1}PW+Pw~Dqp+&!3bNY4Kk2+B#a0HV4Ml*J7$?N z%qyW7eo@MXhN6Nwenzc;^9|(agvNWWCrbV6=N>hRd`qFp3VD@SMKelcb=eRu0*`!+sCMonKrdnq#kh3PxKY@n8)zD` zj*(6EIh&w$9%dkG@bs#bt0KcsxmAfP_CnbWfMyJAK>%xU!?xRe7$H&5B9dxB#%a3? z%>5a{?@;)KGDuPP-kR*hlnPVyU!!4TVokdPrO7bT;o1+k^{oPw)R*cXNFJl+MkRSR zkI}RaZ2sDksx{IQ55E|)6W-NvMj#{MSUS`wuor9;ad zzq*nVCPfc&^_!>gyk1p&`$C10eq1V+KWMWe-ShxlTF0@|fwWn<7=i7lyTB?x`S-~G z0Lg!q{M7#dEAv)#xz<1W2w!C;}iUHZWgz;a3uq^y86EK7<5 zz?H(6pz5JFJbKQ{Ib-nMsld9akTFEL=)tV40esZ4QFO+j4OX(6eqG0huB z;HX`yN-DDvWwwsy*UPv0~GzO4%m7XFf!!o!=UXKs~Od&-H z#09$If(nt+q^#&veWAXCRsoj%Jz`kZXHWV;ODUfh%GGI%&si%wvsX%8W=UlP7lNu; zBxx0a_f=Q`MfeJTGfRqg<#;7>02o3*!w!&;0P8gjx0Wv9O^(yqD_`fp85=%?`T&7E1w(Vv~K!{N%gU8K?4 zl9gJOY6bT1^QsK>B=;uP@ZkmE8NOoGr|`AoUz`K!hLrnhZK+mUmcMwfz4M_RNs=UN z;#5bFtzvQ7ioA)C$;8@Z$1@!{o#Wm-$Z1*1g_70*rE%sC;@0omldpIh)TM1d57L8o zN>l5$v}6-HKuFr9suG`5uvM-4B=pOc@;9Pmp8AmtX1_buwl7grv-F~d83Z&GaBd!F z>0DU|AO~Rn8goy6t=ZlS!iR)}z&PPMNFL!Xy9;tPFq~BY%ZimR4lyz3 zj8$s&DR3-fu02EQ{%xt6YD~R6SbXIXXQ=X`QRdRqL%10#0o<{okRNTXFMdUiGL)}C z03>W10O84~Dch%0Xog4J0eCJK*6!!&un5ie2wF~>g-?w(|SOpw(>)9m3!rv;v- zooS}5^6s^g)C4-o6Yh>s)^&Z|&5tCU_0HuCFwBO`sE&}BfMX4~^b?H%`#8uR&NKZF zpvA7GxvC{jYzhiYg<}CEaIH}D1tMUyc-CexM-@F1e4G+ERZ~#x3PxkK$OhJMG}1W~fk}%B5l~mZ@P^;@R8`H@#R%$0^r#?EafxFRPkLzyWRdr1Hk$+AOWRMUid32pyzZk0jfQI#c`Aa3 z9KfX$(L)G|L*=gMjIpheoL!e_J4+tK_p#~j1Ol{-g@W; zg~;3O_EXMbix28$1wL%1Xj?O2utc(`EfZGJ)7?_1%t3!T1hPz6Uua1|KKCE9S<1<6 zbKSVV4?}8Dojyu9r>;}cTYA+u$qphr#0fkK(m#rNQ?XOR4^0`LN!Yiq3QDRyqRzk>8wz95`W1_Xe+hKnm5+fP}sc;PNqSl^yt$1ce zXtZEXjc|R`oM_P+{ zO34h5U`>UDWlLFZMenI?2OdttNA06pNIsv1C-Wu)S1wtbEmy}d_f~i%lV5oa<8^RD zD+BJewd};)4jo!Mpz>#^^nM;$N7s&vVe~j= zXJFr_$FkKs5r$(<7g?vmocS|1ynL1>=V;*a8RD?e|UH1c`PaRe?^H%U;%X~jFf;-ysyR6(d=YqhPy zD}@pYPfYskkHUsGYAOXMhCXLxew1QA3+|C8Q@wrUj51hB!?N$6j@F{tqcPzyhk!Y4 zKzgT-X|U8=i5Y0RKuq94K0{>rnjk_vMmP`9R_WMl$y-!sl$U83lEi#X$s^<6g0tbJ zBt?4|n|>uzCHHx26f35>F8BWclaKJ>YRsBKu8IvYI;Cf5kc+RnO@^VoPq*2}(jvS? zA?oIRzU}w@t9Q_yx46)cZ?lTUXi~SPaQV39ULz;kq=jNq1^wv`?N9tfeta@uajK|R zyC01Pb+76lsv3TgR>rM^<=nkXMHo^Kn?5Q{RYMR?((x5VIs%|-4xEJdxurO?>Npu7 zbP!;laG@g&l(Z*e=lmaClx}|kKU6ijkE58^pl+sOK6Y#AV3MZ*^H1rjvb@sY%2WI8 zhEz3y1fMEI@Kb0}oC=s%Mx_4$q8{H6>L;RuN=dgNTS&nC5KbINgpznCiL3g-u{mjK z{MSnVT- z90gL3p$yrZeIojm&3=LNvPFtuxW!zUrdy~LOXbBkl4dbO=8Lz^(jt<#{{Srnm({tF zx3_7{8AaPj)=cXHBu4`~W85hiK{K=gi1pz|1J{2-GACQQ6^W&867b^KY*N-y)cFLi z@Q2KTU6(#o@$QZEIve)@@vO4#7OR~EYQtv2e6SrAaHVXS6S9lf;o;USvzD5bL%z?$ELOU?q`5s7jU*s3bbRPx4 z?$me%j9XOjlZ5$FWF)@PK-!!~&a}$)z0*8D(=VzlH>KHDC#K8UQjZ+XG$CHWu=iPN zX$AWc6-MwJ4LO%H z-@cG|c)fy@{XB}B0rcC6<50ALvlcxB39>;Mcqrluhj9d^+KH|R_G_mB8<&?GUC+IB z3J6uw%V<>TgM&#V{{RdqlZG@PD+$b+Bx*_sByl`Xx`m#<({-yZ;}|YUqmHK$%eY&>Mo zS9lbY;!}w|*hwiMNE)?KZK6{8m2?vtom?Ix83S(sMH$~r9ZmI-)J~IO-B!rB{4a}P z6%f#2bu4gDvC@?*3e{88(n~)0yA>?$&3F0R_ic2Y*K7K zmKCe5G!kLBO&syZ6l>H6Jn5>KhZ{Ijv!#CGZg@NY{-R~hV7tV zk$UqT;Axb&)9ePyMudjduN(<7tuy>U698c}G`7o_T!Ni|6-nS`2TtCKea@2lZkwlg zUMJUV#8QJBiE6NlYU5v40EJqOn0&NhS?RVQwb$KEg7>(|Jok8eM$K%P{KD>Bvvo(i zQBz52#WMiu3RW6HP{d5DR@jiSx6197ph`8wk>V;Er)&&mn2*7YfREfCXMh;vKjdet5h z6bc9(A|OcHNS6Bk(ur9Bn4)wl>8Kq!{YS+pNarHukx*s9cg(i#E~#A9kX3 zLR1IchTIPdAKc_u4Oy!7_8QQLgsJ1G$$_8@3cNOll19{!&jYL&d>&JoXG@VYNWl-9yB6_k*>|~lzI&S|_F3KCy{kb@rWW8z zh*qsgXb=bV01%KAPu-0~+sC{1xjAgyTQIj>M|h-=3X?LB6mdAj$;8J+1$5q_eJ^4d zRCq>Uj~Jz@gAe(5aZEMqDkhe(Ck~Zz(^M3MD?z#=8dw6}W!Qi@CoE@)bh-VYym2a2 z_hdc*L`H4sZw!5`LDv2j<?TrAaLlyox1S1*Oe&r%j&ML9O~69n5-Dh z-v_6qp@d-n040YNqK+6LrJgEygnLRn5E8JR3$wQ39Ndd>o>(at4_+{ogp?a-ld5%U zB#2UQ0O>Mzh{BiVPPb_AP|&h=>Hx%S+m1V9qKZa%^##!0rBl&U)L=DPf8=+_li;{& z!z8aJtXxZ3Aleh$8$ht#;%+7DJ<-bSiBpf}uLB?5d$qwI(U^{sM3P5F6kg_S`GFAH zf5b>0*f`gCH>pog*-I@?gHzzpn8`<{sI0&eN#PJiP%20&Pw3^ic|ixvlFfCsi%#wy z?q4~r+l!S^tvqxGo9uB#N81ULW zzldQZ%QhQ=(yc`3trV34X_%6=afVw33IGhC*^e-4-rpj;%)5m5&N7>T2DP1GvPcCf zIAQ{^C+>rQ6_YMy*~NR%kisHyPR z$XVFI0~DtpEk;E;mMtPf8&i;~{wf>5j@ofK-Hp|?QCf1q*-@1!-I7V+I*+oKCA;T< z09~uAxl9jYW+}jRDzh)(d26Ydeg~NAX2hy7I+vk~FF{j@;nPyekwHB3Z&Zd!m@}v` zT%bemct!|bLafDXep!;kXz{kUB&%52I)ETd$j5;dC8u+4k(al8=)FpwacONWu_OlI zIHk-Gf1&__BN?Fzlho&_217@ZdU4eX+E190q(N6)X;J5A^ImO~*m-X;n#^q0(4O|> zg3evKu40_B%|`*^a7Gvi@lFE)(Xxw1Q20=Wb2lIoK~fu>ctR9FqDU>}xi5xs)=ndC9p)WjJ3yx0-Rt*3QgZv9F&Mn@$7mqndg3G7UZu?5 zxF~3AGS+VCo-0(f5vn{x7{!37nm1V@Nh34ptm*?v9h+z?av8Y*@4K77n!9arYSvk2 z-8cf1ZJ>t|L=v!dE5o;=89N0?+r5+K7Oh+~{!?)8c)(UkoQc6`Y*-^l$J|LM8 zWYVdh@c_(qD%13L4T?CC7t5`e6s%=b0Hl6pMR{Yl!rtzH0prEL+Z>}WA)w`kI|^Az z1E`cDI?Uo|K8@SIBmP+mJv!fcN7`K<2&S5>gX_B(c5m}Dl)T1m{$o+HN&_y>cKC+n z01qFa_znwywz*PA{8?ZJ`&YC5ZvoLt5xSX^gZ^0Uh@48@9>QMv(={(m{bkeB!97<- zGId=wDH1S-W~MgWcd2-*{m^@!);+DSE&j?GWsLs-m0CFyfN5tPk^RpZ=-EdI?B_AL zfV`amoCockZ27@>&sGL#WP+coNzfeEmUACUaJ;RJM^lI5`D$8BU*;sNsSMOru^Qu0 z%p|6#ktK>LH$(27$jk>L_4d%4EXkYeCtGbP8eBtcl%Ro#l$4p1wlUd(7*vaC*v;N? zm%n7@S`gx4Z4q%QQjFlWsZs<21j2Nv08&KIHG*{G)jG!{uhQBXXzCeWCZ9J(ip^rq zeCU`5Yutc6)%J3IA5>P>sUen_NyO??4lPnl%=l-^3W}51ZtylrO`tIzAI%~}VFV0t z>-01%<*t);wKHxVhi5*JMAxRo6!Zj5nfHf$njk`uYbh$l`=C1U z!i>MHY=P=itKEL7$NFcNGR7f-%@qYj8fIHmVsz(j`A`@e$O!_4H1`F9i0|(L1~_hJ z{{UNVo>=XHbbi#8DGFh?f|L+Yf)uols@mWZmFjUSDM>-l zprqsCB}v&Jf;LuMSJMx!OhOtwdog18Otg3;A1y%Cln!F0kRcT8Y3eD&LKR)Z+*6^@ zT-c|(?M~Ut;g~kNj`|?D07e9zLIS^tnL7c(cvSai+2-)(R^Q7m-OG^DK~rt$)^&^$ zM}&dh$r^CLojVN+`G3*Rt(j=!tj0RTFvOi~l=yZMVv^(?q(Uj;Wean1ZKj>LHD7J^ z#Tr(-(h?P7Pr~%@VSDsBo465 z0zbXdJYJ*9o2T?qnsDO+;{AWjYyl!qBBiW=omrjhkb`|}px?j4g(J1FrAlqxK5wX> zXc$n9zRGj=(+bR80ycMQ8i^YO6SILajs~2ly&z@Wvm-I}MVc_<<+C}8vJ^tk?=)&! zzj585H(!b3d+yb4FGMEQ#dR&mR64OtY^Iv*t2eg;yS=y=$ME6OV4*+=;i#UvSmnN) z~{w?59x{@Q1bOf-}JY5xEZ<4!r*jk*a+oOe%2yE|ioN~CmPX`#J6ejCt{ zg83vS@0ONgv>!H0Q=NI_EJ{+E3sL{)kpp0 zsGb{A79-T0Xjti{LG+)}E~{nkq;w}XW*k!(qLN`9CO1=y&Ll7H`LyuG6`DwscHQG) zCd6<(dA#|%=qZ0jkU`jivt;A5ry0Wvk+M$8ENykX_;8I10ZF+lK$w!Wtx$1+BkdEk z)=KY2K8b1NS@8^!)I55cH7c@I{{THRl65W>Vi79d*B;NijsE~^vqv!R8ISioJg}gP zJ(=Zcjc+%spZNQ$OcS&Fq~p^Aqh%(i^uzdj;Wcj?bdxgqKWH?Rxq!$#F82X7@wL7j zR*dgDxgHl2)Iyub&j2YBC1oB$T41#vN4Y5URO?H>Y~QxaWN>i;e zV`&Gfc1+SWZf@wMDp75PHZWEW;8n6z8^97aM+#Z=%Om=9$MeMbGp5*eW*;sUh1Nz= zdJw5e4AMNNIs@j&(0P+FX(GAYE?Dp}yq4LWlPOi%BU^$=AnIBGIDxc;zy$2!N6Ouu z*WRYlWoU+yt8fS`YfAgIlAS7A(g9AQRe%z>krZPvT&|a9eEHNa6_5NFjD5eQOvrn4T1ZcGZelU~qJac#gy;$O)2%HJL@+2D z8UFw>+o{>aLO&gnJ)Lro31 zi#&1Lff0{9YaVIp4nV=WXD>|a`g@B|W$LQ5oZ+z0P)7pJkGT0TzyOL@1cq(C__!dG z#VPFXI(1>vq^W!r-i<&+Vo#vkJ31&+Z@pWvzzu{pP>@1V`ELh{Y@tU<6XJ*f96{hz zcvfi26fnfNS4V1P6$n}_*me;VfexT-5m;Ca0}I;xY0l2`g$OR9NBkI=`B7T8gLRN) zC_;KdZA5YY{CkX2rwzzTc=~0~ND4>dQ(g%WSFvPSK*j1!w+Er>0(;eln z;cEkPZZ_v;8JbUt_Q=9~OFt?~jrGY=qokNUHlju!!b9E}{q&8;Gu?e=J41=#JuSpx zlAfw5T80Yh1;b>LE12Y}p;$nBjW?1>0>Z~mSv{LyD+RdT$el`&(*`FVf$K-8?GGol zX>7`rg@OtEx_iMONeV6SGwODgWYW?Zurb@e?fjvqbt#u~Pd<^0S0@j(L92iz@v zNdo=+0ae##7gnZSeF+DpL=SiyC@R+cWY>pE1Ihqw45ME_m3O9g^kYvLZ(RDE)t@hy zx>HqF)jM33t&T{Se{im86=QHT?$*#BZzJ1{)wZ-&mv7hxKcr8yNHjBRIJUSFmY*PO zA(SKAE(soZ)af%&d zNQ_X274In&Y|eizX;TYP;8a;_NC)lG7QI05kRmqI)+3lbP~r3t)#BMJ1j8NA=-O<{ z`fL97=Z2a_J?sU%HQ;@A`FlzM7fWAST2|lllqQVr?^ky{-KkL#;VVX%>A|uG&xBNJ zW$Qdyx|2L(cm@%M*R>ghg4!!N`Y7^G0sK~%KzBPj*t zf>@Q5l5AIS>^0&uns;CXsar7`;7-gUczIDvnLV;W*5gyQNl8#6fKce$Fm}??D!lPe ziHY%yxh@A=ip1VqRmQ@GSfEu_@?ao)R5EI@dN+gX-fMG|5H~~bP)F)M9%vH7hH>jtYsywFiR*g+YtcQsNa&TOw6aVp2%bliSV@=51yhir&ra;1O##3MImmfEZ~Q4VVGLr)^2j zl)nmf#>$X1gWe-%6M@5K1EOh*H|Natf@j*C12$%iHwDC^phHO&RX#9YvN@&|6VF!# zG>bGZOD@`US9T1FTpJtmOf4|BlC=epU@r_of;7som=bV_h^#l=EV}L7>oE+5+$kt1 zNK<5JRw!H;5eH9z%>B`TDaXbAPiOpHrpVd5BUeulLhBtaHv*!DxGfjV6k&f7hvVVG zlANiN3r)yL+J9&8j7P0c?%L*AYJX_T0(ffFXAFEmm_D@w5y5{D#>AekfwFtlf)OT; zqY{iT0>G7(#6h&Z_TRvs9NLZCauVa0Y5xFoZ9;s)rifn5Z({6oMQY zsp3QmQ+uz>IS7`p0DwUR4l7>oWKWqz-nlU(q#t-2XddrqnY5Q5%cRLViri5cnvz9H2ihQRs0Vo?O+m0HPTUY%?haXVJ==>Z98;j< z=|m59v2fS-OGeUvzH!if@k;1%PgM1_Qqjj#gG&T4zQs&BrI4^BZHx)j_P=)2{5vRf zv)s5R`>Oh+BztSj_P*+u3bkx;Dh@bRhfWZA#(_NZnteyEcf#>J%}apOPeln@I=n`T zW@Z=crk+KLFulFvNFvPKG_~yZ$61nHxlr(LxltyVi7jE6qj*m2xR5=FrZLP=G)LRT#W%Z`~4!M9FzC^Ckyl({JL1zlh<(h&R78V2mO~1p! z7dt-6+ddZ^K50aJDN4I&yNqoa^6wn{I`&gOFV!Da*;bYeM-+zuT1Hh#3{;g2%v#n2 z8j^RGxK&?!yI)Nz$7dORz#$8AXNppOR9vpyUP_^Mt)4&KRtWOLXP7kK4_>`RSJTfy zgwK^;SZbD(Q=yc(EQus$B=gM9tgJz`fGXD{Ux{wJJ<9Uos^#+9aWX*ljFXV?91vs(ekF3K}YEda`OAedkU7 zXm%jm-P}RA+(v_q+3u!WI_(~DecUNaN>Ty=ktCGIyUK;`cA3065le4njWD<6EhXi+ z6!8NTp(!GEfM5-v6ViNgc3Nz?mFO$6s9~qXD(NDgsS*{96vYbci4@;pSvIP+;y}MJ z>h<9Jst6>YDM2!1kV%qH5=4`P8q8*GQW^_&v?an5tR)~ME(QtPf_4d=n`v3ntk>$p zDdn`ndTW*;hJuE=wdoSCC}s+YrZP3>uX$srhLV3diP*$gfDdhWeRpk_JfN$EtxG9M zQ4cT@oFOSnN>rrj07&6j4PwRCT9+DZu-ZGth*x{8%F2$Skq}9cQgNY&3hLjk3hYq5 zPF9>$$Wfci%L`0{OR*Q{=%`DS*@rwpa5SyrN<>M1?V!I6{8imqqez?1qrcd)g%8@XwO zL1?6qKma9P*-#$Hp*xDVXh|zlgb~ALAb5HsX*9FLa-}y;^NnsB0Es|$zlBr9Nd_l| z;j~y~W*3K4OHmAwFp6qg=;QMNp0b$;rlsb5?xPAy_|`mC z&0ETLlU2bs(PBSOaW3ruAoHUI+I$&z+IBmq^Pl=PV z?jwjtjaP}}tb|!5X=S=s<$9krnLvzC;monsxnW?5PaC%0*W&D-y1sEqYRsuh zj8eBzfyPz)K$N8I)JjtrlUK|Z<&-F0G=iVFDFI#~!%%5jls0L_MBoKh_Bn@ofT7LQ zxo;@vs!XGnXy{^Ue0x7+DDYV}63&AN!{JJbfepRsCXt}`jmn$flPR;wkb)d($6avB z+h*XcJOJ+(CQkqm6(fvMO{2TXfBS1?G8<^91+Lv8TDG3;u%r^0jYWDOzzIA6zO8h2 zlvV!#p3HmHMo-TfsUnVAbgh3hppX2JqoA4}mV!VvRwH(zpDm_pR}K4+z5g=K>kH2X#*0-MQ2iNhE=60ppV9)W-)`;(WmkUaf} zO29guwp5r?8mGEE1FR`TY?YxwSdeN0-$%128EF?iXrLX3ns%953mk^u!sCqV?2CR6<^RJ8rF^5byofm00y1P{C{l9ZFgCmomq zaX3W_Jxt8~Rq75uPwGD&t*6Tv)@j4A)xm3O9ct=u%qpBDLZ+NDY>uZBkqfM{FPY@3 z2=?v=lDB7jiIryTKVs{;+O~a2a1{gxog-06#1)~Gkew;;Ybu!{vEMe&?{Wgtn@*Cp z^&$k6B%Pu`2`($ejyhn91Td^4sg?D0;}`0ulTTC&`L)#ajps0Z86cVywS#MQw~4*) z%(-i_JdMITwy;hELx+z^N~R;E(F!;7G}^ZSoP0=0$H=BVm4?3q>kM$33~Q;y-kb?( z<0(lgCd#BGqag`9Z?ua518c=7?3W=%##A{j~R+rKfVJl-9_$=pgUlr9k<%Smy_ z@+v6<9=ek9{JVTErAu0w+a+pg6X=wvnle}qqJE?FqakAbLhE*Htj<)pHXDddPlQp> ztznL~N_K%=DYi!g#sh|xm=;A{>Mk{auQ%%?&2AgF%B>u>)<9FvxR4Y9kT8`A{vQ_8 z2MRRJcS|&G*u8slE<3p)q@b885Ty(f3=Oz!5-8SsUi2ZFC+S97&-sI@9YYnEo*RbO zBotND5K_d_N4Zr}YDuo3TW00Gz2mL97H6B(lwCNMY;9mDq%5IoQO6Ra-V9_J;Zoj7 zlPuab-d$W`fJ$|wBw?{5L4oTucrpj0x~wEMZatoJo+Km=s|{Xb^N|I>WI)vD5cjx1 zJbnX!wdQW!3GSF~cIapVVC*uYXlm7(EzkEyRU0)fK*MMN3LWsjP1!FBog%}bmSqGm zY(}bCu551pVLPww2SRP8oFaC^yf7e6-UHq4>!VQk0!}B|ee}6*jAZ)A{z>Vzg{5_r zNPOQk*fVeL?Wh+300RPveYms*9qWdHpE1dW-bQ)2y%4nHM_ETaDp! zd1!En@fo9nc4iK!>kBA=}9S&Mg)Tq)w5`W6yt9v zG6f14Y$8k?eE9qL;YBkQ%PrJAyHkQ^`f5u2J1@co78?aBiYiobyvGy>6)zAr_sOuh zTX>}W`m9QvZAB_y@dFAZo}IYyJ80kXh=0PQg#p0gItCj(Dwlm__0ESYVK{G0`e~7H z$`6)=g{Y*$p=z%yadkB9C=t@a557u*&fV-ZIb*pwLa+5)T|T2H5T^)9R?if8l&J9V z0CmtOdtF9O+8JSxqEjFx36ziTNra?MGl?e(Cp|gH+2cR-voLi}sQ8UU_`NOD258n1 zP5jN}jK?&I<(J%%=!0ni$ZfiEU(E9xe75ncJ5&JLv35$ecR(3PGZ0QH#1a7$jbhU| zWBHYJ(tc4H_Y)e~M3a{0!Fd{gpx)H1fG!-Q65;Z$`;%3 zAeBJ_SyaXxaD%oyv8egK)IM0w`M^>|)lAYT11c$~SmBVu0THVCN{CEj?FYEbmT*jqXT9w3|B}8iCOp<(D2*;+1U(VcldIihDGsXdrNSN!a*_$C`2`Cd7!#dGX zig}wMf(cfpDP5ZCkVhJqvsi83ED5#9@58*eHvwfA8DDo8l_5w{K;oqnrw%bB^-+Dz zy3_)jy3`H;9YD`O+vQKWbJ5RL@dU!K{38;R9G+< z!A=9OW;9oEyScTo@iek}L7#Xy`A~aZ>7%Z=Kg}%pb1I2=Pp9*po5wqzTBgO<1z%jl4GO<3q1Yy&(06IN+~|^(PdIFJSb` zE7Z+Y#->xSF(REe1`c-W%<8*AbMB2{%-?@9e7+NE+Mj(;0#G}&Vnk|DoH5vxlOzqM zhgp8=W*3Tw2yHzi>QOyO9DK+TNX!p0$TC)(EX2ag5dgx^}9(=UFr`k82 zvBc~4wd@LzK_iG?Vf(g`b$pZo-UOut1nEk!8!;*eW*u``U6fecWbb}MFL1iznJzqZ zg@CrYj)JQfGtTvau&tSG?1WnB!hhlIc_D75gMs!1S$JU}~SihZ?PsVPWOks?S~3vBf$ zVKKnr(MAWS`JCnYDRSOw#Jv0y5u7Aqn+Sp`NZwKbmYt|w)nXBnJ>?7qmf-R;%N4ggBE0B|G|ClNxHNohJ(WhCJU0XXp*Nf8}5iWM+kpyxhD4@!y&QdV}6 z2Lsg{I(AWa>CZ_qT+QisGJ1^2ZjVhv4l{*gv=F7LD3W$rXyzjKdS@eREw>>8#N68; z^E-~>@vCQuFyjhAC+;C66CEZ@DqxueY^6DVMft3y+{)a8q&nNpf#OIoP_DH907z|4 z&`vZ6bT2<)xl1xoW(qV~40eMMqr_>k1v^<}h=x=oY7me#9go&HBHkM}UP01HMujA# zb^ibm>m5B59^Ff;d{}iLDQX2SbO?fvBe$r*tHAt0aO_Js^>+d5n?-!RiBjOWxx8US zabmX>5F$PIY^_(?#CY=*w_fE-vvCSPv~0N4Oyb@sGtf{$KD`wzX1bvb@Ii^{COxxO z>(YF!Rb7_yqESy*B_abHesR>;1={7T90mr%MY8xP0O5*XUG>V;egtgTHi zTGy}fh4kx*Jp>rb~7nu4woEfrNR`gDM)RB4duD3PwtUCqH8fL>2Krr5Sht;s3Y zNYs)-@y0>MBdZ*6#-vQT`@cW|Aw{?#C<2qyBMBWx4w|Gq!;1847pnegohYlT@!Fbo zXQ=tI6fiqc1aa9Tg-`{JBMPZ)p+MJ@##r6hN`eYffP5oQwBv~+;-aES+caC7Ivsee z*;3R2CPvNz1ONcQ0000$6p$E?L!_r3+7`h6b zV;#5-1LZ-!@vV5FMTHVVcu zT%SJVqRTI5UB#W{3>WuV2I~eLiPrxBS1egr+OLIsyc`8VpAo?-Ldj2-5l9`QGJvE2 zwriV{;xF9T^5LZ?YW@{nVDP5-Dru#5Wy{J$mRQB4HX_7}-@x_<+sDEP{x5}7S5-CR zw5GQUGE(5;j^6NeNiGQe)@JbUVaF1Z58Xb>@iW4r<qSw5r9-9V->&vc{hinC z;55_d;za{87aTf)>8+dw%69oy-RA!QB3-_Jmv1GleYe~6+e>|Y`0f!J{oGQy0iFqdZ>%2xCRpSHTYc9V7ad^RjhHfeje<;b{tf#;;c=(siwZt`%$;WEy@kt z&qiK_B+A%$B}xc5g(iEqk&G20NGUO?3Q}b%2_XA4%aNYj=#eAD+KwrbAcMEUu_;ty zHscU(tJSBhFHN6_RG5ZT$=N?PbrUbaE*VjWQsGij&^)GkSz$~mf0))%Ns50jW@zP# z4d#|YL$O~hoaf#A*|giG=A~)UN{B%cXT+>@fK)*S4kjc_*C+FB*v+jkNpPasMOqpz zEG(fT>`a8Y;D9@&5r~xFAW>@Q-{K$E&b-TkdRyp5L(cf^Mn|Wh#PAFXrVIv>TrxZ^ zpy9NyMsYg0-tkMio6EaMbsIDU8Z*2$7mhl%*-{n(?{y?0L@Vypop|Cg{*KcEklk)Z zbcWEoo5l-eW4gs|4)YQ;l(tNnIBYW;aH|BX>d)fsmSM)T-V4!8`$)K7n$=ayi)Bhz zB9MDBW~;5lRKE$Eh$1+4iyPXHKs^W*qlf*cy!=tn@!oiYF}0F za#F1;P-W?DWBOzx0|sXSq|VByoHy|q^#kgQsaPgE)9#sK*w$~xF)TWcg1)+|34*Pw z>!y~PjTWQI62RogCCIT>cO*4ty$A$BT0lxf;Sn();kKmLdmX$(rEg{^ zEBn+^(uq+38InLG0wbodderJ);wS0qdR~+Ip~}^iReBVK6G)G_FB$<@8naMxVKwRd7!s~Qh32$ zo;wE4ibi7oh5c^enATjzI@y%4+^v-}9GGM^_>5Vy3X0r1mZxN?Jxcj|<1vO89fJ^r z>23fsP5HS~UFc{dUdUFWV}?8l^1`L9(A=9H-p$apzPFsTS9nre(v46;NFb14!5&q7 z-mE%>m%3q*X>hy{2Ep=0JZ(!%E@PUqo+X0|rv*LI7Dhv1V9ZMc?(-WQxIOZQ|It4HxfEUx(&Z&OV>BK6T9k3QTz=`E!f3tss`V zqBWMXDdJ$j)A^1E%mL=a*Ri$u32%1q^LEA4Hvy!CtSO}+DJ~hoTE65FvkW+qG!5Py z>o3WB`&ZagiiG!0rNV_WK!_;&R)e)tCxD3rP#>r~$JA`6inl>Cb!4r9gUp(zYvd86ke%4Oye2v z1`Qrn!J`;PS)?RK6gX`mF~-^-cg~H-Rr0nXbCASZ#V=tp_J%F!Q!G=bQEm|gnP$W;Ax?hW){l} z2mqwW@g$ETCI~wS;wknYLcY547Ho>9zoxb6MTmuI;DV--MPw)63hOaaz>AUzu(3Wo z6xhC&2=PwI@~2s5<%jhK{3<>qg$z8g{q=1ggK?gn}>FYP4xL-*# zBo)0buQ=X8&6I!7vYsI=B#}K%9Z>ADQ%EKX<>{tJ01;;iym6M6h5rC^I)>00C znSmHj4YWLDMhIG_2N1e#9{hWjI~#{Z7bVE-Mx)ur1{5l`=^wkxuAKUbhe^Hh%4iBl zNh1(|vx{xJvmf2ud#;|-uAF?GIMbJCpA>AOk7kzxfF1J5?RVQPUR`l1l9jgVV_PpE>TT3<3POg^M2sj4 zZ<{M9eJj&3wKIZ}PQ&={Flz@=eNyCX!_^GMo-!6)s=(;+idTw@51OqfS|(;^+@{JH zC%TGleX1|7GA74;U+$8-(cWD52yMp`;X>U=g**^`(!3N?CmF^lpE18`>fvs*3R10! zFi69UV0`KqO1)d)-7Ulf)fhbWSag_mT@7p|c$umUwEj#k%_5dlPX7R1kl;|sn#VS^zvX^8z;xb3e$_gnhskH==Fh&O+Ay9oO zOE+HW`emJRet*x{Y35QnJ=33bvpvfg;BfCRQ6n|lMi2&MlAxi_hlI5mktK}uK00Bk9WRghX(S*?j zj$!=CK@l2MTrzPum;;9&b!}7l5%jD!Ug{61d`d7LY3cI59U}{GjvcktvY|IRGesBB zzT5Itu_UORV*%87`oY7hhb`hKuiQUc*pC1y0<}!n*r2f=@ey--d_MjNR%>ojQm&!W zCwA6J3rKZ0JB`C@+r72z!t~;42Gc?ADOApUt)LU}9s^cB0AJhVuMCoytHmR#>Yc7o zZ@rG)0J%5SkHf?Gao{V-6e@Juf*MS-1k*TG#3~wj8MNCK_L6VdDuQq9;j=~sI+I~F7Ui{rHMPdq! zfxvJBr|kpRZ8w+RX?;wq?OBBNC~WjloCg|TCs#U+=?~N{SM`t5YExC1x^-IP62t5j zYVc`O$*;qz3X;EJ*-Kd1valB%3}zNaJH+5pLBp$HKi-^DuA@em%tww10z!a^(00dK zOel4MTh?^PsrehMy*SIAaOqWA*X4}cK}m_>)2X|86$`jUARlH}Bn=FJ*oH%X2OrY% zL&(^zqlh~o^@0dJVw2k_rdn3fu#JRm1bKo8^PpSR{{U1lPLgzk6YEZ5sj34eM3{{= zH6>cpnxJIzCxi5kk<7&&>l>RJTv*$Y&TDpUbPz~7kOXuS3Z9@bJy_9*v+s$7$RN%W z5GH!IZK@aiNiqC8terW_p0d3$XFL|GGvqp|TwNx^F$fa4K^uuyC#8|Kc%~z8aDCR0 zUdNdyVVAzsOIuI0rr@ZC+#08-bjI1BJM0vr1Bf%WWOM_vt;5s*0I3Yu*1m=1?zGY1 zwG-3hluGpo5jWG;#dzx}Wk?;2Zyd_P#C@9)p&Tzw&T*Ci9$`)ZBq)d^V+54#*^V1< znqf>Oc>S}$@E(0$bx!!UD}s7E{6}$KxYWTu6OcNIhf(4AhYzU*1ar?Qjyly6g+xdy z3~hV;mvC*umG2v9d_8o^l9xm+Doo0b0F6L-k>^TVvRMk!t$<^;V__a!D`I|`X1M8+ z7+pzhIEW-+w22@q`Zr4w2q~tAxaM3kwzrnaZMP!;0V7N(08&Bd*k+KnqQb+6j^CYB zZ{vaK#w>f&t|QjmyGkd~1XJ#yGsxTbj4Kn9=}@Z{^+_VJR^gMb3+ zOKuajE;dG^(<@4Lal(LG&zEaYc%7;74z!)4(`cmDMl;nWc*Oc|*SrfpWsFK(Dtfr_`WBLufK3cyJTJ*{-{qzPK+%!4 z^&0aZexo-s&wTQp>fx~CscmkyU}_GwQsZM*&Js){(H7=AVK^shw@(md(or;cPUb&X!yo=Cl+WNc<#r)0TH zg)bqd*K=@{BtbxJ*9lOV)1{rF32z`*SU}_3z%95TSs0ko#h@}lKXUjO&Zja?LYKpAWR4VFmDCPttbtx+OYA5c= zBvvffBr&#}FaBElYH7nd3pB`n_U3GZ%n;CP9D`kR1Jqc69 zDPcZ%6N%~qO+*=vn}v7bB`R8oAnh7FIG=72)=gb+r5xG#UtyVdC*s{+YMdu9;gU1r zW6aERym*kDQ9WHCp@`DO6u~2sGTXLm861H(t0dnH(=)mJh)UR6!)=uJVp@=drC1dt z>W~y*6BD+wBQ1Y+lVI295We_IlmKvmv4*MC5LK>;vk6dbI{UPx)t#_~LY6{Om@ste+9U!gF^eBa*`pMz z>Nit5Ux?$_rZCaXC2dtC;z_4Av6bp8$Y4+?RaI3`0;snJ_ItO#d0RGo9OoK~Wu(~@x6{n9YN03ZRwg)DGKnqV66@w$j+pYZYKGmDt+71Qv~T#>rfp>3_%?`HkxMhf44EjINN!A1*C+5 zZqf=#1SS-fY7neRnT!P(OyQldT(40c4@r>X%yd{+oK~`0JU$|fS)9P;xJy*64Ij%1 z5P4-L5`!2gQg*jTJI@f6*VyCNa(Q+x$)sv<`fQHei`xJQLvt)6sm7PQC?MC>i`aW?AT8Q=s zs+x%eYqXG2{z^531LAMkACDuO-O_&CMb>P{k@k0sR-xn$6(-tmYAy;zu2phO;B+?H zXABOtc!dI8FTt{3QnDUx>9%dlRTwrIm#2ppjvPM}r>=U4+VIqrs*!d^@lE9x4|MK8 zK+7DS@2sf*6@B#{tzl@c~$O9DV$stDA9axNRb zp>CUo-d>fbQd6vt4nN-*7#QM6*fvm}!sgcc`P+Aff`oV`}{)71=glXTM+!Eo9+B&da?fY;Sd(?CY(svwA=-sETr0>b*=g_pKV%G~bX zaqy!D6>SF)MkYtjX)CsQQteIsxlPMjiexDuB&3wAN`TT(p$Y^NBt`@hVROb`^-OVS zF-ojb8kunNWQi&897Q5qd%Kzjtw`K~skraogbt~d97~FfM3~vfW)#j>ahDVn1fd~# z9Zw*r&kaEYfykgQ1NX8gH7+BIqKfCF%T+R&e6w{e4A_BC#MoVI0PH+@ zvinL%LDd3(h)y{F07v6eYtC9`7U{NeO%$ZcH9Q0ejiDSpCydbHf#ThG%o0IP`SP;@ zdg5uySLKSNkIXkFAt=Ncqmg^4BImafcdQS*yNQeyIC|{#sMh+z+R!OYu*13rpiuHu zWBNrp6R2#1!;LFy{W^NC#ApmS7g8`f$_W^jSHUaGwU`rjYR7HGweM~TnYYRh-}#8@ zC?uYZojA=#3*N-AEvhe| z49$Cjd!MB6RMn>JtV*1_Omw!{$I}|RH@)W8R?{qMR@2@+Cucz-c5K3s75<(*V`Es9 zavIDUR)@<$FrcKUEQs63%kFe^vDH+Y1AYu`GX2ze3A=d*`}Wc!u0SFW@1!p8=3{0E zMYAwuoi99{xE(=60!YA`Mbkyrnen=c405j;!m&DbmL;l_EYkTBs;S(Hl=nUZ`ev_Jx26ux7G09=n+=R9~CM@vUb)_O0QoqWk)5YbbqkSh|7!V(l|wM&nu zzYSaL!ze~D;-~%zhqzJ$+MWF3%L9OvxKF01X&0C>#a3X%Vx!8PX@rH8Fxr%N-C^$` z5d~LcaHVbqi9E9VJj#+VZGMg)m^7un)w34C{hI>_{^vM#%FK?VN*XSW<{T!pQR3ZH zmQol3)cBnmBNid#7mhur-M#EP_@3NN{e{YQ7M6V0X|vkKX5g5&>Xs5r32OCm98J;4sdi*uEcg0WqPzY6d7V<@s|OKk~C!cLH< zagZ>8RgDm4yZxJATDsXt(xfO7n{=iD1P~Rc!bsXiAQO#Z&iNx2>OEd5j^;eyk0n+y zIDbBe=AfkgC=Ua93Vf~dL{X&*=WDTB0=x&f_w%Qex4cO$Vcyyf+>RgZ zB{oS2O{J=e0+o5|)Sfj5a^tfr@3!&eq=rT-`n}*h&E-XWX?I z;jmDjL+GoZS!$^un+n0PD)&hwj+SZ$cxEvz*#weG?54v@YkmTp?GrJ5CKaV5i6JNi za0Eg{2bXq>uvOhSlt=|-)hS7n0O=wP3OQG#9-5$tNk!A_3X~EE^Dug88(#Kl5s9}7 zUf&$d_*HPT(+Z+1s~1~8bjLxDhRRgp`AemkWgPW5MpnThn5ku0@R~uq*nmh84K1a- zct*Y9yt**s%OJ$cjy`nVu3xQb)JzN}P7}5dUNU+sH7`opVuu^RDyS(u=;9&c!Kh<( z2E?jAm#4DbhYA&)l&T3)B7cood;S!;H+IaD+L)LmM|ij~fRGJ7PmpswlM17p>!2rk z`Bd=Gq+oaerW1d^mKlVMKt5_z`*l;T=CMWbdT6&FeN>cWEFqTqR_Csknib1&x1 zUlhl21gMfWlMke7TR;Sl6H2H&sY;uu>_9i+%XbKJOMyC56XH~jTQtcsKcy5r$?n+9 zL$5t-%WR;e5FBtWRe(@QCsJf$c8S7^&M%8WfqL7>`GYc~aN>B5P{ygAQTz1?Q%w4( zxW3zg{CFs7efCuHTapm-XZ+HYjk{QW@&l&OWDtZ+RzQTK~8W;(JF zt0W)`0l3&}srq>q8{&>M6IF{X{{RT6IKFVNz$qIMsIKw^02Y(ZA-3FaH|=|N7UQj5 zsc->4g#PMPZU2=9HIi|h3c5=$l3bU^UTdpu@N zx>Z4%Xs{{=!myg!Vf?8c37z-uW}O)oi6YixsIXh`Y^#RcY!F=}s!3T28#aSGamS=q zL$Q-uPbst5Tq^Y-x}qyTV{7_@u=kdebdL*wob~yPS+Y!x#nKN zo7URlAqhSu6}p6|VTgc2f!QMtG?(chuhEZZD*G-p|A(AHrlinu(0Bb{j34hr+Oo=VFqBsSq zC$DHD%Av>m9AO{vE%H=G(CABjUJ@p8=?RgKRWGp#`gf1kEhS{NbGnsCUZX5mtg%ew zIV~bgRgZE3`vB<1+SC1(o^DTYnCg5CJfex0*%iW4Ro*obI6Tq7Z6Zi9J21wD{1YZu zV-)gKI{{VLg-0iIv${MYSosj5{g+}+Co+{Z% zOOHmOBS=bzK?W2k9+%UfR_c0(CsP+b)W=lwwMNKkEfSS^IKRG{FQbVR5}+E7VI18l_g%?s2$ zGsb3EvN;_OF$P$ZabDNmsw zN%qjSt=G!!wzL+1z9n2b%zDP!Uf`WH!fE95A*PBOYQ#djkHlY4Pt(YX<2QdZR;S!r z&q|b4@iZ$J4Oxg~2~YT-C))r`32T7TMik041F_Qg(Dvoh@>8;jP1=>RnQ_cl0KwvU zu_+ZIPUV;d*Fkc8N$u_Wd9~c8dQSi-&eq-Qk^%vf)r}S;&UyR#^Cl;jD5HEPXk(=^ zNjiDT1dQfofL)@F_XBsl=fDBO5c(3>C0NPAK7Brs*HdZBZ9gmtht z#VcVkf_i3!YD$@=U?gda8xysN7eC?GUyljR&qVy#;e>g6tGvSvb77E2h*V8kQAtiAhG|^7s+2}6 zyy`=pO}pEd7lqS_CN@dmb$Kn zjw2(LUph*OiA^8vGN87a+k;H4(%{4u07)?>0!LQLowqsV8)X*`8q^af?SKS&sNgzw zQkU?~ufucSPP0xQh${V92K>ON{6?IHQE{m!6pu3#)H-V= z?6S41#2pC-_!PL+#yT+Cc6rj*E@rH!TO4$9R>3Pvx66V+izK6UDORYpeJpL4^d7FzmoCAQsN9i<`#kzMvJCTS` zQQ~pvK&Yol06odoN#Sbm7i%R1j<87hQ|q~I@i5@|`;HXLQ;<4Kioz&yth-MR-N9C$ zbY1(E*z31Y3Gw2aP4Bz4GTY81iP)lc^%6w}uCf+xcA*LwZ9;I5AwZ{Bx-;qKn)m_6Jr zq$Mf@tbnhybbz2S+0jMg2Eg!)J`|&&$rPbu3lWX6oKcYltgEpUfLLo|t@Y%L=KJ5d z_guN?hUei!#r8vywe|=RhTMIt*gAGps$P>rB>w=-r|H%hwB|Po=4@WEtQ>;d>Sm1r zxfb^Jy@v|!H^%kBh0DbGp(AHPMDwzcvDudHv`ST^oCFe|ILA@*jCyEY$Ud8~jL%Vp z<}9&<;54`u9wMoUiSVd*Nen{rq()|INH4UqYkdca;3e(re5FCxUQ(2w3GY-O@FW5x zM*~SSEQ=t?4|I!k2TFA(z!!-GCm0$;!i3HPu7aOc*&-S>>5c6T>{I{_e=Q>WN#fZJ9b724ZA*oK$t`G&bBO3vR9V z7X*zd5fWqqq0j&k!gX;23ZBUMGNZ4)wdisSV3Hg!FF_O%Pgf90;}r6}M6iU_V|l0d zrDY~Zi_05=opLtf=lLc`TuXzzc|?Gd;W~gwRP7-s!65iT^7vyiWsf3AAMZ z+&U#mI?3*tNtCzVE5zf8mllA8f|L_BiPvtgWLzf+%ov7Ws)rJ<%RelYlxo&7IAvI& zlxQt1r2)CV+v%?{qQfh4<;IYpQkO{yRA4{{Qin_ceQHC@GnVqpM_f?^wF*)~hN)Qr zBm2{g{3_`xX2oH`XlU{Jqg7b6@O;dxWmc5NrGhHxv9Dzw&lAWGzDkZ05`6g;jSQhB zN>UO4)O3!ZP9|}awDre%>&9{J|29+#APCWF}O>SV6W;Mg0 z!fMi%niDUcJfj?v5%ywG+nB2RKo`>IiyVANjvP4o^m$`6rJH?Cl2(}{3}*q>W2bK1 zC^PD;&6qO&1=I=*7}lIBs-&74xTmJ8ljbRpKdgGJ;PX}7Rti9<V~lBU(B z2-}31#sS(!8wVdzQ1b^l8M18Bw`4e7zmLnI};#djShJ?7sD}3t3@R&kjqYx ztO)dM?M))YHY||5%CaiK`B4HQy4u=!Xa|38hwtH-xCaa= zCZo3+aH8G4Z6%iET%U%YM-EuH#A8Vv*|L~oe0&50v_N5nlhaf=$An9oHSi) z$<&kP9CosfCtTH->MAijVtD+!C|au9y&@IRM*>8v+hE~FVVzuFqq|YigvjpF0$Y)U zX+{KyfTe0b-x_U7xrFJyfjM047*#y@PlBkewKIumc z4&nTH6*|8VJc=7PZQTL{h}c1lHpq>YMV_-gP4v5_U2dZ24qWLrQqG=hqT)X>g+lUt zAt=eg;+jO-08x54HZaSz*SVMzDGl;~IsYm!=2_(_y%b$t91JTS1qb=h( zCjrbEJ`}|2I$DG`f+Z_IAG?6G<4$#J)q)AE+P zg&>DgG>;hpbD*T_T8zjhK{Y4bX4ctCJJ%a7GNhG<+fXc+QAt8nQU`bx3N(nuI8YIt z{{S6l&pA&5%otBds3pZQy1I%Q7Mdz*h?Yp6G-`PxWd=DLbZvhXHyw{8?7y(rve({1 zugX%=61C~pgQS8&lLiz9k~U0;pt3tcuv0Cm7LKpJT9DW(K^nmWN{mSRfsTVUeKPeH zwY?)?-B--rJEX%pjgC(Q*me(1K}S_Eco%flGNQ&1Lj-4YJNu&HNF>(9iIpk{KgAlh1BRR?q#I5;VZ5A4`jdURRTaTt@1r@55xMmP>{3@$2(oZEM zmGspRMOz!%NKCPqOv-lZ@v$XI_6``dLI_y^fs7r7Ai<6pQa4&IB%~N55r)wqiTBWB z_;KdCSb7yz(wrJOo$`JuTLQeXIwbVf6Ufw+R0%AyOth>KuCliM`@PVcc{*oGQr-^W zd&H$g0t$kN8j`3=Qz^o9$bvDMsGD}cO9iZdW~C-bAtVA|rb#e(1BipwRucpf2|Uv* za)k_vb=((GuYvcyfB<#9_!vS!#zEWXQVA2lj+%Rpn+~d&JdNffpta7^bpv4<`{%;! zN8Q6sDOvRW-e=B}5K=vVf0w0ksHuw&frULoMwIMi-EVhG+%QvnSl+~&p4xKdVX1=< zXRFpe72w{zqi!6{R_|4@x=h)dF)2}>`8HSbDvV6*W2wZRK$H*^ZG538>17S62o0B9W(GKBom}}4Uuc}Dx~A=gTHKv?cX+RIeRfT^ zp-vGlI+a670~IAP1yLmuaa2emiT9^0x4vzsos|alX-ZT8Q89rcNgE^xfhI*(I_I3v zgLRUJrb7pp3&7}Ro?%@Q`4q5K1TONJ&DV80H@Jk72|#YvzEK>#m+Vz{-UYaz27}^S zkuU`9g^`Jfja(}c+PifbiY-goD;Tm@uIuxKM%~gUprEDDx)ma zWo$DvwMn3-t)=p6t0`#+ic0xnbqvWkB3`{+ElOsMD0nyV_9Lkxl2}T>Pmvtq4!LtCUmE$ z9lc_g*{7`0=KT1Wo({?#_6hat|f=i(g&4j=woVl4Mck8#8RiaRv9Qs-XZ#uqxOU^Xx8IX&74u2a~o(aNb()=Nv}0j9N$f+7+;? zuTC%q)e|ICnc4pUW|tfMRPTG-TQ;DF91y3La8YduI3`mP;;=~jLXN;20O{sd$c7xB zmuX|ekU!4h^#O}aWlN;7&n2%ZD}Qw8RF$#hjd7Yim`m=ctj2|>VqoG5NATmvXfS5F z5YK11c1v&kuGImQYVTTe?sL2wb*zm}ag>t<1wafb7gy7ai+=H zB!*-%ElZ8k)4@q`DMr%71GeE->}&)H%$dvzTSAF-De-~~X&V%!Yy@@0#GES>QWv=o zJ#Cn2OGNjLsj?M{wxuW@C|1;t2g4ZAq3Ff{xZVJJK!m>uh2VLX7*?wlIF=7qwJQ{h zK+-6lo>^rZw@L1{>k>m<6x?zy&R387(#IoF@z|LXvcTiw!U$9 z8G|7$ywjQzy(dIs2`MqJfyV>koDEm^TKZ+vy4-waE|*1#G+5jS=y3{2DCI2_js8xa zCy`@WWKhwhj$}alU*0wuF_vblX(8tbJ=O|^6^S58)dD~U2?7q87z*YF@MP&j+ECd* zc66pRfu!scJ5D&9HAfmESe9O@p9_Z)!P)C+snym&<%OCVFLy~}z0HZSadF@+Zcl97 zfU<`?Dlr(!R5%o!nDiJtY9Dggt+2F8k^!7CNt{6*drry|vi&w*r0BK-RTPyGVmPK^ zs!6<>fTYt!PQF=<7vHi-NoH#g3mad7yR|KMj$jBw35`NTl}VZ6Mgl$5Ahl(r*)+09 zEAE0?p2lZWsN$Jx!R>Os26bkhi4l@*iepXGuPHIlKqMf#& zHX9tP08ROed&73-=r}Vr5>|zfmzpE*AH%2q3V|j+hyn~@LnfIe~WW5XG7{-5CZmQ{_yZj@AFjSrD5th>wL7XK>wOE<18qy-)L7Rd;w5r&37%kns$B@TkRx#_VRj)A*&AOKYAjlcb+i z5O`zJSFzLT+}%^0x?#|MyHZosWo&l{tHW}xCoKMN&r?NH=E7=#C(DwZn`~?~DoEDG z_$P5@mz#R-(Mn3gsZ+>}Aqr3_I(kx~JV5Lsvs&iWyt(z-t{fUdnO+B4AS=Zf1q6^m zScI4Y#Mfs6gbAA%87)kQsSf1)h zRC&>2_1%?lZm)WH$8z#svab?Wk_OxtWQwG1)YvPk*o*soc_HQZf0cMVID4lGU6&Hm zp*=VsBU)i)Y&MlE>au=dgKcd&kX>Rd-r?E>k6~fAxYtrWxfmWTkhC8Ofwu|y`}(L& zcz~mb#C$1zMVByXp^jK-Lp%mh%M@trM$*E{hBWSZA^H18e*Nfb$3vBxS^mv`0$vO zU*WESrMgZSh>m*dg&b+MGTaf!Uk0TP2>t79QQPeS^o?(CVAq@PN&AgdBch+bs~7~a z;qD4Cwns!w6%@ZjfUR0QMH}B$1~L zZjQF34ZM2k#+&aBo;?(HKdJaX%YQfd*tTEn?foB>w%%6D?zfKa_Sb<<_{2x=ic6-y z|JI@YoMKS*(uN$7k5p4(`ND=YrpvgMNeU|=_oIge#O7~xSrmW1+Lvo70+vJNv@IMo z@fmPaqI6=Vfy1R~9`%8@?%OgZ#??j9Iu0sG6QutD#}Ya}rk$8;7|k3n!~5|7ru2K& ziq4n%g~DRYJsr%oLJZZHFTd%yo z%hV9!k9K@bIFt4$;+cXqGP8<+l7&Lj2rEi~TiLsf?*j_a0m6_Z0Cl24DFp0MPuQ?h zX9B2*HC<}x_elD$RqA8c_oob{hg8Qkeg}}U6=gmh1qB2%!t}M3`JOt^QY5L0HK##R z5;}myf+S|K&+MSG`{;V#LfmnwQqrL-J|Lh~sL1aWp&&#w6NmuUJaa*PyC`PIGFsX| zd2SR*Ux0#8--R)(wwY3O5T!k=!I-vR#82@K!n%L>eov6|z9o$1UZv*xd?zSkIPPG= z8k&ZpqIx8jy0y$^IUbIZM*-?1LeY7_0_D&00F?L;XQGQ6mi+*qHL%)xm>*Vf*yPEbLx!sd!Ryr;SemrP%_b9F3X8_ILs*>XN)Sk3 z489V)GKP{wjfF!K@7d)+oVwQT>7}V69l26goIp}gHeh&x;vn?V63sX!U6(TC z&VXSs+brdZU+1-v%;l8Bhi``rr+FnMo6Vh`VRN~a6o5$J2Gt7uy4_aSPqbi9rB2O+ zKbR1lQEY&L8#Tr!qOV^mV7WV@-iCjy-AIKfzDEwM%+)goG0P1^s?#Y)zjB*YuVxw% zer1yuXtTBmGYCW&P=2) z&Xd$j6-`ZkIg1#ABQz#L=u0ptmR+_Ddyp+=<{Mwj350PlnZ(KI>#pE#_E_Fl!&Zr% zEH(nXk})Lt$*SS1#DA`M?j?$)Y?X%;tZ$bNJlAE6`Ef-nG2YTL*^%`ZxH{W|<{R!? z2{=H8nlXDy5_G(KAkJQI&{&Zq|I6WnGSKp=80yh zgAS4_Q{gZW!PZ5Ax60zgw1f>o66~n1e%B{7K0!pyd=zX>q79Iy%Uz0f!W`Rz0Q?lyw zVa1_o1g^o=RL5(yd&a7St?l*wD$*cR^Qc5qr%hD!_ounjKUCAOno4EB=qfg`i7K%& zeC6{mb($I#b_4@(-qWO2ylFQjn{Y5I?-%6WDITjM*;8KQqw+0X-Vush?ofDZdj(^_ zrJziXn#-?lqTga=voDAs>*np-yIDa5 zaVB{2k6s?iX_v1uwvzBrC^9qwu_Ns&^!_1;;wtNXCiR1(y;I6KhfvJvPWf(;@tkW6 zm5|R(1sqpbKwNypQa{+0H1H~?P6;h?b)=m_K-hR3J<-O5?PkqhH?155sXRa&dehLM zf$FVtb5?N9{Z!95&UQ5wlVUlO5tgB2j-pX{YNxz0ZBhXsl~JeDsN$d!fCLSl9PO-b zTdrNWrGlwZk%{B8s}7+QbA51{{+(mFC(||&TQkSgTn3(=wUTL-q{T5G^vd>-@4FRu z2o3CP0MnF8fyN;7v&&^4UJU^)r2V1}*`B}GjU7M2`=dF#{MqB3NWtED@!a!@QDscI z=gT7rWvQtYVpR-DR*jxniSQAfK_cq`E|7t=%^c;e_em-<;=oMo9D1h{TO|G`nP<~) zQhKeBzX}GHEGHk2CR6_aRB>WdM+PZ}vqepXy9L~`Vib!cv01Fl2q2O!IVt?P1`e2s z9b89A8)J?%t%8RELz15Gl_ZG5BM&e*V<9JqtucC$l`|(vv!*eWGp-!;IJOT_B_(W9 zXcAOyvR?l6v;+a|xbMT2pd{gl=^GDS2X0$7>mcyrHXgCnL9J9RH75T6FiPxQhnL_< zHv}*jzJ%MrTZzb;D^QV2EDfQhc*2<(_Jw;m+TY^3llBPFfY-IHW5f;$Sl5O*o@R*lGm~%(OCPJu7|jAov&@w7Cf~B4=uOD(w%uSg zAok%cqk&G85rqLRtq^}`p)z23QT6;j`W4Xs08m(-X!J$Y3=0XQ&AHAAt8x}(nF7ro zGff*bSVXfEV@q5CjE@N{!+~u2^?R#y&TtSNwnY!s5)x1Nya}UR zskR+MmhPn>;d)t6}E%{V-bg;%{*6{kwr zoC?@kTv=L^VT=m{sU-G1>6UY0lv(8g_8VnoVHz9=9xX#rDd>dzCJr@GXf2v0z>@&U zfseX`FHdbI9K4v^62TF9sB07S^vgVvx0fnFs$nDFMg#$Co?-pv znp|!WkQIp>B<%yrg;`K;-6&enl}Pc*L6oRtw}>Ba5g1UZn|fE4`fb&Z>fRmllo@vr zq8RQOjza<@Rd^qk)eu!K%NHS6V+K2m`=npGT&FT`Ft_glLKF!~(*P8xZ3Z}T90;ZP zg_y8-phl84C17Br96|Khdh2kn!+)jKT`BZA)9ks4#K~QZ($r=esNTWExU|hyfrt9A z7{K-ma$vH-w4IV9&tJpJtk8syDm~SaG&mfQs3XoRAA4JScletQ8mVwAN~8`mR2?KL zbQd1)uzWr~&mJ&?NP=R5%tC)LnKc)-<~}~rZ}C`tL+RnVO(=>-VpUZp106VR&1Fk! zF6U?jd@e6;DNGu&QH^)&OQ`aCe)MD1KA~am5~l{sl@!zghyd2sprNHzKjJb;a6O}o z2r7huB#=K|8!5n$t-fc-V_!GS`<83+KGFoeJD6kjyV|bkL4N zo5PiyxmyZUF+61?_*Fee13;|7G2%>x4ZLJ+)zm?&9>`r-PPFv5`uRB7T}2vE;&icq zW0tNs?$TV`kyRDhcN<*Wy6~9=H+JfEJTOq;6(0k`^r=eD?KzVj@Y*m~8#R6k7?0Af z+x`>R>k@hhaZkg`sl(-?u3GHTkmP4OC56e86v7ZTyZzHuAGL&_YsgN}DY$LH337Cj zN8P{-?_U1^46M_EV=dGEpL$3%Pb?mFHX}ovE1{lb3L=(yp^{mt%NGQg z?_f!_@5xDoDfIa4;Xp>Dy0fzh+DE1y%8B2$X#|GW6rPL|`u;m=xpJ>S{d;s5tF*lx z>9!@9@;+_E+{sIX(_+R0GTU$J+4^0Zi&i@Q_9$Z;|6d3lkGBAta=XQ!) zc7F;ejmBHllDdVbvn&MF!GYKtwBL}hOQf}SF z^`a8f?4h)RldV!t*T})>B6W z)HT$upo)qbq%lg2ruR^!jt^Ns%JT>i5p#_24T1F zJLHd6Rs9gmFsyYn6*TyM6!584mk*s1JU*&0NBg8K6_0Yt*X_w?es0e3+}O0xDb_+j z8&jx&yn087bqa(F2GF=vBZ%mZ5!FK;LYoM$^`S{kNg|p|rA>)dIf!cnSaljwLIuXq zJj882k~QXV-P|^FM(tW4_bj-z1GOn$hEXxHK~WtsJ1QnJ8Y?_Zd`Y6w*ZTamiuE40 zvkZWw{{YFbSZiD}7Luk#mb#&iqynnQEVk0#I`9jv`4$WlhPP^Z`gfi5(Its;Mk zNP-6vk_I$yJ$Ci$C}p2bho(6Qhs7}rsV*yz*A1Ihu^OXChf@Nig=r_ANr|{5B9o^w z;?<>R9ii_g^C?ozjfu3i;*z&oWuEaW{)tM+Pgya>q5Q!n+bd$teif~HmL?!1l|k!~ z?5bbrZXqoBTNKGtdzD#n>1!y|fLmw$jl!U6#r^MssnGKcyGF|sV{p^40Z8sw{xU?R zN87iF6_H(^U9RPat<(3gL+uFKnf;}hS#}Hspf;x#h5rCaB|umm@V5D;5%`204R_!Bpd+1ni;vdnLA7dTDAjBnOlWQCle)LC!$9HND;!5 znJ+PPpD$tc7{-0W+c9Qk#Al*5Phrc2gvuExV7fw3h+D5e! zeH2LB#w#gue6`0CLJ&119|;Le!HF9_?gB*7eyht~qBAXj%hBijp+yXPrIt0Lt!ZY8 z!1*W5n!!hV*p<|9;TeUZK_$0!aFrlq)AkwikxxJT&7~xz2})#ttSM)s1K)rN>5O_P zHK_F8i_zvBXEM;{OuJk$3?8y9MwbbWw-1)02@vgiXy0`;OrgMHO9Nm?xhIP5Gh{l@ z2`iK-Do(u$0tk>uNFWh737QvMUf*137syc>ibC{{3b5x4nj!6eKfig2eM~5(5L?uRgC$ykll|-~hp!rsdmzaylFngb z^P1FdUTNmSbcU4CDQzjk#8lZ!n#nqchxiQaSJ2+DRP{!`9)Bi!rEiz2f}Wyc>L4*} zJ6pPLl}Xxrj~+o9%VYv|Y6ovsAMZx)rz1l+r9X01q^1t7QY3MNk&gpHyd_O9%wbUq zb>F#G;N19*_qVgz#~NIT7*GXYc9#yUIqIOpI?(k?G)&YuJos`_Qppu#M^zl<_riC( zDS#44KzsXi@#8Lqx=18x+t(v((Bmw2#=r%*94b&KloZ4(01l|*8$D=G$el~VD6vXh zyI)6BhE&d*<8d3kBOv=KDgfFX4(j1r=f{+{xB!hqO!dg>pgwDoIO-Jg6qgbV5g<4Z z6QgWT6v&D(&pkDKdrYd%0Q*V-8vef?8o02&H4OwQqq7PMb7duNTdI#A!fdFn3n%WM zsQCWQ1TN58AxYUgD1Dc>o79$E+ZY}`+D~T8%}0n;VVJy12k4d=kSi|5E@ekk*r_{~ z!uB2fI8a;wgTstr(r4vH`F)a^OO2DnsU|^_8c00^2s|lm92gcjo^@0)zW&A0TH@BX zyf52=goLPSP7{s>g9=l&*aCeC`5F$hHbd#XLMQV~8xN?AwZ-Woxjl*dI{Penug^bh z07I?;JQktn$KyuqEysyC%yGx#@}zxlPx@tuz_308LREo90*)X^>~sm+^W$sIZj>>3 z&sCqsjoU$N&KP5eA09;k8Skfgw=-ufC#U^3s-(aml9HzOpr+cQH(k!9qb=raAPbuh zj|h#HB-iGIP9ctd0)g->=ClY+Gw zP?c#DFnG|_=r7ZS9zy8NE@bLn8V(^+mC08_QvfX-a!kfR$bIedCu>_mJa`=5&EWja z+LFSs@WO%U0wbz+)Bwff`8A66&T;%Gr}OQ!Ktcc@&Z#7xJa8U@ zy2;oiX9b4445u)Mb`q(YSGkVppcz>0QE#$6ykhG7Y9N{D*~iO`Z!x(&;X>6oV05Hy z#GeSno}Q|HnrU#!1vi$hbz`U`-1gVEejrWaPZ33FKzwSGv{FAX<_Pc%V=mWY%GC7I z*BE@#7^?4rRVA&WsnA^LG}m4oTe==f!VHj^i5v*_nh@F9o3`IWSg1FuFp~>Ofzo)u z#)_Xr256&V6xp{?$1ocB`v4W$^2wNS?_p;_da zloD;?Pud`O{@x)M>eq-T(EK8SOJ#4XKuU-b0073{bz{bBvFePwRVG@jMyqI~@>yJY zd$ygnAdoIihu_0{d&yYV6%&pIKXqQ&rjYVO$U0Y}Gv6r``^1(3+A z<^#b!mSGldl%vFuaT6*eKpuq2j9>s@Rs?p5ZsWVpmpq3O7D7^l6AB7tMMX&%e|4A~ zbpy8w6+KFHdne|6D=T98Y1Rs_=Fu;hm1?amI7X1h^G0v9SZy{w!N|KO&Kw26;GYTF zorl)5Cv`KMhMak~%Jiig;3SAxFgzq;4EWQqjkF`=9JZK!DW+^qWrPyOCz3BPv9^Xy z)*uUCgtz&Iv-X+kf^hPRA*Vln$Ek$6s7wkNGqJWm@mr~>5a3n}dws}U$!>eruy)Ddmh94#?Hf6@J z%vo5Op{T{gg&rK|Up?{W3?+u}9Yam-*6f z%(!GiHVDD1A-Hb#Cvp0R9Y#@nqdm&N>jUw|khyVe*b?J^>WClcg*Vpq_oDD4M){u# zaxUKWY9Dv}M`_VPz4+>~JMu7Pdv=k}vYJKxw8?#;{_4>9u7KS6)eld&&0Q`pU7B#K zQ#ROxRVymU-@KM<2O!uI2_6>VdCD^&N?Nya2mr!Q4^5s%4GnVr^0CX(rp?{B)wXUJ z1df9%k~qML>!fuTT{_OjuQqlF`1Xj{1$U)pq^+q3KZbehe+qIxTfP{~VGnbFGt zxh4ymv&Jd&n8qD3o|ZMEt5_B3w)rHc!MS1`iT&fL#ER0;~UD8{LRIMV9~^-<6aIw)}ZOnPdvpfX69eNNH_tspxH zA7qp4AdUoAxVg*9Fwh_Fi20Cc%I~+W&{~R@nA@gsB3$FJe{;vHq+>yr4eC$RCKc5@ zXF1_mo+4?g=;`GD0C?(}15_^?$dK&wk<2E+$uT;TBURS(P5$lXH`!V(WdX!NP}BsD zBUI@Tx38+PcFVUd+RL-smmIqNgQ-AE%G9QHpdCRz4PZnhU;rS2h9zZ)dd29%;sS;$ zy6JU&!LZ5B=@fw^NCvFIEw~LqI`SxMv&_tas3RSpv`)?jW~YSxM{ZgYRr%z=0P0I` zX#mU;OHd^2;71yDsr6gwNo(k_%ubsTr=E|?nHlhzRU_P46W@^CHt&$x<535a2RAD0N0+Nbt6C#~H*>g&*Pt(5h86D7fHK z{!!h7NI$nRJ4~iU-Yutp-S+UM9h2UL1+B))PSOeZj-N=| zjUTi1GrCQ+-!$^p)(2N~=7`#5U=R#?4lzlL_v=5SKgg)COzlgU=#ddB5^1oCNQ|?( z=scM!1(8!zueyHG8XhdQ?C$#AWT9q^^5{t+u6$3&+S(-Z-``nlZASkUMoFcE^Nf}CrW>*a#!XI&xp-YQBG>t z&q7sJnwTOk^_DnMKvFkc=m67#=JzSqiVu99At^}kE=s2u5sB1Dj-9yCyFXbu232m} zXc)NsyJ*49Ooqy43W~K7K_?gl0wPWXq3L?HC#GJk&x&;$B-BNU)X_mj1QS-6=4NMC zo>_dz_qiV8d6o*GZ6xbsT*GwUQa>!GbQCD5X;W%RP971Y#7L8;i83h#zt;XyzG+p( zg`28vJ4#$ep%WosfCR*&YRD2m5kePLvvqb%rHiP&Waz{+m@a6Zny#@cY5<0~LoNO2 z{HskPk#!*1g520x@U{KUy|PP77YjzD6@y_TwO9K&-3lcOl-@t1Ys$ zTcioaXp)iqVp<7WTTlQf$O-^ViaNMItDdZ8&Y9Nrdn@#ot+Le{AT^JOZG}*S?%cpO z7}0OFtWJS<9`ShW+Tb#7d%{{t(xs)PDJfna5};!l7|#$)P%-}itSpYo`}uRsKi_If z4k^$Uu_#KM2`CG4Wht3Bot4L;-l_V@>JmDtj*#@Ss}zcY7pSTtu24j1rHh3yjnUj% z;E)>O!ksvx%d=ao#lv3aG8GNoNnh274`qe=XLj9LBF zB&tYsMmFcHcM%t=LR)=GQ;G>f17lfHzyh6eJ+hsuflIIct*r9f1m-SUsI;V@pe5aI ztGysMrL?qERI)?>3B+NIb=E&p-l6g?bDyC-N9g1g^>zMrBT!5+3DAU4W@+JuEyv1R zyGD(?AP(D9@Mev}85_zEJhUyjN|L06D-k0>*Nos&vEi7B;u25QUB2>V@4kyd(p%P- z1Mc^0LeM2hS`^SSn1urv;XG+u)sD4#;PlOva3j_}oWqDsRYgxx9b8e=FU-R$`EgFP z^vclFLc5Vb+!S3_?Bt#v=lz|VXAvp!i3K0VP9ZL8iWq`rGRlSn&K;EnwMa1;Fv_3B0=O zLmI@Vr^9x;5e(GWdPZ>>*@By?F(|P2&G{2&ISsb&rKenVYi;C`grOr@g9cPigvJ{+ ze~K%p9g+5izSlDU0L@!7rNrsf5}@LIc&AE-@aY5{Kth2?TB4RYhXcx)&aE(?QhiOE zH6>7ITmqJ^JO>4JxY4NSW%;_KUf<~zE)R%xIhQ*GV14N+@YmE=A|dD zvk9%&ePUb+lT3El}qKK#@__JM! z@jNScK6>DltSFPm5>J^kN)fxunbM=yQgEIk1|El!l0>SjU=jqc;cCbh(S9bK+JqD58uJUE}OVVcFe%r0GR{d9+*)BIaSh^t4^hK zB}pYS)DQ2VyASH0Nwd`^BR@_vHWiIy6vBAnqou{Ex0;0vs{*S@aVxN}ENl<6gm-y+ zjl!Hl(Wrt7lBA6%h>_yM9llg{-+0=BR+3N%3m|HaokchRIE}TgHBNKtho?_f8FL)# z7E+%N%+YKnry7d1u1|8;0Y?w2nYB|wNV%9CIbzBrkoD|>6R6W$&S}mq?wUG zsg^p>M*Jp@mMEFyaZCh~&MX_uA-1aR9LQX%Zd~NyHfV86E+f83)}pxuO(7`+g#-|#FJaXLh$5{osQo(WtuNsd)83Nc zd6NXnSejoAhY3kVs{|&{b}E17+En{?gptt6j>0 zhSI?hlw^L0t<;c;Y3obkw)hAnk2Gglf07+3vI<;*SL%5r@m)eIPX~*9U zFTl4@8Dzbt6r?grol$MGwP7Ia(n!MQWa}SLJwxZpTuk$F2>~DwJSoCT5O%;OCu)u-Xagp!n${AulLt{&tO}06 zqBaZ$1NcW=(Spjj9#5i;9~zz-7$OYv8Ko|g6MuM-w`d2pq+D$m7UX!A(%~A6drb6s zQLDg#;S)=_@vM)7D$h$*6ew5~boZFw-UKy^ZSl62Cf2?9!t{vK&(4cGrLTdcK5^=f zK+1S#CjZ3VHazTIM9jY*VjSd;h@q6fgM}`{wV=iV2Dk6cbe8a??ju8!y^{ z>ImNp8y|N1_O`r5XSq3z+0uf^DKJu(LW)lisFFHjqzAW)F1Aj$7PvTqTOc1Pi8R+u z_^>`PgivD`A4#)~eKsTS)78a=&E-$Itr3LS@4xu2P>?OB20!d=m=TKGpEVy`6OWeO zs$R}=%b+a`+$kgi2x|;|a0F~P2=k!(sK1I2Q8LC7*sgEs&T-3FS}bfUD)54~R&%mP z53^TcqJl4O<6ag&*=A&@)bc#MX#|`{h^OD|2Ap$v8n!`j+rE^Is_yjx!w?Q0Mv6us z_=Dtj!>eZHPFs*uX}GPT&KvIYWYrskBjf0?Z+gQiE`{teGxr8Z5X#}OV z$Rc`Fp|C8Cq!XuLqfgPSr!GOt(br=k8!%=GPs`Ey>{gx-x29mi$IDe7bcWz=(XVTA zA<0rhH|DOi z*LrP&EMF=<876DQVlrXX7`ju{NkUo`H{`8-2BU{{V!KqUgH4jaK@K>Rj_-xE>8G zZ-voLr)6~LN9iUmFEuKWV1q~2!)U)SgSAcW{#JouY@~+>C2kF^jsYNjt{Iuck2;+< zdn+$~-PEf|J`|oY#GR!*17%&GQ8Erd>26TXxHm}Fiwnf_L$)W0QBYJQ5mU=DY?h)5 zNv};vCQ-S7LFQbww-R}PDa>wjTc%vRDsc^flr2dnV3HD4A#2i1B$9N98!)Vo%B-2T z3eYs_l0@M#6B`8ah?9w`JL(s!oOdot*j`%1>v4soWQI!gr#@9ou&GUvykas{N4gtD z_I3p3=2^LI-3@M`4eF8*Rf+*!th8RZSwmtJ zvZDwPa0wU*R~QmZZ5UQRzr0tO<=Skl8SkBN=|US4wG*~uVpGJD5|9Z|5j1LgYn8El zpOQ!QuMlisG2*hlelJ|iWG`7DR49ahxkVUQld!NhwfPce_ei{d_9^b#K+w`QLIjY1 z#!)3o<0p-G%d-8=JByU2$<+nEwHIy{45d!0B`GIr8%PLF$pDZ9#WUuNBw~1ZhFkg3 z641>F8>5j9AFey;jN5J(+ z<3a6ZWk!C>wHQm(Nd-|>g?2TbnsNK_Ik%J#+D2Oy-Q%wW?Vx3@g@6d#j>RXSkK*W1 zI2fo?Kge3&Y`xn>0GDAwDg(yT=@<~Gm{;)iD-1;kxf86tO6dkpn>yurJiH$jrjm=! z!;uBV z>Ok|J{r$?JyI#XV?Bkg=%H1n%!J$%9-NXVB_K#NZ!)c(uY#X-AIcqmo{{XZIA<*bn zuM5NWhDOwf05SYK2SpN2yXExDJy4Q-zM_U4N+_{Nk!CEg35V&UcebhL2h!b$9LTNN zxi@xTIpQcKvPg|ue$yQ~NcLAN^G5rpwKw6_q2nGqqr)?X&%AIAE z7zu?hN>V{3Mg)nHRz!gU0F9KhqRScArrGgv%nmyEvjo)ZJQOm-h^)zSedLgtVT=t) z+Aa^Xfz{pH=C((rjcZ;7LHc1Up6vsbO3l;nbvHawcY;!%c)6qNVkn? z`&Xn)r;HFF9j2kHTfj3^JQAdi^)i#R834~*V?s0;7(}j=qZC`DTMR%$#*d z4Ur9y4C*b)brS;>046#%lSfZB=Nxwt^efRmu2PD63jD8%t^1PXY3oO*&8YPgUWSi_-=5ah)FC@i45JDR|j z*{#m3K_=E5$SYV*UXdSk8SAV`d94>FHU)g?gVOyz4VrqHh#WeO8vI%&N?b0EXiE{g z{{S;lwa=DXHPA@l?Y^Gy95~A@P1w+ZDmVet)9e&P|Fnl+E- zSp;&KTGEnJZsra)8$q4R@{%(8C>{GRQ=4Vp1F7SIo?j%mhfkyv4Zmk@@| zP2=~NA@b3I1S)H(>;=zp?64fS*lR#Yt{62$!WFEir4KVQNf>tpRy1ZMe74+VZT{#j za4*}(o?j4Yf^eeg>Q^tghWcNy!Fqtbl zmjyFOWMly5DoCScNy}) z;0q@iN+9F3lYp40Yjhu0QDJhjwYdAvCd%2x2nuZq2~wIHGzSWo3E8A#L=tqXaO}g; zPr?oy6RT@aNt}I2O;?IzQ~^aiwD95#D&WJZW`R>;Qemr4O%lC=v9dDUuK^h&M=`xq z$P$L60yzHw2v?enoIL1hysRfHZ5Aw<3tA9$c%UGptza1h6Nv}Ti~j)OHPbfB{R_=K zO~Ut5;@wch&K9!yU!|eT*h8{QVYmf)%A2i)h$^J&2;+I9;gpva4iXSHO3xo8jlE*0 zo$Y_~kF}JtMuyUrJV*3kLSu%Y0O|%sSeIE~AJwXSGKfbMl2pM>PA3Ri0s=$EMyn)a z-ra2i?!C$64*EZ52NJ0tubl^5xeVWTn-aPYy&pbu+)R>za^aB zR(lOh%=t7dltc;TSzTQ|nhv9LIdL&HIY1tQyw@S#5g(iRvBg>QDse1w`}{vTLok zfU%akvS7MWgpQCEiTL_bKhUQ{X>*TOYO`K=rSh`oM4^0V7@DAkNg$`Nf`wSvEk#X9 zRgHWs*B9Y_^Jb$gw$PvMj~?x?I#sn^NgH~|pe{*c-@D=%ClY$Uf5MS{Ld|%uQM0Zk zpRppTRgBk9Qo!v;RSmggbQcO!O`mqXxFO1{#$RrR2k;~eI!4ouJ8IW2eqqHdY$plZ z17!8kV~kSK;uWz)iOgBzL=bHoS%iklY`w}8cE5o(9vm2?Q8LmLaiIc_48y6Bsp}P^ zR99NJ7iCr;E!3zlwlEFW!t1Yx7a=lYjgWz``5HZWi_+aDD*Ze3vyP;+#|F!-n{yw^ zG8q=XFvuGXq^T#fMTW;1W+QrenhyMrZ|%#jDPv^7@=xMxBeIr~#jv$hLP1*k*1QLx zKs|jFWh3aW9fQ{4nHMk6Ed>=QijAqHaU@9#6;=}#w&dCYVtbuQ8go|22{X*mUC%(+ z2F|XJWe@<3KyttDUp)=zf2T?u7ph%5rhx@G>a=4$F{ z%#nh8-ZNa+WFG}c^(^@lYAh$Iuz z1_RHi#T8udpE3TiXKYtG*0WXO`Ku6;r0MT9MQrEEMzGWZ!9ex_rvd@9IMXV4K1m!; z$7KGsySL#@>EA5Sb=M%}XYxKvqPbd3Vy;!zHN^2d(@?B{n|YC{&r(TH$)|xFJ+o#U zk%&zDcu=`%0WdKF5vXcIf;Q|ST|Qv@MilkKP>`LG26_}Y`Ge?26fSjPF+asu zr8t*aX(=%5FRU3Rm0`_zY*VBs6N;XdUGb_|SgR3LZ!wfyBYU8Yq;QtsC{N`I0f!n< z3J0M0k_S-$lq=09B9<0YnOngiID$bQcz`4LRka6!l%17IH1zUQtZP=XF^%L|KnHrV z8!9sX=mWjKc>6d62BVN538l^yY3pj*s|}?dWJDO_n^qmhrEIFe>v3`0$DSiq7&Qtq z2d6w}V#Dg7hvhK{Khfn`c1=z$SsfSxRmiw!2ftzL;bV!45Fo@6he)KZbi^qlf=Wt7 ze=@4ugla5gmvC`?#ZH7={502r$Bvp|)4*}~nvX7Ar>h(@@)O18RUw9(zj)68AQ`-uT<*v~F3O80u~ zm3I>B3jP%|vw-R;AHyaHP{KtG?hs#OHkb(~WB^9Mq~ZM&fWs7&;!MyJjiy?_9~Z}{ zD(UeII+BuA!(fUwT4`%)5h0D{Nf!8^kL^luEI$p5g2q%&vhws zwAs6_SO-qMDAD0zrhLZ*79CUrElo8ZFCta=k~_iz zlfaxjUU5w+^*-7eBkfRw#3bTV<;J(jrNS`$F`&!%NK~VtiYhn-hLF>siXo@^sx;){ zS2)qBRN{QWG}hxbT`J4{x0QQ0Ybn>q=>Gm1B-5Z%W=^7$7|wWoE01y~`IiS!6$QY*d*9o`M%4zNI0>ri z{C4{1h2&pPnIEJT)iJ;`)@Avc#UPRLSX3rJWUwV;lB!6MwX`-PvEth|(9P3*;2Lq2 z6ZW1GItjvfO%=X$f#wH2RjQX;a2!&ON?cnErk+z!zbf&vi%A>kVY>Ia01vUX_HaqO z*5$#eAd*IsIzi#j8Y+1zBov9^9W%mO%NHX4HiYO{3JCPEeR^1gz zwuM1xL zqG;|^<2lEr6Xi~<^s1$>?CH~*k&WPWLN{XOo>J{kEMcr-oo*~Up^on4vMenf4HRe)ozHqhbwtGoKg8>tduU65sjRy#jN=zS*PpulBiS=uzzNUIH zfpw;rE}D8w!v^^xLJyNs8+mn57KMRR6rh29K-y1!1}`leWx|CtMw5X9Z$ZK-KuJ&9 zspC}pp0LiJdO7viL5(E%g*HLXF;r7ybkaPfA)~F9)iXGh5h7AnGSm-vl}DGul425! z=Gf>eN|7O3M_&=J?dTZASh%nXhy;zDXNQriqx8?3vFFOCC-owFTAXhOmah%2G?Mv{ zRL~jRVYSiRk`iiNm%Z&EadU1}v>e9Ix=W$Q8-*ocjX`OWl0f2P9-KuQwC0ruG?ayH z2Zu=Z)jR$(ev@db@y?!lqot)1P1DR&(BpCy2YwMMwN4*9`&JsoRJqUzE!&v`xGkr6 z^BYUDK+~yZIL@#LT2m$g3jtdsiKyRsnJloPo&_8GOWYyNF)a3dI-`VyxFat;~+xw{{qyf4<$+IFNQ2IHdI`N>5Rs*VGjT z0hD?zS(dOl)_ROo=P``8mb{07N}tpDDiJ}Hlyg|r4WOB;47PP%jAQ?y;#ITm0@jWAZ)h6!<^NJtz?+r=xx z2t?=3GHG4mHRd9&F%KKUHk8MEv02C@M>FyAZj8=PLUuP+Ipz( zefwKZ?7A${*L>*#N|T@^IHXFUM3V*p7(|t06z9+nRX(M<_ni}_xhJGD*WyBUgu*JZ z7zXuKlBdfv(yr%N+i^o?1GupVnHI-o?WJh8w{W^hDga^TOelo(lQ9*8`_uJmH(6*y zwkmbUPKMCJ!;Y;$6Qnj8Dlh?5#t9mZ6zzoi*Xw!eB>f-2`bkmz_BmvX?8IwY6>l`c zzHG}(H!qw5Gb;$oUNI&4RPJLf{>-gM#iXEW?+Gf>Qvj2R!^>_JAKm?A+Bue-%v$&~ zY5=&Bu_r(!px&v~hKv+W$R>l1t72ZF`U%vidR^77lG2>Q7APsC!-af<&#H{oFPj>y zz`AdCN@$+z5|>E8Cx-jWx+d1)EUnUw2uLY9RSEtWQdI{G1`#3;O*z@`)+6~QUj3t% zOYd8CMd0GavdWZ@;z4OhSrUSis4EacaEdW~M2po=L%I!x^^ZB_s!Ay_%1XH)T6k(I zB6=9iY#J&>fQW(J`dMd{0J@QV+j!Px*|M^>+qiMk5aub6HSj(xd?F0N6HBsxt{?3Z zn@94cG?!9dY1f}p5a4X+TEevJDM?avfCiv-3^AblFLV#pCVS}iHP>U5(w#8asi-9L zsU|faGdzgMqK@8ZVy>VfZX~kVwzc@fdxCClmwcBAWeSB56Eh%Tjyg#ij6j+kJN5N* zXK-y(mL*7S)HdVEd0oOCb^}OKhzG~06SqJhsEHLn(?>_WV0xFzA+nZ8h3T+rYLOh% z!#y&$$%jpfSx9$|Z*iAK)Qzl0y32b%IpUl}tA#-+)UrZiKcWnYS>QJ8J0^^?pRK&Z zD0qf4ugtB$w-4prQqq(pj`2rO=!i&GwHOH<0Ix_t49>UbJivN&Pmvmz5lQQ+aLU6) zRU8p5Y=qTI8gFgT8kAsNg@wQ&2(edc(9UiXY{QO~yQL7Mj~8?Z1eg#I0SYq-AnG$n zu0E{q@_Tl!ZE}WPQWU3JX_Dz$3+e?#rbO<2vS+i~tmvYry z^m(podi+7!mD-w(BVkOkOHmLT(smt|>RkJq$Tp_(TN_fF8=|mnlc!#s6oo6op*R7k z=?VrEd;pRut=#&u&hlhlX71%JGN)Fj?ix{Chff1Ble)sb^GT188=u@sM1gS8RkdUC6gQ+S7Ng8GiD6^JS z^~-~FQck>0l4zmA=csb9ifWasbczR>R*nMTwuo6+ksi>@Sl9+TZ+2%dPG$$}7N8QK zc7k9p?$x4XYK(U5BBGmrtZUECrqNkK(Au0+2z|$jT2qNhSprZNQ=uw4!gP`}q?1Ta zltb&!s=X=3`oovXHSVj~p9jc?7&GIUjZ7i`z6wdV?Y8Nqt0hoX`jd-rhbO!T8q>%Xqqgmm`{$`sI6;Z=`8RB>2UO3gtUH1Rn~k`{DA30*>x2KKqJCPliV zI)Avaa5zBJN`xUGU^N^L+ynwnI|UnWSJkEdS#aIE8EbbB+!qpt*m+6C3D)5y!V;7u z9kY%AV^}D9yX$ip>gnkO89NP%yh4>mvFTbmSB_erl8Q(?+L1HFYEPCV*f$+Q1^2nM zWS#xba$1#Hygfk?CLpnQCRHT8}BJC#ytxb{2iBpinORj?lX{ z-E)(?t9zi3ppc=aN>&xJ4%r(FkGrab`@Qv1cYIw%#fw(2+pj~7t>rkNqJZLHw52CW zY^M^al0@N5UZgP3UmYOmwpi*8W5e(&+%8Hwta2}urdDL5iIF_|uQH)lIMrlZfLYm? z1X}`l_4eg8m$t)~V5Kh!LSz*K0K)WxB!VCUK;mRY6Yh`JE$)AGK(K1rHw-EETyfPe zzhMdqQj*#hRE26FgsT#qV}&j9=0yBN@veyCU1Wwl4w4!gx(Yv&G?eXC=hba=gl(&6 z7!;B)B=Z#p=4L7rf=2f-w`>=fCOfoDf_!QKfv5<@gV+g9t*kv{yPl{DBFw;m% zVXn|rjj>MhBc#@{lm);nmr@8W$~QF|#NwN`DNcli5}*JxumBRGN$UV(iNcg`Z`G!0 zyH^6<(#4CFmL0iR?-t*7!z2e4`$r{8GvG+X?fXGAf#|j|>wBwxVXElOCNF|v^U~DN z(a%`YVcSHQj3wxt)1>b9kww_XTgqZ1musCPdkxgJ&8||<+NTVD(*&Y0#Dt$HNFOM^MXVCuuQ?hi^ z`qe{GUAq;5B%cwWNbOIts-mT&n6%`okYg{j&1MjW+o+o`$gHw^mD;HRN^FFZB}r10 z1QJvPOn@W;IM%Ixt@F&sB)Pu4ZqcvGmxIkV*03D5Bq(=@Qc9%%0CSJH9~7N}U#*^& zdb9NHfngHYXRIRTj0ttw~|6CZHI4N&A};5E_9(t(n|1F zokK~&YcEs1GJ2QEo|f>guFKS%9HjD3M6_|#Vf3`L@zKEHqH4XO5l%J{2>`sn#E35H z+)sbGw(QxroG74&N=Ah1Dom54;Q*Wj!Tum|#sZs>^>Lp$e%4sYwMDw!xVB-{X?Ebb zY!phIK}iV?1nFdzVoFMcC`e7|d(lr+de6{G-m+p{MZ=?uEmJNvNrlkXq~YbMYecA3 z7t5)N%(6nn`9*+!z!Q57-)Awjxw%L}Ln$Llg0-xHsNf6%5CXB(N^k&^NO$k+D|@$p zGI^G+n<=+xhi+8qZ4WKCm!ve)Noif`l3=YWAS3`WQiUwNBlL%_-l=-4h~#WbsMt0H zxNUW13)E5LP*gKbOB&8y*vr0k6 zPe~CHWi{$Y`-L;?n;NDBPex0=+>-eN)ohC}ZTCTAtLdEsOmOqVoC z3(yX&B!zv&JVYlGDZtbDht;m|+HRsZjV_>}O`&PGQ%xnHrLRVkqKp&{J>*82F%&U+ zwdhY+Jva5ngQd{*OAM;{>Z)2Vny$$azc~?jCYB2};5jyKzSG?wzLY zT&me=?=++@P(c_O!9!Psjhk^EDUd}Q?l092^KTPZZQea<9J6ym&ATnQ(xssAP+FT$ zg(*-$!gT^oC_PpBZ|fJQUWaAwtx|9?F0T_5^;nct`o_psmM|kNJ!OelsgMHp zc4r%H!47-4_Bl1ZyTvJ4xPk%_s6f(_GE5Z8fKrIU2?8o8?Dy*TdN;=P3_hzwq5F3( zTJBqI#}bB?8!fyGK`3!V>Nt=fr)^5XeIxZB81%h2s7N}?OEpB*n0yNYVufh0REslJ z%UEfH$4MH!r*RP}<+`oSi4M2BmTStDnfG7>Io)?!6j!t+b!vcQk`oYP6$6D9UHx9~ zLtDZ8xLn%z3A}2_KsMRA3w5xt;#v*q?wk7+jw%Y-02WU~UYq)l>aQzfnC3s$Cd2;# zmP3lpiHFt8DU;UaBC?WLo z(X9Q|?@?8K5yiT?l++Pb(L}!`Syw!*^FXxBWEANTY8L@&)Ridg1Y46{26Bv|&o;Ya z*s>GesHCq(xBwDJOo^EA>L4AbVWWNU`k>xyrzW<{t*+7>xm~MiFS6QDpUeTNN(pSN zA*seOP!qCEIQ5^Qxv!@ltJk5?^+s8!YHG0vOtQUu%*LHV!l<$WYh+0f!pm8}4HRT!-@R8Ba6dI-WzN7f%zo7H!bUFI%b{?^poqftU>=!sMN+61Ho#WW{7yY3ZXX zS_NSwhDTefgoqhQ92;+T?OATi?XcPc^|V$>n@S9W{3OgIfwO2NNjT9LX5UjA3ZSQlHEcl{U34D)BZ1jfG^90YgnGy1VE%CuIKsOV}S;zs@yPPBNAF zlZxuvTurGc7*j}(RSHKR&AF`>RE?A}nJ*~Xjs~+Ft&F=RX7#kKX5qkxQkK$|$R%1~ zM`n_g_<`|~U?)unH(Tm=dh^}mWsAJYYHfEnR_JZElpJHYO0+1tKuY`Jfku(tq>=%H z0jH&3NgwCC({5nu)@#rBvSL_92^J*hn1TJap4pYz5oHVr|G)Zwc(9fV_Xt49q#%*R&@ zm0t9S?mUxCB6;Wmk-tX3^1G*%F`nNwXtu~gn^TJ^(4~kNCIU!Ak_lJ}1P}m_NS1q5 z?f(FJw`CTLT4r}Fo5$4Ac}=bI+5<{(p5?FC$Aqy*%PDv zcf&e$()?#J;n+=9C4=FAD*1mCt(~H(hs>6;Q5=X7Vk#CoO{+BJnp7kMVV?NeTW)DlgD5qOl+sSFYRx6Gv=?Fzszr4Hm|nY9eFQXxTHGBbn0uu zLiLqsNdT=81Ep{48}RVyS57@K6->rH5eUT zI)hx0$mXXGSwBf6OxBGzt5pFW!WM28Wtv{eu5&UL9A#uS5Ty4-J`pM4+=Ucg6kr$d78Pk5zVu1iG|`viq1Nl8diRuI1rk3pR>>s}9z z;vHkA%y^AWAj}`j1egm^IeaotmQ_!E{pMK*oUEwSkG2xW?E}rovbWE!U1j7b>1$XG zr~p(*7^sgB1i%<2Mig){Lay1j_dUz5*tM~}yFyL9p<~H{iO}_eUH7T_% z#}oObgu0|4t4WYgatJbD5Mq`7t$hb%?5pa(56HPA3C(a|_>MJ-Vc#c1f>P9x6+Rrb zvAnf&$Rn1fQg1al3*=J%ojvQ081G{#$}%@g+ZMfy4qzgvl5sM9v6z zAAj>(ysGrxJ$B=^uidoSdBT^LmYVMvN|J&S76A%#0Vp8-*az>#Gw}QACrEl%fM>3d z<^01+%a-VINencU)dE?brWC1`N#tPkR0t;ACIFcvXyYre+(?__ZTy4ss%**~MkU4T z8o&osCyZgI0f^JGpnl9Z^EJ7+Enhu$w7-|Nb`^3G(gTWE4-}=SQmuee16rk8jQD}o zLw+szar7$;^jvc|%DJ`kFZ08Pe8IzT_Qcu;jLMOJEZ_3Yh_P!3FR&AHr~`=|v`O9n z0Om?eJ>G3AIyCFj1Op)vgn_SCGZ;`g{qN0Fp6XMV%4_+r2#guBv3*)n9|bi{X${(_(FdM;V5% z3N?_#Af_tOPb7fL3o8iCFd|}Pw*Z@;a5D_amR-=aLiHdOi75(=MnsK-!5D}bZ69xr zVD0^_gJ>5C7dIB|yZLpXK2r6voYAdn3Dn}oy;2f}!3rr=23=9~QJrk)D+2*4nil4&UA6nRsZdAlf>HremJ(0e z7xu^y5<$QNs}qP`$9b+8-3yl-LjM3V+Ha7REooEQm~bR1OHYA4!XX4F2Tmy3Xj}YK zJp%Nzq&dchevjlla}L9xY^o|?qs8#J0>@ob^7F}6JkIWt&2t?nLSv2hNjM6?azo#A zjGFK^)Hc~_bdt9`V^$*-5hM*joI*)J5(Nr-KYiN_#_rDSK3i?OHxMq}Y1fB;_oXOk zsD9OA0g_q(6$F9+UiyaoKe{Zwh;pWI$o)OVX>$ap9;K_SrpGYYs%5FAien0S)48T` z5QrL?LZFxBxj$XEwGCOO`JDU`QHZOoJvb+}zgj8NIWw zA@ZAt^ClhdUS!*s87?Z_ETAZ_O9=;2At_pcNYqFpC!*g*9Td;LfU`bn#&QqNV{3un zxT06qW7O5H2b_#%sDP z-6G7Mp|d_&>P|u!x?%XvJBP(bU7VfIV zEguq`$5|S5n9@Kz3(~(wuuogjWt?j%(zXorLTDB9l`hF%EMP$?gA3YOplH9*;GieW zWd^e4Z@@C{6y9JhRH;I4f>fO_lAS}s9Q%kn3bvHtQP=jR`;Ep6Q44#x0ZyUP78HxV z?QVx80{YP{rMZmBrlrT&i3zIWo)bhh7co=0GLsd&4G|UkU zizk?(S*ulwQvndglAPtzH2!#W*36r}%zx+c`Z|AX_wrv5RV8-!VxQ4RFs}D zCr~oyi9=BUz>0zUFwGT}U)rdK(yOa0qNDkxyz7p(=l5>p_*z6Dzdkd)r1_axgH5_*RU$q+Wp10y zf%nuB9ZHt1YCtYZNFV{yMgb)0#FNuS8_jr|T;AsJ_Xu&U%FGuRbl{dA6kvn=9(oVZ97`)_S{!c%$k?oqQRWyXk#hv~>E=__Y^I*0&PD(%M`bHQ zqvl}-S0TBs&%!eY-!F+h(81JfNr{BwB4ntK5`02-NZYhBoX;`_?6S0{FTGo8ef3)< zE+Nzg-T|;wNC);vfL5Orq=};S=@X@06vDp|IsD8YA;{`->qUnga<-QiCj0$c#Lcq9Tr)DwvTK$1ieg*Tk$XENQKzrF5V zK~`O@3e?L^e$XXN>j3zbw&_Mjl1@7*+twQMQQ`mqaU%*T z$+H*O%X2)vr7}Y=U8nX1#jupR&>!}GLnSJRX2dE}a!uwBEnryyB0{Xv*8RF0RkGROC zK_o&{0oXRCI_SHzjKRBH%?PvZ5|^^eb(U=cl%TXJGu|ygBtD`^c}W0iPK6S$5`{eD zle!z7KMdRsTnh*3^q6HHD%SHTaW})|f=#c!a01uEgh9ORMQ*H>)1)L@wiThY zu2i*+NP-n1_u&PCWC{Hw=d2G8n<~#)TZ7iaR`B2zf~~3`shTjKr32Yq`3 zX=PiyY};z;&zTEt1PH%$F4o>#QtxM9Or~w2hOeC1nARYwEd)b&O_bbaU zo(=b5>s2rFEh)xNdeLmHO{9a}wtPrTj`3h=F(#89qOwL`%Rh-V5UQubT1u%g_*oMn zR<&I2vMp6KvyuuVvZx}KRXeC4R(VC4PZDRTU7hX2M61Ja77|E6g(^S|oOF^&!b0%U zaEg!em#$a37xs;6P-xz?78_G30!x}w!hljr(sdLZSwVvlMw{`S%K3h;IAA?gi}`Sg zsWSC@O;3>Kt%Ygn>XGG+o>ttk(V;5!5)@gKYG${|-T3mp`3beOIkPuX!@RH&YhwVbNx}_9h08yCrJ(Gri z{5*1n4i^I};geV4rYLd@l~czg=_izB!;Sv{)2CS%$fk(i4dK$}A$BvBuKRawNKuB= z0RWH^1c)U4n?#%vNg{BXhw@dsV*Xm=K}Bs|-dZd*YNnP{@|L8Fi?vD=>!~RzWhVyA zj}XNV_9BKAMkF?w;?ArY(%)>)Zjio0AOlctah$N)QnAjkKc2vuq-@k2{<@ZHSpr|c6n``q< zYPq)|9tBDT!^C(s0)(ScBTlLdYB2oo(?4ExxZPzwYm4V8F{*f@Id2MD64+KGm9j@I zQht`EI2FA5=?U{y_Qa&1JOkzzip%qbDL|#v+$B<|)#Fs8#;pY;aZDMIM8T+{-J6#8 zJe>}uOeyrsn67PJ4k-#`7!9-pyf7ND1g9D?zlw$hp2uA<-lkB0TV%tbuge(BvSIWX zG%_!rH}d%E<({I?Og-@pGB9N3+!lU$UzsdrtV%Btxf;G*!{`=ggG2Pot$SEZ#D8)pC4N{O) z6N!?L0Zjd}Q;h_7DVx<^WXK}msRr{cT3jr)!dBj*mePjd)#(kA^Q)97q5^`j2)|0$ zo^H>cfbr}yrE@8IJU<7=soGl1IzR+#5t2sHG%x@=O(YaRsmLE)Hg{$pwi zl%`77VChfWs3a*|6QGqPQ-VZHiq`)CWmkD~x9r8jkQHT^Br;k>xP^C4IPSQ8NgdoY z$_Y^^*QW^y{{X`Nn;FY}P|h7MmK@C#RrT1u8w@k!_-xZZ%|ZOeIIju)0Bbap)JAO5 z5VqW5 zH5fa#M2E_xf?n-;lHh~LeZ1YB-OjbSh_}1YpovnkSpWs#k^m57h~juuQk~wtUgTQe zAu0ykA>vxa(3?k&wV}caWF-f>{snkcFrgdqBFb2%SoITy=d4PCs!CVIsH%iDIpt|$ zhCEIaPvy(5_MT_6Oz2oe5LIRZha}rPK=QSZZot z2(G00s*L9)E6X(snG&&#f1(tW%^R3v)J)8PuHvj^jpw`>zENd%beRPtm8D1RI}?Hz z;!N$=DhUE&aqA@SzcrRzC;;Nwe$h_2`mUaE+me#8Y;a|y6sZj*F{@OpPLie9M6e0E z-{_LJr&TyDB)HWo;TVn;gi~h9+WEybeLBw6ICzM>-#IL3&r-yRBJ&8)s31|2S${an z-L-@jh;gyrY9J{gL->w`7*HuE4N^eBP*VQDy4}U95SO23<%jK%x7<^zL)g02wS#)X zoh1r#;HyfKlLaX$5mh}M^!e+nquEl24(KLVg9E{Om5Jl{JkZkO__GyfkgX&Ya;Pj0 z9jS&GcQk}CmtID;*-mJ}61GCeeJzrLkV=yvrOZa3;)N103YmzZRrYajyjm_F7fTNi z$nKhS3xy=4s@$a*J10uCDoB8In5x0(9zg1bS@kiQdO4bK8rq!ah~SvoM?hmp-{Fz z%oU?2acN0tpd|_|5#13eAe5Lwj*+Vw!i4_0^c&S?bHn;?(rhaw;+bxt=QHD3qDlp* zT2*7U7I%t9nblI~Y*spg4xEs)UF+Pdn@f9U1)5X>i^~mnWlB*YDJls`ASc9R#KdD= zI&Hn>)Sl_fjrHhyXA%4GyesZO1LGw^8;0ZFagyA8W-aJP8uMG%7iU@u9=s8;mv$B%eG6JyluV z3+S#Vj8$gL=Upygt-+$JN-RE_o?6T|5TTYS7*z;^NT(7CY@xsf{pO4t4ojPr*`Duj zQ!cIKw6y98Mu%G}2WpHGprH^pZJ|C#ym_%JHx9f2FqEh*1QGWfVtN5MbWy~@@?KnA zr&mdpy0e(*Dcz&rPg#q_GNO}d4AEjyiDQyC7fsuJpK8|@-~BS~)!e)a+5`BAXe1HS z9o7ekoOoeU6~6afwy>h+q5<(Jf}z6#MDwzW$5AsjZ0LpwE;Z8}-9cGKYTc{FPC}%R zJk6w&&4@H;WRgX&3am-CmL}&0x6`tWuOw|nx81pgcWEECX(<3;0+dwT4WK4R8X6~i zt{->22}&^W6wio*_YjpM#CA+$ME4n9wYOQM>gTC^Qi@zxC14cC3z$l%@xxaflhIIz zjkZBLz~zE9q)ddc~ znB9hd$~!&f+9YkFuQ4wML7K1)-Z)0vl5*M~T+IXs_;y7{n(^ zK~|&TG9rW9+huy&UzE!dmtB1K&zBB}K~L=4NdgHbOimyP9x0-a==axVZuC=>DzdgS zmR_$7hZLT8WT}!$6{M=EkL2+Y=0`~C!cQ!17Xc+rqd-Ri`{~)Tx2EJ=rD|vh+V+g*~lr6qvkH7Wqs(wj&-BUgE% zIO-}-U1i2s+5=a|yGvzcpAMJWh}$G6B!krktOkmw@g~J`oo*|Vx(6Lz8&w&o#43(! zz+(A<6nl~C4FfXBs-s0VW;S9E21xpK%$_i}SHc1jsC2+8cWIdsBcmK>())XsR+OgS z#V`Ypq!~L1@DUsdnU1O@vigqow?C;!{U_kPHp^7G`bjD2<%jv3)U6`TPAYdxJt)|p zFBuIf7b{?_FUH&KEvD{&DC5tSgNgueXo6(wQb3Kkz{iLpgZ}{9Y{B*DLkxvLQi`2X zNKZ})1jj%UWJUxUG5Mp@2jVY;Vfdb6>W5P@=2xV{=_jtN@-U^@@`>*~O)W)OSjkd0 z`?qzrqfv3Q-H=)3h$?Z3(qabx9ASfJsGd)xyU|(Gjr>~i1GY7l23(|2uB`IK_ zgyX1)jAp8b6UjYr>t0)_&ABH%W_;l0nQCb;*rgQ3Qc8mwJn}=fmM_qQQL&^9sK^Np zNZ``fBFXY=CvILAw(4s@(4?tuIjF%X5VNHp#!L)gO+=ZUjm7vcF?(@vlR6Te4G5S8 zK`=H-z?lLh%>bA;O}e9)ahy*tb&oUU{G&%h81kdU@k)BB@gfKYIAMXN-Czij?{MDj z&CQd#^9{C#EN$L>N;^>6n+@T#l?0gCq(nwMDmPABdv>)mcD9*7`%2Unr(!lF5+Dz~ zTS3E&(5KTJjg~W~SFk)Qqq!A`@B4>>m<+){}HyTUexP=0ZEfhA;5};N@ zAe|$`RH&H7NTXZpN7E)x=tW*j$yt*NrO*9Z%($II*@G$IRdatW!XCARv^Y;1fT#V%{UTvcpwsFqs{XBYZn@DwyT2U zkP@O&g@Yt4Clv;Y$k8XpHEaR_$?3}9Sdyl;dyMs)Acq@Dmy8BNNRubLAzmd+l5r&Q6*#GsJnEc% zDxD=nNK#XzX$eRvfzSYe1|$NBi4JJD4}F@s__g&gq3Pf3JDTNG85wNhDE5%Z*FPnNmdQ{4&)H?ZJk z%*yKh@5;OqqJ?NBvO;wj#ubjB4wJxQXKeuU%SYW$v|+3JTwr#4Bp!kPU0R zIH_8uBn}?58ojdpnp%VeH>FAmQb~mUiGU;mOp=|x#p#3{_c zDJ2Nh7t)lZN|PHxmUcimdC-lLG6zllWqLvC52`xct%N2q(_BWGYhJ23G8oWB5 zs3~{yoLB{j3)xS)%v4^$aXL}_@uO>S+E)g2A!Ow!W} zdzt_W05q|<(~%BmyBP~WYqlXn_)xM)Jas7X>6s>nJEORp(Y^}rZJli_9hVQbTS|ul z+hSIs!vFy3t0DBm_<8#B^}W*kSF1QbS~B(*OI3-@OI;lJeQcGnN|7$-0uZrfcl9u_;|vQ#=qY9V|F#j^?G2-Q7z|wlrP0YZ5PD zI3r8u*>1MYx(bj$2Ne~mSm7WX1d~4MNUqN^)Hi7D?q=c;`B`x!A-?67hmB;)q^V^n zL?^^a01_gXUYEK>mvTa4+5Z3p!z98W#uA>N41%PyRkajDbJkYe`HMAc-a!!Cu{Mix zB;LFA<^>EXTFY{!5gIk0;Yip*1{1{2HPC*@Hx|!#3;Ct1Dq$BP4X~Fr7r!oyd*_O= zOP5Rip+JP8u!O|T7&_OWi3(BusM~9+6SVdqF|bgYYwSJlc?&I-B;)$lbfMW4iFu)@ za;S<4)L&ZyZEF*Kqr+a>UykW1=bzt3DR+eg*|!c%xrrRX0(n%D6^^he89LZm=4AU2ioUeiN*w!o~lgMWz0_rsls5v z5oEyeTB?fIkr;l4qA}(gY1N26TMk5 z!-Yc^c8F%_tgx~dYV(V@!|h7PjI^ZSbUL%GBpp9;NZCki%hPO=jbzHMpyerM!i<$K z1!KhS!bFqwZ5=%c194X%k`MevNg#v!T-M=-#k0UJ5()tTK^TIkI7s2`AXYGM*5hS& zd1~`qnQLXWsYr84T9C1*p=oKAbT4VZBn1!-1O%R^`aL!mneZN(X2@!CR%^iUDmbwm z9}=Z2RQ~|(kj&;gubU(+ueF%INM6q7WKW%CmI zBi6u@MUC#0J}9_outd7*rBVzGWF!G54%KlW0YdzRrL^~c3^dpwIE-+DqD%=J6TlK^ zA?ju`)NJjUaV+VX>*+A3sZTBlQlT5kqEJ-Rgb%xEU$=cpzJPK-$}R0I8AA-AYlA9L zNgABns$w?%v49jC%-gxWTaP@p+nfLj1f{*2VrLQeaVM&d2cUkr^<-lATF2sYx*;VWiH)0mf#Vy;1s0&)pd6eN-?;)fu}gVoMX#s%{nV z#KuVHi2n1k0MU|e>8IKj;Xdl`dl{X#cJGCUn?5Q2=A{TJKiPS#>TT zOQ=vW{V}wEof|rKZ544ogF0jBx7Fqk)Nf4vUCY$93z{N>INuH4)p-2HlrNWXz(}}`CkdjOhfr=U;>fa$jO~SR> zxJp*O?H%p96qs#Lkp!hfL0UkNsZg3epNE!bexv>#RJm%Yp7}>6SgJ zzJ1`Yh03`X5z!9?!k%{TqQKN=rkvu@_s+0V0dSBB%zj{Ey`is%Z ziQ}86QyeD=ph{U5ov1>2wa0C@%`yc^UA?~O7rEfF#pEf-7$rP3i6meER|y1@!nKs# z6csk88nKhp&cRxnOcGks7u>-dT{lNwj1bKt$ z>9TfF!Bpe=Q~g(5dU9z~Y?H|-l(oeu3kr}x^6t!4w{E_KFgnu3Z~l0C#al>4MbALl}!wC1{x;DcK3&vLyh}K*&k$halgr} zT^~AWP6V3cCtf;e)l*e9B#jddt8xI`Nh(5zxGGyy-Rv)5IM?Le0y*d5OzH-cS*xvC zD=}cTxJ^wY^$^H~V@8rIpd!s;H64SshNN3d--?;FS`-e?Z#`8-5Gbno>HM4IJi-3- zTKCs(%XYtee0VI66!lVB!YlvK*M6?PnvQmh4BGE3l6j%gl}wtGF3WwSeay>ZK?`qq z26!yWusrk6RIUIUC>zX}ZZn2fQ_E>-fhzl=a;zN+%&!9`)>l^8#I1-T;EgzV%0U?8 z=j?;k6GYD>r1f#)4^(j-B8BS1{?OPpUNuEduhbeCCaA_R*nn8`6&x{^mlUI?UAM&| zj^?(KFbwH>s7C()IXF@Ra&e_4xF>$t**#79O0?s8dhaIOHrtoDS&RuHp#i%OSEl5g0 z66Tl-FgBqe;SixSjas+kd+HmhxwF)kFVcmfr=ZK(PL78GhL3E5s-8*W`KfBvPTN6Q zW%+isnPVYXo9&(VZO_VDeqAvuP%Aj<17P$6-!&3$ZLrRBh26XrHmOi;7!)sDg0C`U z0FXd$zx4tE>%WYp(!9OU{*&bHonfcu3gGyB(oG{q(n;q)k`FRi{mEKFOq;d$n1V^M zF}CsDCgJiCIub}s^aBz{0(R5+ZMv;W)bIC46s0eyl3@V<07V-B*eb9+dFQ<0MVT_k zPO=jP#&Ho91r(RxvV2NQ*2(3AcJioHgWLk+QFFo;*&W(ey@{21^bc(nStRCpfn_+1 z0=kCWYQ()2bh`?z^&Ru!1(fdjsEFaACU^;Gu6F zr9mU74-&pZ){*w9f88aUL59~lw2uOMwwd&;Zhscey058!S{b7b!Rl1dVKP%>oDqrL zAD$))TT^qW5z54pFK~ogw+u7ulG@Z2h-_dw$keZCslT!Ohxu+&my{vPwfBZbI)28+ zIQ_D&y;D@(>-(zM7C+ToyU?zkRGddH^!kn*Dw;ZIWQ|(7L=m@>3$s6)EByz1Tw9Qa zP{BY`&S0gIqDk1Dxb#5V)mam~m+5`vTQ~N!BLVzp2pv5GtkKi!PFw!~V&6=;Q_>8N zeCL_tk2L35RlLbXM9cn%hO~z6K29@zz=FiHl1pn0WbY??Z`{ljpV=@=Oib+?Tmxa% zw}`|J6m);#J+NaQ@y`;^_rKAep1z8$d_&1%W>{lF%Av$zlq$0O%&JG)CgiBG()PbH zC9yyXWU7iNQgot*Me_Bgk%3=%m=_Ih<&CVvwav)44pJ-88$Br5`d`U8lc+wSsCs22 zNr={F3YDiWfUCyKwprAbuqyC}0F@z#Do6xeUzJ%Z`spkTH5^Ys7^wOQ^`RA!D0jt= z6V(`>-&QB;gQcFZa)+xNZ#ZE!Q&rOSN!Jj;vn~yXMzHyG$dtyOqLmoKPgg}6gxDAY zi@8C)fmZP{#_qe_I<)t3C{Zv7=$64TQ?MJhrml1oStOj7`3lf}q8TR?0;2v^z$Np4|l zMjQcI>c$7Nri)$6uAhSAN>@am*1E%g3J$vEtbV5o$=Gd9RIh4iDjuR-I<9JJg^&Z~ zf~@gW?PAJQSfK0@O z1mieQwuXGS)L&cvn!4#1r>rYIQ_V-!RgLlLRKsfN>g(vEUnaeGR#L|C-jKS*G;Y?h z04pivv6W{CQ;Bth2#`q{PaUIfG0|RQF}SmMHb~M`3biL5f<){wg#kXWIwy>DGpv$j z#YrW=>nQ2#vh8HI2{szGNJ{`VnW@S0EQOt_Fv9qe}4Egn3dE z)Av@S=nq~phpAdBSHbIy1CHyg{x@fG_WH7G-YZXg5~y zRFtVIAJRlg5z>?5PajGxNm5R<96*mT(Hvm-hgj>OyYW8sZ-n}6>JA&!o`uz%d!$`O zr(DOAv7}(}OGR4VV1j8*rdUh)WnbP~4Zsn|E4=SUtT8+`bm7hviSQh3IGEcC17cOT z%z_N0^bu9RmmXmxk5ewde5l!pB+5YwR@!SJ@frdx%L+owjlN!gzJ`pw5=Bc<@{+Ff zMiNusaYaIQ5D$3|**?|1&u%i}W`wN>nD%qVgIJ)RuM&cS6R~OCXN;p13K)ZZ2`*aq z0{RXFt_3v8H7pK{XhsVc^Qy{_TA4hsRhG+UX$W1*p;DvSp*r7$jSVh(QM1_fZK$;v zd@EkqwD1`xquyg+=k&J#EV3{fhGK5Lm<@O@YXdY$w#3OBIhq!--%qhD)n6?eQOQt{ z(#eUKnxW#3Rfq(JUo5u9kX-EdOCPd4ZY@A6Jo}H!jU2Ylyd$shG$QA07cOP2Qw7O% z(ycd_gsixgSeVp7Ra-kf(jZrKOBU}ZL2c2sj->GV-~_-NQVBgI{09$8R{8^ECuR~( z*(aE*FZ>(&TUFHGThyIR#;QJLawZ8`j!LSE(XCxy`|Y5N?Ezz!B`)ly>^-*Q7AWr= zDnG-Isla^AFv@i(sPG>1hoJx(+j9zx%Qcy7ZcV%&$Iig7|PtyX^>{-mCzde4g>;mRuT zzMo)}xGg|g2vLYukLFcyKeAOvj14?2H5@Z#gK(7+2^ynp0|0FEpLGXrmURKZ501}p zqCe6~dTyfh-yOoSdfzgm2acS_xpw*b6L1aLcm0V1{`&m`k{zPW+hq$fq`;k;u)xO- zgVrcZWCN)@^Ve0!)o4Gg6^5Rn-a|)H;dXZmGP6q%xVXCl>~3xezP!e4{h+h2h%x6P zW8E|n&07}<1no&9(1J+ziS;yPdNtHa{-R`vDe*m%V|W1hSpa))O}nXNz5VUVHoogv zi)wV>aW`i90I156G@h_FA7C z0+dLcCMRGW5&+>rB_VD2h#njXk7UPBO;UHEs?6i*Kh_p`{64cTH3MNd!%3L3k$QXi z#Kt_xgzDDaEi#j|4|+(OOYiM;R8}qAQ^yF7=a|t-K6ZJM5Rj@tZ^U{&kdDe{ddXvbE};`#4f{7xpbgWyMg4!3^cSq5PZ;1+x4xB%jQ^m!H5(R#Ac?$MjeHii7QKY164CTV7meT z052Gle|FZ?@GZP-r!4L*0Q*`K#A+#$eDx^F;SoVQXG{8*(rUte0c7k8K6-(60i!Jw_1CAj3DfbEV z?b80W=iCb@^@b|Cx|&MKu!CDiQm|A>G_h}>nx-WM{qPK1*bV1t9OQ>)d21VizVGht za*$eDmeLZUw4p8q4(Vx9R3tbfN_Ho`1njKS-S!c_Tc+a(NL|iY_jrx6t7mXm`bADB z3@9qeT>|MwWA(27ny@-5h%!w*O;#5wG}0QGsX~)h%_zHWc1K;-vfskoAKchjX1n5x zW>YMFZ~%=;DgBCkLs2^P>q$R!g#Q2+8V>IDvaOMJ0x?CSh|?r^oFONV97f-b3SPAR zKV`m@=4vdBlh#-=<~M^w9vHQD!UouNr4kyu*syrr3JYzJ*Q*G=8se2&t=gm*|JvfQjG z&{hgUf{v9$nFPcRp;&pGSzbGK^QvqOPORcnKXKdQp1OU@Ux#OMH{ACip+ss0PZTH)5hUsd8A(YU zb4hKipYGOGpqPXp>5ya{T8f}Z!wKl2U)BErrgrK70O7@+dVkQ^>mb0~!Hfz@$qfE< zP!xKKYG*&B5v)iVLAhPF@!=l$=1k{#YxcIPPk4)Sr3p%t4K`9@6%aI}q(>dJ6n7|j zuvFqe+r$w*gyYdwL+F#QqorL3ldTzJ9j${jUAjtN@QC%Z6(kY))6vXgMP&9vJV zueBe`1nF=ML^7iRE+lxAmXtx(C1^iL z(n65LLf43{w9W7Na)|F8?m#PJP1?)O=H%^KX;E?%bc7vx)}mmb69pmyv5vT|e)h@Q zR$G^6FWkEF64@zjrIX-ZlmG}YASqID18<#d!T3mYi!kL}>zFgHHG$)l2AXWgh$By% zrJAUeK3q)Owy({_2w2#H8l^ya07cu$7jp9VlXACTK}bq;q=BSt5|9)38JrJDkpNE* zGp*}R`De`CFjVSoEv{ZAmqn|MsV)Bi0_1m!8nACrD@i(sb`%H+(2SE&n7LVa%?#ygDos?fe1ZTXrl|tY8!hQ&v)gkiF^*Gi<;HFh_&T+zYSc87ryml4 z1S${P96;L@9HFnyZuP4JLc_1yC1AK21#4cV%kilsnG0Ser5VLgC{+AKCS1+yiwcVr zhLW-xY)=qj7A2jhrgS)M5J=-_qP&Jp>>iF*JL(89k{0|AZ~LiZGkGgf#V7#A%rG57 zeQ~UYuwms4-v0m+3$LIBIA2^_v>Vc=)JllM_DYharV??Q8~*?kvq44arz3RU39!kR z`92s5)aI&$hDWZeNMxRvMx?QfD;kJ&jyRim4Y7DH?ISd8hV3oVf7Z)@qsEv32?zMG z*iHl(8!#!{Or>vJShCKTx64xEv|K9bI__QoskEp=N(CprZ6F~4jWecbZdfv=K=dn7 zMTgIU(~M^osNN21trQDOM+A~3EllKj{!8q&Jmd)pXo)Ha91jcTvhCDBO43zupbnK{ zbtsdleZauQ0w9#)DZH~L{%3k^fM~mOn=G$Q!qxj5R4GBXZHI(~6w3?6MM^0 zY33*C=cW9?oA8M+bZBrhUldqoJ6g3;SJkwlN~c<-8>?W^CJLbx1=?7#=DR=5+RN=P zpH`pQreju@PLvQy1i&9?N{12#*{L^s?yoW&!ssPKQ#LL4O_$Wgz_@)%NLm|2rN>zi z988EBV9Ke((U)DitJMDhQW%y8o3j>7pAN&Zd1(+~c&%NQltwBlJetofV_F|~#boMIPA*`gB5Ho$%&Rcn&*khb=CrwT zls=_ArWzrrUkW`jlS%63(Zh(Wd(`I?~ht^yJ)s7cn02rnT!hZW|#!29{Tfh1_}bRO~+*+LW)nVdB0l_EaOR3Okg z!FjtIv2&cT=`IvpJkTx|Qjn+Al(tl%D|Lj%gpUt*1P!!iy=Qvb>z7XYfq-S6o967R zhQnJ?g23`sOC@Ad2_oN7QBNdsZ)!$j5^z26EJ5$VhiIGSbC=yEyEP^QNnWIcxFnMy zB!WOA0|b?(Bx6%94LaLHw#$~HTPJI2d}lH-pTic$Llq7dLvl##a@0X=2r z+#Vl8xI{Bn<@)BRrN(M1V5`I{7AlIA0xEiKkufmWAwTG0h=?)-Z*=OTdou=G$gLT- zQb=)WBqIpYH5o`Gh&U0kCtw>Z4mTe!UUhq7(~D_tHZvQCQXO%}6ygtd(pJ*UA><`Q z+n={WPLZV2XVR+ly8`rAnrUb%vaLS)ToMTnE3F z*~Gi8n6k$2-l5%&>}8bp{@(G^Yg-SoAc-rBfr`^Q|$*=@xwVZxO- z*>S|69WJ(o+ggR?m|jI$TDv z7w74*8uoRkqEDAnDcn=ZM^!o74!h&10o{xwjtn>ZJ!<6f!x){NC^A5*Wbzii+750amFynS@Td4~PO4Tip zBLDyZ6B0zp#ADM@XJi>mZ{IK&EG0~3h)aUpEG)X~{{Xa0n(=Pou$@l=B|w+}X`zBl z&(S(>Lv`?B_4z86FXxLSf(!z=C=!kueetyTN=Rx&1b{B+PrQagT=(a#^SgC!vXGS| zxK{-L0I;I6s60xe9Z{zqx=3STo%o~yy!b2m4`nr+bSq?#o%4KmNbkYIHM$* z48II~Z>E`Z(_Ue(hPNy>B>8I)2AVtyTt0WGmZojdM^Msks-7L;R;&+w3Lpbx9x3ea zHe$h>wY;!}1f3yd6{rN5@r|I85)d&2#|mHC-LSIEA5-1IS;~t@L+vSU7oBlZ+fITK zA3{n52D31;*^7)fUuNZ2L(Nt24 zd9ndjaJRHcxi>7cnA^E_zU>+oLY6^BtaPRi+dsmi5yuf(KiYoln|z-vQkI7rZsyT$ zxVvKONol)$Tyc~T10`_Ulc_!;mkFfDS9*`rJWJOrVv=Ln6*4^*KP06xqB{dqhy{uR ziPT62*F_Rj)FsU?`5+DNz|MP`HF29catSSdWj-)LNeTWijig31>X1OhyD8jj+ugvs zTPOwFgkL&_P}0(MJ8()`ZK2{NXd2m3`$Q&&f5h{uT_(k|=30{u%y>mb1XY<%2bD6U zHMggNLp@aM49*f4gn{N$9ipiiqg_xA47)_$3w-wZr!3qKr8esEAc2V|1G8ox7!fd{ zB8@v3-LrjreR|S|bP;22g(leBC4JILonLlAI-6P2w1WybLt>PQrs~A03--^Io``W$0M`Lt(*=#6pd}* zg{Md|2p|NUU>tP_DFlH~{{UvYnRGMzOJyXX+h;Q;Za>Ks(vjYhEz;w}X>|{!TAEPB zA_R>hGx|8|UrI2qM|p<|n>JHTR4_~m2-0j8l9pvr?^JnfPQo>KM*B-44OL+ycN}MT zH^S2<$?t9M9MbZ&gfwL8k)#9=Jb0XB$o?o4v$XBbyK6bTwbLrRYcFcvEmY}Nhezf# zKOP0JnJXqj#*^YAgWtoG)Gtf$9;V~7<{aph>iEWItb!@BwG9M2Cyh)pMFd31t5B=@ zNDsMBC>~h}A>uyHH>%fnuZpiqnM#@a(*-()B`PTjfK5xkEfpdRCE_%Ik>F4V!jerFZk76h>8#$b>*2+7ZA27}hhY>fA*v(ZOfe5unSU`; zXByWk_W6e+{0fC<=mf^Go00PK3W)Zr8X5qP^L-diQ1NDn$HwWh#hL9yvRb3)@QiC zdbh6Ecv`TxvRd6NrdyPSNNm4{Skd&oC-B?fDR8%OzW$#rT9h=e~BP|wu#Of;B9mDFSm{8#&v3^dP6!T0X zHKh5-3aa@(2O>)=^>&HDN=%gPY&#*IFhN6(?t2M;AX4d z)v|=#mfX#)uL8pf41QgflAidu5>^%#oguP8R0V_(RA>zRG`&^yvnh198o=|8a>e4s z9}UdVM-5dy0w(JE<19i5B8uq*6}N`R68 zj20(pBpsxQGAiwtaPv!Bq}*B}z|gyY`#Ze0$m|WOA5)gESURM#ge~sw-LRJo zEEJazWHyZ|3KEhOYlo=6Q{5-3^@~fJY4dJl{#6{Al35-)x*B>gaYRLjcG#M4)2iCK zD+4O*5Lk=xE_a)Z&oXlQ+-qpKg&-?fUXTW`M*%Y%NgfqO1VgcJ9 z3JRs3qB_uHX9$4qrjdQ87ed}j?uA5beCA2nDqO_=Zi6lV8n8HNqGGa_q z{gUow_F;cCxelt|299EcD15mRKdGwv@Bh%(q^oN+bdyV7R)ELmqxNa2G)!3R(9_S^Mv?`ub?V!TV-GiO2 zplZ)}5s}(nTB(;ymtWkJf_t)bkaglTfiiGVRv;55r5@D#7tXhzHva%4L&|32+R=ix z*4u2Oxp=tnd9r)Owh(2gI*Roq!f~dr!<*K3Npgo@aqP{XajerzPl;o7n8YcgW+>f$`v zS6_`(;PFt@Pzl#E$|%-ZtG;PfDI<>Vgxh^HXw#pV+%3QexHlJS%oNemtB(7-kJ{)8 zl*-7%3^w$QSkP9_v8>TupZ@?MP*QHqveBR_32{$%z!yo4KhrSwO96{8z0%u08S_D8Ck;hK}KI~_*>+Gq!>zu{AmJQv*P9ZP29eg&^323QH3m`aD z4|fFUNK7d(MJ|0_df(^{eDt}1emisCq@^1AvBuw#=_Fj~S)PNV`vAy;&;I;YGF zD`{)0&iAwXL2GAbE!KrwPk7^iDFlS+0U#*qGsY7bbYTqkRoFIlkmpUke$&Wi)vLxs zintD;&&)U$(Pf}~Eu|72)CQ%%g(Wjj9T4^1>BkB5g^A?s$0cl7p=>D@mRxqea!r6Sk*I)1m?1_0gCcfO-u(6r zo9A1~ZmrpM%V*xOc)R(6lr{N61De>?3sTY{nF`UiQKV2U_<#E4=pROLT+36RsA}jV ztbD~+vGXN$OVmSNRK&B?yDEN+{*1DF^(60_mKShaP2)~9n}u6SE>e(#sU#AV5ia<=Vk9Vtpf9DK zvU(|k`n)|un+lo?J>tRW>FXOB#8`=GDty_bj**#TgU?b_qh2~uc_8)}Z1)Y37L3-!W%mXCl%pLI>`g{h94@Z*|sYXi8 z(YUBl6D&_EsAc(QK1kf;HuX*qH=BCby=L7BXtEdwSyU=;0}V0Z5juz`#Tt0j7uly` zIi^E+9?V$ody5pQrSZW|z{y>Uq@E048WNx%v~dJXlx z(H?{Jqci24Z!XirQB#K1!r?0?c9vSYlO-ihOp?1LM3F{9q9UqnRV++|@XL1hoz2x- z(%*gGBqcHukO~AHSSm!4b^Xf9kg1M^4keooYvdrpfr>) zp8!Po%qYZAMd@qR_e8o|>V~JORXHOErGpZ!p_(bFC94%XDCt;ML*`E-c_~(HH0o8D z$}JVp8xv$Xo7=kkS7djZB&ibsYQj={Q;Fga0pS=>hkLs*zP`&W+PAesuGzV4;cU2D zNes8$xY|^dAHnX$IiR5Vc05`CL1`3o*c&5&r-YKV1DG^&5m?*hUSLFc*@B3@$k*u8L}z z1e8v*Oz_JCqOqw}F-|26j|kch>mClblXz}-mf^QMvcPQxGL} zqNzxaxaxz9U?`_|`zg&b{oro#%PTan#nsi;wCYlq`G8{IN!W%;gb5)p?9gb%C<=cv~x3*F)t(&)7uLUXA`?aY?;~7YKK~R{} zr6@_;GL!Um>(8fs59_WepK}IG%J9-+Sj5<&ro*tGl@X%Q{IAMQA$KWCyLYSr6lu## zy2pXsp6UJByJqdOr~9_l*-F#^I*;C%7^qGXU_y9`m3RLDa5D_;t3_GaT0FaFgQ`QK z5}+9jh7o}s#QxPlf_02$NTiNy^}m&IUsTZbs}9Q&5JXeVn?gxZ-Ph8#HIe4H_r92+)^-D>Nd$@^(bsS6(L{L84vaHbV)0sM% zw+}dn(}E9jg8RMcAt2!6csFjKN>bknSNiY#MzAkXT}Q(6z6X}_)*BuhSB6wCor2TW z6&Q1w5(s?z`Dr|d^wAr~INGw{X;DKUV38W8DZ``RincM+Z%cU3 zMa2ybY?Ux!_-j|mLroJH=xNtt#ZL@kGNm?#W>zwrw5$safwq39|vQ0rI0B>My)U5M)=k zTdv`D*Z7g3hYFMqor=JugNICY0a7OP_Gg>s_e@{q>tUyvQ|gym?-1v8`q0Dzd-2*jEwzU-GXRz%)X!-(%0ZI;rv8%lzb z!`<=_M#PflDsdxGY-pTfrFx$HQo6O*9<5V#Ix6|? zc_M!xl(;1d-0d%CS9;si>_4O{Ult8ThT!J{b)~0` z2g*(&`G_X-70aZdRGT*Y07C<(4Ij9@&k)jY3JYxi0CGwaQ?LYrOyXf9sz%5(U%Fk3 zU+(LzxpQ`2OIGW&X`tE=k!-RGlBFa{mZ%z+BN2cCobZ3e=dIaqp-<7QI~SH&rmd&1 zn-Hj2jw2-0sT5RI9%)+v5s3%^Y>KD?u>_TNX5!Atd2?$CWyKXMN=YM81xX4fN7|Ui zaKM2|?mH07FK?H2Z%SHS%Qt0|G}s;U0V!@*8nhuOMwDz)fhyZgewaTMPOti8%NX_- zhGTDuis4%Xb#>~ph`*avEk$sph^Scn$!^Z%U7TDMPzM#|H!tK)DRzfRT0%&IU?xaX zW6sA7;jBpL!TU$5S+ zWRACVMNi-RAhoU@V03%#7Gw2babP4l8?DzB>lY)0#^2}TDq6o@VMI4 zw69E^N{vz!NEcEncl!Q8>s zy!wjWa3m?hk*EY801*Ib*b+8v>ZMs{W9KWeddKq*IBrX;dF4lVTzNVjT3|v;hyl0* zN>Bh01X8=y&*ELye^FE`mh%o`tAh)pp{2ssItd<`B&2}G%S|k3!Cn(8D}<8cMQd&w zxN&-moZ(1S()IUg(u9ySfdj<=Vyp%`W`eu7*qPneJNIs0xmjg4(CG!SZh{MK1SKIl zQvj2RQiPeBbH@Jw6mL*feICMkLx*FvG<1}bPhQF^WfF5t2&Bw*5ZW)z>$jIqC%-pHYg{203J|A=j}oH< z&)S&+CWCH_`uXcuLvj{9({7#PRdjSX;u?J?ca`Cgy+o*4%Lv4zu}H<2R${x`itYaZ zF_wk?Rb{a1KyV}hAty+JAmAk=ji8aTk9Ui(+g<9o55DW@9p7@}Z8%$L)~8o=w5By6 zs#LK)GI7G7bPLx%QhF`aiF&z#VwDFQnK#Qj)lTL;k(krv#LUJsv)yB3YyOO)5;#|F zYW_~@Ub7*!rb1PvB%NP&tRT-`G51NO`Tqc8D9^3hw@c4k_X-MW##N=%s3f2gy`-fi zr3YwE6qe3js``hWdZ|y;?8k}CSBt?Rlub0US|*d;W@y>AJ20@^R9%IfFaw2eST67_ z$COsJol07vN?L)y>WL6U#GE5cV?qq0vAaB{E>={HYGq+z&1x!Bo#*#LRB;8vC2)LP zc+#J&zOOo$*Bru_zf-Fv#G;5qu}3{iv2}>-Tbq|eP@t8u2G+0|h90$k`CaY9%XPq= zI@Wa*rYA_8J(1J53KDLYV!3|kYE`DPw%taO0*vyl_Z3jQbwvUeH;8Q zdZCu9>MJr6TT3A*(%2ploCcLl zBmo#15mjmHN259OEM}^|<~W@;Elr2kOcK6X3sX6Z^mnIAYC#_9xh<{NZh}tTTp{+?uLKWi@K}vs!@h2Io$?C^j zv;IGZu35$LMy#QLr<9wSuKTxnavu=KO`s9rI}2q-SCzJyPy`SZ04D&Gi76a0#&+>F zh%a_cljRo+ytB4xw;cPHgn+Z=t+U2wZ5dy~JFQ-!@~>R5ECZmoY+}AfrPx{Gjn-me z`E-$0j5fX6R91G;bSHNtY_%`g<_)UNQ0t^NktxSiNl_rcKAJ`#@UC!n)w=9tMXcSG zEt{_KEi|SfFF2=9c2gr2sbNJ4#X4k=pkgjV`4{4$l5(agLq~{0lJu7{`GRfFv17z{ zDK3SXU5S%+z}ev58TcP}D?MGgdCLR@^B~ z<85V&l|s}0NpSLtbtG#tr&MDNU~4B(N~F?XukTJhedt%K&*r|OYN`!>X0L{MY9OeT zs?ya)K4Gc`=GhvOM%8AK(Mfv~!5&*}bCbSNm}zmvOR748gOW%9DOh4bPl!TeqAR7n zhvwrayhc-Sh1$Hz!rw0ut{(Ag)P*TZDoVAvDma}Z90K3)-RX8IPo1-$tK6YiSJVsx z2xrUKO(ct5PGWY}s(dboDV%8kwOFS%sO6EO-}98`5^Mw6ss zQ#@c-dMq2ZK`UbM*FvNM5Vq5VPu{ul907_qJyFlSG{b#9=f6`~ejGa;ni7~!0P)~) zBs1d`jqGvZB)~lcWT&f(niR2~5oJiXAUCxUZTKV?atzIPJTk>*L|qp@wSI?bK69Ro#jmbR-3m0(FcWT+E| zS*X~~1JaDWl_$kImqCR!5pgMc_#>$^R4%IunGvcdlmZGOU5{lNTs@k08@j3g04Pwp zw;+gHcee?SfP|?_$AC&fS4A0&{qgtrY8wu=kY}%8lkcjt>dih_>SiNfh-OTg1{;Fm zY(*puU5G)5)wFAQl5~!Cf|@Cqd!Sxb0_3MKS9o%F4dU9h%rBg6CrUp$Q2LOefm9TN zAj|@GV5u}@F4?+DmhG!rN_Hn(Yf#!j(x^NW3bQDm}6lmK-g2T-Y(d%Pj zw~=eN8UFy~!!9b#1mUf=oz?*8UZ8N`R0$IUg&bJ#<(--CG~KJaFni@Stt4TgNRAO0 z;x^6|WPgQ!K>9!GLnUM0uGW_k>25C$BUOjdVt9UOTAWUz{{W@Lr>v5p6e`OpP^yZr zB8C?$sgyT2v-|SWuAa8wyC&2_}3~;*yefkq|H-mw1~( zl2G2B^+7sNg$z&*mBV->1cee)B;a*M6;Jfuj560ka!p=g>fD&FG1S^THSsDeok2@c z9Ql42kTc?V{FBqg3{VwhDus+@_Pe!*IrW+54=5=N9UvGhAyWXsQoJVx2-6Z|iHfFE zlUmr3aQ3&B+I6&mP*JEP!AVMhASoxj?;!(BB`z5ukMNitsb=f`I|rq_EBUT<%~(}c z6!?`I{Mo^%D&~w<;@(;i5XN?GW4MmWj@DjM-8VN6CA&#T2`N!2KWTw8)zgmLF(R?| zBh1lmm!G-~sZT5}N|U53QC7`_6A+mIzy?HvVt%bXIOV>9belS4GmB#QuTijEVxJnu z^F?k6i_uqOv(+?kVd;m6N1qJFS(-!z!K#uqMs+80 zR8=JH#F>g2X8|weo%k}P1SpijR-~AXP3<6QN>JPc#*>7>?C8H!@*hwt@Vsv*QD(er z1j6lK za3*zlOa#Dyc!MQFfjH9B)`zLMx_{}PF=q%eW@DgbriCdhG0HkjKA-u5O202*B~h8m zvi+2f=GXR~1aphd?W5pW)c`1@2vo>1GGZrZx~-M!wRE})72Sm^NKwQPa3(eqM_Je^ zlsyw={a@g}922p4 z0LZMCg%{8SO0iZRB0NfgwL}Br=`^Out-?#Xbu1MCNh7;VDN+T<7~l;S-lX-n zFm;a;!g{^bsbb4C@KMKx;TUEdg;{7rF^!PUWT={Y$ym)ZwcXjg$s2JTE6yKX+KB*Q zHVgocndrt;cH>c+?+wUJ%fz5!5(nH;P6kYwUIZi$2!VwMIZpD()O!DSo!MaBtj-vyVqf3ibLuoLY*N#Pz zBaR@!MVdJnki<2(KkV|+jOOu$U!_HEHhYrbkQzZzONaz%Dq506l9eP0Op0fFY+PZt z8?tmX$`(8B>NP3F=?ZN|K|)fM2p}jZr~?Klq-qdBQcR^-;*t&oih<4pVLW4 zh+r7SJ{dzEB}&+i6(fA53Q=O7X{Ko!o{ePD70#xXTMl87W8wN}V92IJAlJPMi{8>_~cC>V|#lZ%>C# z){_mZ#4x2Zz$f-r%0+Y zP66_R+l0Ft@j5Hs?Y7yUTfM4iOr)B?$;g6M}&R@utsR{(y5D=J@?)b$>ZY z)x3U&T3jN&YOEfU4#Vi)SsGdaL59-%kwX+6{MM2{(kUeO;@#(c=3AE40ZWCHh$O}U zo{b=2H1NZ11$!>t?6&Ut3d|5*xM{U2+&V&=LPCLBlHQOzz_LnIqPc>p1PUYAoij&L z_>$Z-r}u7I%L^$4n*>qc$K4~pG5C&(>CjnL(>{Fdq)sXgEpccS>5Q9!5?tEpxT=%l z-yXx@c+0KMG~yNONIb(%`vq(Tp=k(+f`OQLvkPh${3k#O;zqzpgO44t&s}V+jh?iP z#;QeC1fFqe111CsK>^mlw zzlxr9!~IYCoPM(6^^sy@Gi0nTwhU7Srj{sXtc)1(6>}n@)W6OLk91?oQDs8b;InkD z9I&@3!%(?B;#UCpk_t%xcp*5PB*fq==Vt3KNOe}}B}qb5gsC{lLW*P^iq(V>hCFJU zdcB+|Wum0%ZdUyk5rl~TVMFd&s)GB%_8#OnAZcyaHq)6uyZL&OrCz;@j!v8)r3a6i zw)E+NL9OJ!MwD2wgKYt*Ooche(K|XdN#Q`|0SZTrK^;0q%_HnP`)y(G5>J3#f47ny z%B2QLz)l}3k8&cJ5y zsaA@Cr&$D+$>~r!W2j-`5HWe*&M+Mxdp;Ki!wEQ;>Nt)uJrtnyx0?F9kUFxxOUXED z;+R%hRm^xrWjyG$)fCl(%f@ipay-rZqYW<5q(H-SUvL~eXEJLmExD+r(7x%^Vh4u= zDB*?&PNOn0j15eiuG9I5P$>#+Db|%>Oen(8G4X8G17X96qXE}Gu2TBn!}_7=@A=~9 zoIf$pQRBHLx>l4j)Zxd^I9dr!)-;dJS1h6AkbRpFM1cNoa_2uVqO24o8I-4H0QD1( zRE@PQ=2=@=kV0DtEfhf<6+BFBg#crQ!?KBg;n&liv0)f457iEuW|zY2@myxJ3eA{4 zB%$!i>R&x$c*J^qtxCd4Mi%$1ZK33udg3m%G?ap!144mq;Z zDx5>4J>EK}T3?B!sS3cMICoBI`$}OZd`a0Gboy`TR#EA}Y=MGRRMOJJB}G&evdI&} zQv}v9Na{%&V*dbgG8;69cGe5bP;W0?rTFhKE+k1hagBt3M~LxYP9R}eXS`7J30R*B zy71sZ9V4q{V)a#t;`O+7RQP1Hb@(n@hK@{LMW_-)XO2dAQXR~)RJ16-Nz?qG6@_3;~NR6d2JAh_4J@4I&?!h`lF;Ue@`*8F$Xn7~tD6D8g$kITO#VW-l`eC*` zYE@7LB#}51G1r~1XKmy{{w}>BKH~Dm7;`h~i!_iP` zacu2WTDdT|5GLnE@?#_hJIfo3=m608dj~EWZ8&N^(^@MgqHWFp0L=dYoBW)9cJD85 zmYuflwYGbFZT0f{QKlykKi0J-zyHzKlQduuRAa9lYoCA2`BS`IqK$zGU~H~~WNdea zxjRV)G9b`lSbFpC=5%$U$HQ97|BxW0k+6lIX#1^pJ z0EGeu6ke|u+5~e(6IYURELhF~T{SH9(;Av8s#j#FrKp93u~gE!`~KvrcCw3$Y6!i} zlF+$9N`N5XQbdIUF$8QfI8bKcDM`|(Ajlwz2dX%V7_lLR^`kFTX8aEgiVV|53)g0x z3W+>~tc@)+*^32=J8X*JNr=(J0j72Nx^Q7Paw_9io4MT|eHdh`{18xXz4q@2Q`Oo=#t2Rw6u5z z8Cr#6>Rwi-V>Mn0Q&YHG9Hos-MJ+%D%|h=$BWa1q8yxKlX$_Ra=u(JW{pceU5yA-B z{&obYfKT!lGMm-r7VbkzN=I@M27;1&L0nUb1aufbYG~sA9-ggfGVTkPdR>^YSuq}+ zXK*R9HZxv8Y&N;&^5?*DHYCSOEE3%eB#$afI$j9@3iB&u-zW18{l^s!c#n9Yo$a$X zK;0$>g+)W8#sqrd*XKgzEO<9tJ!a=_sfRK6Vo_#fGZj| zg|%;AyU6?YJ6rEJYu$sKWxq2Fhs+yKi9y~`7 zQolVcyGf2gD|@M8F5q8Kc?jn>0m2(90ZTKEGA2|buiag9wn8%W0@^$cBqbnWqyeQq zP#^(GFH89&rap%2X?BvS6Rc({{ZCcaW)t7VU36?b!Ima>vAAW z>goOL{{SGcB@AqR{6+(68|f!u_u)ayJ2Yhn^H*5BxhZTJ+IF6fuXPuU$<#ig^&dWB zonz_+U^xCUS6Nk6Dv%MRl>3o+YznL~t&}2*ZMW0Omd4Gy22jHy5QK!Jbq*x)B;rp^ z5%;TgMa3TxndhK%R0(LRF>0E0r-n%V=Z%18+@S}VATjD%$_cnP1GbzHw^of*y~8MJ zu^1y-inC9K(m>J);UZL7gAJSB*ZnCsV7Fj37Z>1(ks^%{By|ssSr4HWrs>*sr|}5K zso{o)rde_6DbY`v4Q?@33PkI?4|~ceNKF-(>#rqE-*8x$Z&olu2plC*JAH}urA1xC zZavgQbjOIFfb*I$KZZBrPlLo2MJD;+pT)31p7`R`Q$0=nDYbi$J7CL~8 zRyi%XTVeYxafn;Na`onwI*{N*s~8~aIE4gi_4d9Tb|GDeMsMi*5PBCi9lKz~OyGm=8J_kq1eg!3CS%$YXiIN1G~ z<|k@Z#R}^iLEJ;vS(oWna;JD=~jJud9 zrSjwzs70wN{AH(edZD7mj86fraCAQ&qQ{6>Zivon6AS#ZW+&Dbuh!TE$2q z+oTIe0v!?{@yDVRHl;v}dMUOYHv&h6Tu0&32-(wFF&>TMnAcr0?jxHGUNc35S1oQC zOY_Yt;q_C($tE@>vww7Lng|G9gQ3KQ1rn7RkU_yfVgcxlhJ&{^2+dYxkvM}91a)+9 z!`7(N`n7}l>-6=AbQe6*{{UCB=2fezN;Q_-Fr33rr1*B%{U^v`2mwyxV+K|xJM*DC zy>TcA2T~v@3h7F*kHB!HRv)%OXEm;nrWRU= z>Q+!DM-6S#L==JT2IJkgCuZCP4V+E`6DQvrDSJeNj@~^pSBv;&U~>A9^n2GIO5JoY zw?}eCB$=lJ$7Kp-%UI0P{{W@XQzHT%inN{K7jKs#lGhD!j#s?XT96Js9nrWE?ga(m`1S$8f z$3dsrBe(}oZz{c%V3lbTO;~1Jtc|6u+#~X~7?GOl`hqQDK=-aKp<(Rt3p|N5p`;Y! zPcz~Ii!;xO2ozLF?t77vrpg7){lT;n03&tv9r##N3-qnHxKT7Lbn7WeSzl6UCTlUL zk}7E2G_u0#<*FhrWZN0BW8E$-!3!AEtfL$`9W-RAF>apaihMdQo53Aqu;ECUja^tS z^5TrH^2ttK#w3ARQag(?AtYSf3s9hf2Vw46_^w?Yh8Me3tD^yC>?hf1V{>>fIRn}+NDAAidb-Z z32|z>`Bds${{V>l5Dyc3aLlfsRx}>sa_Gq_9n481L1KOKN$sKU$^$fv<3Ua>Bh7Na z6Qfvn@8S=E@%oPpTQN?j3J-BmL$uZnWg_0)H3Q&2ucwL>x_nUa(`adMe5XTQi^#CU zFp|2eMgRqg31(yPNY?)VM+A21B_Iq*_?{J_B*5~m2KuYiHS6D~obA=Gnn|F~7~U_5 zMs+*COzA}ofZQv2QJ`De#EootB*?Cf%V8^kt{`ll10H}PdT1~ZU2v29L)bz{yM03;N|akk%l0S26%blB7|9S zECLmWpTdi-X3Myad(Fs+M+3D)dJd0CDSwmM&?YcS5 zo;rw_S=GB0VQ$_$MZ8U=HmXsABzY0X+A2~g)eaGHj|ah;0d3W|z2qfu8+BYm+^8Ce}hh~%x!xC6Hx^C7{&={tA<2Ol^+bl^TN zjZ&fQ$I^CnVOB$rW@$4208a7DUMwO^a!e|UrnVeDFE7uj5h0P`f#o3Jq`4Zjf~_NIfiNctqFc*u@Pas)_2E=m_@HE*1FC%!z&%>@dXQoHvm;4Gj4)JB zH{|ZKNfkkW@3k}7-EJ&o14h3l9opV&d(?Lc9v73a#tMmyIL01yNb62pt4f9`IDGxJ zVEr2E*G~HD(+m%*xhkT1Iy`oc8jXa?q8T;?o)NqotWsS8*FX=C1THegxzHA*5&iPM zcu{(ir0pNNsy8~|*r%eOU6^KI!SRDpk@}$0Q)2Hhi1{ll!*aTy0gXLVq{!uW2;`A_ z4oZKWUEQoSv8@O0FnDqE8)>8umbgX3`CzzFPk(NE&_{(Nppr&A5~OYGG-qhEDcuQ@l>j4Y_IcK}zl+~S z`b(JeepBlvD=sUIP~tTSmN96urG6bGt2-Ukb&{lyv6f_08?!I~s04yXChI-w%d@+C zUht{Zt;F|1w}MdGof4qv5>%0(%wmzS8K915kUSQkl#r!DR5ap81112DGDTK)YUr2Y z+ks;gGvfVL%p(-UWLX9kPleJ|)IgTsA*_;~Ng$^R2AassZDbwz70);J-#WWmZF2jy zyftZB+(Q=RkKzSsD^f7k2|y$bvq_lTt6a1s-e0oXPC6R~;qNUi_z}=b*8`x?`RRg- zqj^4~H)p>_b#=Mt5=uGXs+zwGk&G)+o=2D<1o z<+spO>&h-E4x$2KL~L3_Y5PHB9yKI(Tb{SNIqPoT=}o=bT(!9g5QL%7V1(=eD%0&% z7jMIcn;OjCsc}A`Vs!IY&reN=Rhbe*Q1vqC?o6a10!f4F^>HFKG881m8#!>{{Ez`Vc7QY|g5Jir@AKI@EW=N{t5O-3(X5mKEg01%5eec+ zPRvCIck3e$W+v$>Z35%OLe7|U9WF)@1j2_#sx-YntNvYu)Kgc?=M}G-S>5(HxMA)@ zrN|yyAPe8Z_Sc!T=6h)Aok~C$l)8nsq0=c+L7y*eMXuymJ5qqKIH5>b_aBH9VyGd* zGd@(rdViaO96nlic*MWt*~*l7tT#QSMj+T7FRw9cdiUoj%I;aZ{L6ZhtqvpwD5<63 zxrC5(#;7NT%96K#cCTG&Xe_D}WPP9lJ$US`Oz6EhdbIRw*6hZ5AB5B50}RG$BY`Sv z@b;m_uqor**nS~NQ&57Uf}#d7O02iK?nAv)j#+Qkb&!<3m$>OItbp#WbCb#Lsf~e=}~%KoVrUzy%yqq^ZD2j0oG&jaet*Ks`w0zQ0S>KTY{+ zO3G{&n!3KH4p>jh(9x<(GSX3b>U_nBffC9|+Mj5K)JF_nUN-3bi0>S22U?6BNH7YQ zh=nVlV5iymbUNqurtmqz4cpNC`{|8}&=- zo2gw-^&wl;jBW#hW;v?bYUp4Q2n(&rQovcHLI9M4VMorZMxdGWf)VaTaTktY6&h~L9%<7*qN&PFJTe;b`SCKF+?HNmL?I=j_ zpER5%vS!ax{YAwv*l-+c5_#dGi_3~Pv&0cVL9|-xNCRz&Ad73L;YzYbU4p43Y{d9_ zgqV(z5JyD}a!$%}e2K+BWo+9ESt?qaPL(W^B&hM8Jv6b)9;rH`hG0V{-cd&=AC%hS2B`x!vn^N|H3<4&FRS7)1JYRN0sIOO#z*i_>m^`4C+Q z0dO`ALm28CC`jp7S9+tCDe-CWOh$T7oG_%Q#fr$NgrP!O%AWDEi)=Om{j19(&P56xLPvW)Y4R-Nc)nlvZ1u?!YVdb>W5Kst~!~Q zFV1PEiDxD?W?0&HU6IUfVdp;L4Ta9zcRJn6CRUv!nUF$(@d3mGw@Bc6`ZgM7J&m`R zGOK&G5bJ6Xq^$sm1P~!Z5hGye>55>-dbOW(RxK7UjnvCMTy1xElpu1Bq%4cHT@KrY zH(uhyUKlf%Fv2t>U_@~y2s;ez#wTqA6WO~KDejqRDM+6PNC0p+M%d%gLVVt!x`CX& zaq|Uiv(tHd!}+)O#lSI(4U9#!8tv5RPYPbjn?z|4XRn8^vWjebIkP=1Sx*8b@h7EtwzT1#*T1B6HTr-bzE>7^rb+6mAaPLh~_1Zg-C1B75l z8pWAmyuIMf`;*9_m8sH4NHs^pzxDzFkRM#T!Ox3<+PyFeDy1KbotD%NvhGkYJCLp6L1|f@( z#4Fz5TKZdvp0aI8C_iZ;M^79&u*7-AO8Iu{G~m&v0x`gQA~tnbCa%qxwkEaM%+ge> zUR%6{n3i?2`HJVm_gLEI+pJF-DP^?jNC26`pmY)M90tml?K?bL#<1CdHjD?SRPftQ z`J)}qc-=vp8>pG*C|Elke711=MZ4QVFQ_8-vEnOcSZC}4C*A~phk@C`jTPCcfCD;s z;3MJ2nrgFFY^9>6!|AFdjtn|92#V&*XE)hd#hER4c3tV#~*t8gw4g}vQ4 z+l;cc1+5^$a6CYqG3n=RZ99~uLVL3_q+mE>f!k0h@vL2BnyM<9BAKaHKRFG((7=TE zyMt>M9f-Z{ryo;D5Fin%VD!e{)1wMEx7@Qb5x||8Vb0p+hvHb@^H?kV){N4~Bv}J{ z%ed<$`|fL7$8ov$Z_2pZ0t#Yv2#%hwA?_GsM-1*M)giu#F|-^`|Na#NeV#7M`kK zB>w=&xt8(nVjpV_0~YbqxfeI$7YbCa@T5=lqZ}~9h>jgwFr(%>GgJN)jC`bn=gd=- z_*P(|rm2z|x{cBZndA&T>mPN`Vy|*Sn~iQY97>CZ)JKIpaQKfdnppQ`FI%LPjf11x z)h3eeYcT4QS1>Z9H&oi&T^ZKIk1s_mb-B{u-@gshrOY-?-mpCO$3;RJuIHSz{{V9s z@s2!vy=fe{`@^d8O~3v{-LNXKW8^5{Hzw$w!a zMwPE%>M_r=rn<}->ZcZ(R+?!f+RS$}tQ~;?ZU9@CBSv5?+V}6p3|R(%fCrGnr>AES zJ(Pi2B6;#s$xd%XbwKJwlw(V@8QJ`TqWZXvxmQL z!=fUD?RIYSWJub2G4<%LQ_xQ(R4l)wRAOTaO}AWvP#(?LFSEm*Q=kLD@$&2H;%M2f z&k0cQy~i(lLK@ft4DrEuxP*@Z}L_G1D{N#Tf} zKWz(rKIxWj>UKXK1(Rqiafc^c?>LBZUGj*6Q<;>$cVsUjE#q8!9w`k4TOw9R31AhIm9r3m!fKt?4nI>t7a^0?xjzLotIraIC|UKlmvbeun>BD>O0MQ zFD!ka0TF<}$)0_*ouk2V2jYdbZ z=ani*k^Smt6SE(mvYBcy{6=;}Sv=_p-c!fTAcAg9m=WIB*IRLNT}o#N8z-yfQC0Tg zDS~vQs|h%4>Go84>2XT=DkrIuM{APd6a%!ztF?WG>uX!SpaaLlh(tgflegP5?Vy79 zLB*t!+O&`Fe1{%0gi}Rn#p$Aom?IMuO>N+)3^uS>yA=U#r*=ADi`!BajO{!z+dF-I z1pzNNTNu%^sy1*O<4tE2G_(lFWRS@!2)y0f!TVpNQTDBKW&PcFU=UQU7y~g8(SiB# zsLtbeLIeScAZ*9fR9alYRR@}CWDHdTvO8|Ewb1*ZHqfNp4|p9k;_mEpddE2XjR73V z^z9K8+}V>Anz?G4SCY>gd;1dXQ&LLW&7c5kEG*X~@j@7E2!Yq-_;vdzh0L^cZLAgf zuBxHjRC~_tG<($DT(;5-n){(ZHrr$1J=^hWSVsZZ`@H$aid@RlI8zLnlM`Y*$s;Nh zew9Eh%&c`IU7*}qK(}k?Eybaf9v+^Y{HYJ}@SG}LE^Dg8*U0l8CPv#CUAvS>q!$Be zR%3Fcl1A-Cu58k+kl~n_+vtBu@~aC0jPuXNqQQ(}FyS(M!m1e-NJv#{ww508C+x3n zbUn4d9W5b7Kh1{8f^}=ypMbX_eOD^H)5 zL6;oF(dLe-Rba*@H@Fg50k?3}gY{pxZay1E5H@?NpUaXsRxyuPC_^(@h@aeRfF3|V za64>kjWn?X>EpUmb`Fkw{#9S)sZR>@8HTckm8F(Kq16=xPC+|Lx4atc4~_gTYyr9D zJCv-%dC#-->#Kh+NW}G2n6bL`#Z6+$BWIDC;h9H^g02nh0~-NiPllG_Wi*{J7)PI0 z&rEnyftMs5gKad=j@4BdAQL;Jv53i#voYG*FdA+lYzY7jz84%&mJ*pTFf)fZV?MOU z9UH0 z9KK}6f@sWF*v=TS1dn)@UgGCcFJeCaI!2MGW6`tA4w|R({YOc{xX)EA)kzU`VZE55 z02C8z5H0To*Ws;&xpa*pW1pACnN^V4S>>y(pL5SQn(V2yt}HyZ1sGcAa|`ZLPweM} z4T3tn_WL**WBGWlW@&^T{9v+3y9iJ>SdcdWMea221;)H$1nuF>bLCq$5mVw74@}Ph zu(i=Pmh!;trHQ+JX4dV*svsPFPfw=~W|a#9cvFQHO*|DMTDLo_yMrla+%*SrBFa93 zb?~FtZ(1Pfk%jfAVJ3; zXD4X)P^pU{B06fzeJD$YQ0AIi?7<946*kS%H~~>_?w8yRj_nh^eyOrwLxoK!OwoGxp#F(Wbywt1D;PTt6?;!%ss$^DI84 z(w@l-G*s(RMDHMl1(dsafr&0iu(0I&yDD=b%=@&t-86%DXtG-!+HGxZMcXd8>a7~q zSW}_Ptz|~!q<4)eu-2$X?56(FOLG zOv4{EP<*vqw6w`v3)4jrQ%_s-Goq-4wyT0A8tA&-=G=x5%c!<(F9&g934JR`X~zEm zFPJ9!;Ui6vDJI$G?-b!Aw9qPbP9aUPO7jbpTU@vpUZjPnwxFddLfX)RNm!ByC^%wp zh!a&y_>wA5k9==>@#Mr(R zUbVQpPNI^XR_?72AgM<}l%+bSoKCh*N`jAij|$Tg zNYeyjU|k{N`OtY49lSL*8I(kiRRLT%xsRof4CjI zFraRIXmu!c`g7JPKk2_Ybq^x-DvK8Btj|x1tlMF(Sz}2Ng4}$$m4Yc&w)3GNd#AbJ z$23rBDR?NMNFhnnAf;1*Bw`Qrcms*9V|LGxT4wn>s=L*pfL;U@B!#0CtQ2^GK@yTS z9AdV6#l0r_@2}0c)(swTiVAGqmLtu~jVv&%budR88A`OSuoEaA^oB<&SdFB$r)KwC zIRrMVfi9rDWlAGjN@Xrj@d*Q13P{Ed6~ODid6GXDc=3X zwx0o0i4whJ>Cjw+gv_YHNG`n|^<|p9E&6i6x-KNgvc4lH%~#Mz23dxxI=E__%qpmA zByo#wJ-Ise zeUv?$W+lyGL86yNwBSf1NFgLaQjR1{08TMO)*W7BaEP4^3C9psI08KJ+aj#94eMQQ zc*dJ5WLz#d^F|*l$y~K_hr;QEWC>=9vK?!YO{}!1b-me)L>^~*S-Qqq-Ru8pQgEbY|&d*GY)N=Y!p?sNU^#} zGXRiKMSmuWFM8x4E*NF4MbKZeOih-vdi(Twt|e652)xNZaA@81X33fs~KG zj=?>B1BWwJ-=FgY6m^u?Yk^S|Q$1x`ZrZXeY@i_|SbW7xDwfb~xjf^(@m(pKWkQd5 z@hA%8Dw5**NePpO6HeQ$c=4g`VjQNRVu8(8+x~>^<49nDt z>2UarTjX(tQ%DU#i~w87mU6KmRk2XSaHn=M=jYl&^%d}g@2~EC$h6bEdterDB$l0?`3^A-B zx84i9rEPvwLKdPBLedD-sELz+#wV+)tD6DFe+1Y%pP9PL9&GBBHCA~n_`M&<{{X(p z)=+jM(S#r(1|<&iL1S$X09HMzt1rBI=_?wZQ7cJ8bWHyML@G&1n37^nHIj_(Zuv8G zJJ??!{90F$8XFg>zP+CJF-0OASwU*;~F;N32(&zaf?FeoYM;l*jNDu{78 zDI!4=K_zN6{JG;BC1ncMzQU|SaOC#5l_^Tp2D69_h@OGtka?PB-*UIo&DFeyZKZgW zmk?46%z@N)ZL0P49n)XC@icYQwk|3t~OQor}@9O^GNr1 zcJ4|2+b9|{+M5=wrKYr{DG>p)w~1GXlB2}*^+2KBzU}Ybt0`ftdt|ne0SR#lK?9^t zB=IImIFmFmRr=2SC~>^S4rkAK`!{Af$Z2P#Rm3v1vcghRc9Lpw5LpROsqYIEPzsT9 zYL3;~KqI^cc=vJaI)yyW?{DS03vF9lAQBIS#D#SLLZo!zjx#j3!+n4L7dR##S%&5Q zr{=sqO3HIim0#7`xh1EF5X!XgGB&jS@rbZ*C=;~UDuC_hXcm|11;vs95(97!JYiFg z$q;eF8e#3)-_lM!R zpA$@9GvXBZO-th0f}jG>MT+88a7!$-@i7ey3AI##rO7-a%(urcyi$vQu}aolEw55ND`0Ph(x5PJsHz} z2>yclv4?fnq1{){Pl-{|)lir*3>uA5P#YGEp&&qqk<-(w6X%Hb(T3|csc*tNuiw^cZl!fY zH&sKNGx4HM6_s;MI@8unT-Dc zp^0IITV!#@s*$MBDDfm4o4;?p)@*=~wR)g@l^)8t+>P}qN7zD^O-j^4gI zXeISO)o;P))s9`l@}E??ub=5K>>^spA&U>dObGK-MyS$GB!&FfMA9~}+F6P3!koi+ ztg|2j)}y4z0VCVA(d!$jzV_i-Z7rcdgZpIci2j#e9S0GOFji(?!CFsFSg)ka8>t!R z3(7d%CKpL8RM~x&bomN~tXYJHD;cU?+s|fJG6QP>0peBfHLrKwg^-*K=@TPw7{`wa zvbRHhoNu}|mcbz^Mh^f&RsbS(PYyFOW@d|AeG2>rsi%(>o2p$+dhnq|RM?gVZ#8%v}VDaAqB0#gy{tY>8xCvkVpvJd4g$^MafB;nUM0l)|w zDbJ?8H2esbT*v1Asoa!&(UgI0N>biCt% zAZY;!Yyg}I0~{s*Ryc}Plx~js;FRGB9dqQ$VNV#{I#`MO#|Lr&79J9nQTkaZi_eWG5wJ3G_e39(^8E zEk@~YlSwE|y`Tjh+;_<^lZY6cCx=O(k1*!n!E-Y8#~bU$aL@V66U4Ec!4_kw!|Jm7 z$v|sTMVZxUodYy&CuYcM zMBCZu)1XVB>C%vyNGAf20gy0PivvnL^Xeb)p6W(<#&h;Po%3{c7}ZThRFtvhnLZwqtj1_nc{v2AnLp%-Ot1 zX+=dT*mR%}2VCrpy(eu)nI7-&rtIH2nOU=HhaD;_L3pX9DMoQYClRq2!V)y3MH!Bo z`kwqOdNb54JF1;I&Ux@-cpQ#t1eg>iGZRM9%jUvaqC| z4C#z|aog2WR&|^2?(kYJ%IT{D+k?j#E5bnp8SudyMGG05@i6oWkMu^r)0QiX=6pi~ z#cHZ5>+0sqk$*IvuA)Vmsv2`qu_e$VZA&a*DuH3eH+h$Q$+w9?B$XXHi6(VUtOz)D z32tGeMV0dK>8r)#gIan6IU5Q!>eq zWm+bk*BKE+8J~BQvBeuPC`uIFbzn+>3D<#(T%|WiSre@Z)Bz$0^x^t+(C+)SZRp(_ z%T(tnweB8tC4Jg4(g+Lj1AzeQ8$p9rPhW{q)KCfvnUQ3Xwu2_Z>i5+Lyh&@X#QSvM zG@z(p53tu(3ymbmS|IH4rxCPq=*E$fRAJQ;&AMcJkc_H*@_%?->wgn_A7B>Z6*58D z9(80bE@F}tHcCh$dL$Al4T!5$K@XK?a6t@hxe3u$;Mue~_Wmb|n;J=<-%B>}{WW+S(#nGu;WZPn^e)sNsQ9{x_zZs z3k}P!huQi#pd>C*b{U@|NR*}96h7VsBowG{QcRC5ebr(9h`NE)EVt^vF6VxeQmtJc zF$=+&DQb5|K_(F*`FNyt$}XavVkc=jmbTG*as=MIir+ZO*JXDan^;>4A9@@~)Y_7E zgNKSZR$p3LJH2^}H<@xIzS%F&g$U8%bf{tg2Ly3cz~dI(nKEu6=@Y6HJsion-1trl zjEQl+p5t+^%6YU^M0u1mPbcY|OK}4$cCxVqUzovs+V4WHN_DL;m&Q2YKyf30i6^A$ z9B9(OuXpZ0D3U^CmXshtk*TtHnU8T4pY*qzFs_&S#D^2avc+Btm2(wq)L}5<(TJoK z5ind*nN$m`Vp7Zqu_DLEo6H#e)v_UBYibhcNs*;r+|*AK9v-cnDS$i|& z+b$wziw3GPD7&K*+tE}4gvR_vv%5EY-1|)fwca$g`K2jD#~x2X(Pho zlHxicM-k=>&j~a-b&n++U!wSiR_P`e6-7MQWn2|DNj&^OR4(tAT9sFHGf8%mV3!I2 zRTjSk9r9AZ4NN6Cm?WRX&NF~JHdF_gu%@s)X@{aXtz}M0i>7#n9~}l7wDHrr(6;K? z<1DN4FjbO#sLPGc-)m@Vo1R~Ha|K=k+O|&7_b3xOXNEYQsTB_1x80c)sz>8<>C!HX z`jW+D%d~3+1}jfbk5ESoG?7>lO;lIGq#!HF-osw!lg+b2+2n+cDJjx^AkRe4kv$YQ zu)6P=987!09}1{^E{cN`!(*+dja{}_SzAI%>c9be>KDhivxAl&Qcjf`W!AvNQjZJ4 z-YDmqjRb6NTFYfyk{#90yv4ifG$UJ*IJM_+6G;-9mNM;BjVehLaMgKeBVtJ^sqV0J z(C=~YZ5{^Z_U60shY>jQ(NrikFAK_RQ5d7E5g|lkWot4jYAhrozyqzm*MK9QcIFI; z`TIE(%3Hz>I@4g-WDgS=pXKF57FhlJrIa85d&|4t8jEYYP9yJ$2Mj^y@c30UV@RgJ z%{Ub_(Xk7?m2Gu4Z+(o9abPs=R_ACI7U79^P>y|^nx=@xxLAC*%>Ikzyw4-d_qXlY z-uB!700s81&vkLz6Wo4` z80(&S;ZuH)Q_nqo;L}Nh(8(lpcx-Ju2QgSc-{rR4-9Zkah*Z~g>_|J*hdfHmQCgGH z$>*7(%hVG=ip-Ui=Jiy|B^?5lEDOfpq?(zbH)9RG0h>nV3$@rFF!XFOL_&zB$CM$={9abGvNa8uE>f!g2K<%o@8r+rDPncAKjioar zA!<`ANK#ZGK;jBc(0u*4NW@YrQXgtp1Q0qe1)}DyVQi3DkB#Th3I8*yLL zj1Z&!&jSB_4F9 zqnpT~rOgtOVa!w}KXVP66Cga68)BVWL_SQ78p`=S>XMS$)z&yiS6BlB)sF#6#flly z(oU3;bd!idKf-wEP{5852-#PCmar^4puUSRJd4t-PNx~fF?>#@nAJKYbq|V3Dcma~ zLQGW)blisf*WO#9)J*-kx_7&SCLna<0FIwJ4sS!^!p*?6={ih~97!|AV*^W{#y>Dg zlsaLNy%l6-r5I*K!|AgIYNeuYE=V9@vYxhDUAJmTs=UXZSjh;*Hv|oSNY`O4AuXiH zk8*GxQ};(*W8Y)>cX@i{^}s$5T4_*pmt2Lq37@?vgn`6t#|qSI)pt@cimr~~xgBc~ zrk@R>^Enwyek0#vN1XxA61nPp0fpLk1_*irKT~Vl_5csc5{<^e84(TdV?EAzNGQ zqZS8H1>4ndY%->;Qck6kRtDecnDr?hVkuT?dzRACJ2uY2{7UrHK=d_0`Hu|Dc{4h$ zbIAg$1IF+P1oaXl0VOR|QhtQTt)z{V>uoj_BoIO7GBa=%08s=Vx2#4ynuA>mY0XH$ zrynEpA1c}B@Z|hJGS6J{b}d<+Ax4iANTKQ`Uq=F_q`-hvW~>%8`!)29c9j4Ec)>$* zLE%-^svFeXlBU)GP~ryyo|2uQ{{WhBH7nU({&Xd2!D-vk{{ZZ(k4KmlWVn7^#QJNQ z(vk|nUX^PFb{&jSl{D3~Q!tW}vI$O!6zOH|S~d+ES%tX)UD_)xdqFd>r9)zqGL-|@ z$A~fx${(S@aG8#o2Z7=bIPIgW)f@*g_3tFp_3xxrFyZ}9$=*b@D>P%}u{a?&^6Jrs z*(s_(@@E8lhSCBV0V52-AIzH<%@7`Be$){mX&V;f~KBP7(Ynk;G9+SwYsEJi12@F|-~js-^XH(+mTzJvXNHfzmXJ zw->`!m2*rq_l;+#XhKtCF)0O$$L_~C@300sf_a=-MrNC&OyZadAJIKNN8>a*)Gh#8 zcHutGe8qB1X}utR44HbCmB`ILr}I?VlC~#hUo$IU#6d?36J|)NN~gVTOsBPhQoGWg+6^TBV=l%OL%JwOdTWGrD8{1AR-9ZRB7|59Ws~kEA*~&PEe|fzddB8 zf^0sXU8!4Lgu@6m5dq#>npRzs63p%bo7mruq8&_*O$eW97mbZ01By>VxTN$?$Ihr$ zy>UD*5|Wy@3TKhbQu&FjZoSc!zj;_#n`zp^P8K*~fhq;HLBoOSr5*1><_eSM5gRiGksZQ<&8?JJd&suATM?+@ zQrxO(I!}AHh1{z~`Fio1mM)?r54goPx{)+eNu`y&)*)}-U3g&1G#_Ocww~{gm&{SU zq0jL2+}2>3D-VikYao%KlBE&Ebv2aYo8|%$?z9m!j)*h_h9r@G3mbd5CIG|{k64NH z;Ya1(=0Zl^o{}TojRFBMCBZ9jY*PS>7x{|%I-yxRlA@lKiyCy=0WsA~(U~0B?Yb${ z9#w^jf&s-QdH~1Rc+p6Ocu1THDV`zeqY6le%A+>%W@fSY{gm#47|s zHJ-Af^)(K$uh>PBLWsS>Dubxtzf_egX(XB1GG=3kP~k^9ipf_=@}cg%9t;LaqHw#| z0uH6Ly_ebTJYh!)OsWTQ$J1*b_uGEjGEXHnJbPnRKWLPYmKxju0MKxwcb!Gkt_2cs(kE#N=;MLM%C(og9$L<#N7^S6 zKp%|ISJsT3S%Owq(iom;1coY&>f0K4^ao+Jyv4V>s2(@qKY8-78&l{6pX2C}fFN+1 zCCu$S3Lr`2&||Bfx?<@CWA!T{VtE4-LX%+>lgfxr*;)jVV==5rAs;q@1+E9xK3mIDC;I7l+EyBCSrr9bB zAP^O_iP(5ilOSCI0zrw1syORct=~_1b2ruGZ2g@^Crz9qWXtf?VNlXhv5ZGgRfk20 zRINBjqmcXZ&!TFfnAiw+A-#7nD$wMV6zPNttpamDmeAV zGJ1yDs{8yqdYjfyP9CUpH=?X7JK>nN6_{k39l#;}VNYL&Q%K;=Ed?!FNMm{Ck6o*^ zcOfgO)?PO|#O2CZv{P$XNm_tdbqWW?DL4!<1pvr9I%q3zVQ$G%Tw2x+C;&o}Kf|=o zPR*5PKD0V()o!YEM;Mc+Ia)k^s}EMI!xn;yI!BG-1Tkm#R$eqFFg7>87)>L;LhQj^hviV3|8`jhCVT{=Ss zGmph=!IRQF6EZ_qwG6HA50kAC)G_}6D7FqQv@*B?+Hz{$r*afNwv?3>5R|Ddha66# zxB?fbY6_5W1P!n$2+Z%7iz_J;;V21hLkva$7>$SLMpHAf6haBuVPVv7J`mlL~D@3S=B35MpDmZCQt*yh;v|dQz*;bqg{a zQxb?sAWhOVE4pIwui7Fq$j$J*uWn~AXE}G}a%)tPiqN;e)mC72Uwi8x?9ca{*wb(SCow_{`8tUzP1+teL#Z0DbRXB9$@k)qW%}Amk-QYiyWyevtsmu zqKtWg;t`sIEb2<=lBft-e$};LIn1x7n~Qbkmy9Vxz6>{|I}}irLxgmsDNVxZ$=gdlzsb7iKK*|`jQPogothn=4#Nch)R@DzO z6e@QgEDPTHFgE1%+8vvD=Jw^ec>zEr#}*U2_F0kze1_+R19#;IgU;~u>6tTlnQlzCecY8=V@#+bJF z{qeU@HfiOl(#zbRZ*Jp&Jk=kVZA~lfP$@hxA}7xrIyTVa$oFYU90)%;r!U6y(&5Fk zj!E?`fm6pw~5}9_lAwdKmuzEr1Fb=%z~Y_num* zqlmo6-UuU!jiNwSMmw&oK^)<=vcE!=cWeS%)1_pT!pHPdh$>MNGBFbaZG8Uk=4{*d zS67T1gd29lR}Zj1W|p5&M|7fLD(^@VRtk^+A|MlJxD`j@eU&pVAD3o~M^V$9iC2iI zVnOrkX^*)p-}E%-_OcNofgQHk4k2|}>k3nC{miFS{>`0%zL?!|;Ag3La0kA{4 zW9dS_KH0FfacD>fRjsqB1xhouDoGeFQk@|o7$_%Ip1$UsSu zDyb=>hVjVbZPkcd5W`*O(4|b%~{gFG1X>VCZf8!zLy7TVu;^uv^!4OCRX$@6FUj)= zH%8zIK`el`QnCqBlu-otX+bJVQc$njCkINDq_!ACpz=Mw*K?a)t0Fh!ied`Nq{DKYcm%R=W*^BJ8TgX#n3#ODKKF?Q+U*wMM+6 zU0PI93D%M0OdV~BMwK{|3PN1gj_GOvE`I?u4zd9`-0*E>cqhgu6VdzUjYb>e zxoXQ+P=I0qkdq!=0yak8G#BPbB3x|Ec;r-;G2M!&31Ph08y30R1@C*Y?ZK71l8!qM zKd-P>H$RkwE7WwyJzmpL=%^v6bs|g1b_Q@9mtt%gk8l71K=yXmzTI@EkjS1{BRg_MmW|??w0Mhc<|OR zz(-u;COt6yYVG6n#p%li^qpOwu^hcuSBcYO*((N0(~Zpxv&oHN(bv|*cd8oY>M2i`qGA(5I z(Wi!;1|v!YROilc3rQH$QKi@&UB+DN?UG7bcS25+;u`czib(F;j}p9PDOytrC1*{0 zcKcUeVVC8%S(T$i<^ttKOgW^qi*0II?p*ONz?lIGCU7QT66u3}6W*<{e9t}u{I3p5 znDO~?(_bE;RTZ?9ja@xCCQil`Cw;8POK#$GbdbK}sVP!iaighCrX4^fQcA!H5JFcy z+Lho+$-;-XJ*jS^4F}5I(rwXnBHh{UR^VwWjWPF_DVgF;Cnfwd{Y6mWOODl3VWO5S zx^q3wHAo9#^HiE>*a0Wn5*vAU_?8+D6|XmCC@U)hTSL22PJ*o>6Ea-XJWa=Vk>V(f zXvG`%yG}XXC%x7AlWG0I+#U$;2-)`O$5eGe+e)l^@TB!cgyOSg%u5f#<-{qmtSc@W zZ|9UH{{Wa*(=AOjXiJ5=!a>|@tE$e7QLtLy~{~`3U|9KJ8~3l-GI|8Ev;W{$WVX;$mp8EhkhAeq9&=rX<o`|B&%-mWI7U&b&NbCIDWs#z_)a?{ zhZum7MU2!KXr$US^LN}8zSSSTPMoXRi!7kHRv;y}2n8ij;Ry)|okeLRcdf>@_NW0* zv)X<_{laaM+xpb|*1&fv{^@R=ZjbRm*r=1UNEp`~Tkyo|&J~MenR>Q-0R{_>V7X?l zL5@>wO6);U(#N=f#anp0*jrz8*zr=X+d(8ak`m^Eq^T-Qt5=C6E5zS{TAWO!AtzB4 zRy$D0Zdz%?qTu(|?_D5%U2%CyB993ZPvFDY|Yp0hjNh9>q}?=nbzuxut(S<6_|=NE9s}w zcd49_k+E#ImSpMucU1FH%J?lt9OPkzMJG_)`IQyyQK@b z7YhB78qkB>Cfz0$WkJFuCKMu_Jwp0m>K{hsTx&K_xAk`&tHfc#@u-yfSc}n2)blhA zZObf9rDTnOvAv7^t}S6iHrt>O7MVy_LRF<>py^fwjfMqf9kZEU{IuhCs{gk(L6M$5K^SzQ?w-EL?1BGPfVYpR!c9v8tb!ZwSge8ZpYsH?ZNG{fm?mOKPcgc z#<4GWw{=-trKli?Bn&_tG3nxZ=_=H6R7e+a^IewW_ujgaRa;$u!fXb&(%d-jG>PHx z_IyP~BP=UDWRGXBPeF*GBQ0Rm&`TWDz%xm^YJz?1_Xwa3sz9~Rh||M?d#B2Q2Zy`N z@js1Z4(aamZaR|UWNjFafZ-nczJ7{yqo9=@g0t>+#4>&xi({AuQp;HU6;%&c9cP5s3}x? znr69`rt;WXwQ%E1J$H3(q$D<`^tEi$jExIPDp69@RHCRmFo97zgZO52$1vyla+gN4 zEnX8*gLLMXKH_PO1gxjoB|o1vBsH`{a`|RKw8b9Oz(%`JwU^$@QNCoPYA)Kbj4_AmFL9ZTB>O2)n^GTv%*0R#bZN%Fo3q=$8U5J z*Z{9u5EHGjE;@kYNu6XRDoGNubReB8QdNaXcRjK0<96$M%}RA?Y3G1bPNg9XD7NC9 zB?P4?Sb_j6P>lf0)q?dW(eI}G_0wE|(B7HT6r{zvnT=$H%=GkuaY+O*$K}n4M=Yb~ zQW*q*pz_whJY{<^6|?R>@-!3Om)3;-%_Y?(!)@KjL(0@r9Xb${ph?nRSyUq$GJeqW zoVN1!Grv@+ys3-hXr;>oQC6g~QlHqBr$GwwnI$U<;Un8_9SI5{&f{51R;2z_ zVhDXfKjkX#3sTCGl%*QUQ(v=6^$_oQsk(-zJZk08jH3MqSM` zjSz-c5mYm7id0+LYH617$q8=ErLH@R+yyrGVbp~n%z$=8gR(~4N0l7kZl$jCGMkGM znJ`s26k$46j1+|oBoQR_V@1C;<>ZPpi9pB0aq~51Z+OWe0_Bap(c4WpJhHl<0r+f; zAa!)s8E-D>uPa$91W#OQoOK>J@CStiviWq$zFk2G70F-(WO%67M)4$SPklHyPmi8I zA@238W6ZMg6C5_l+4K0%RX6VWVzIk13hdyKy3RG*{=a+cuM}z3i0F?`l}7L7`V1M{ z@A=j#2#`HFvh9-Xt$_q;*EZ36A7$-vZg>qi^>gb)?pfkTUnk12Q?(qhpKz%QYmihn z?Ety9-P&5?umq9Eh*C^`vCrZtu@)g-&n|tNAl5mlM2}^08V#Y=V{M)nU_W(^m)753 zED81D9DjF58eE*RdbUjP^Xfe~#dZ;(eaeq><+~zWZ9+65MZ;L@eF*k*UvQ53?rDp^W>+-`r_8YZ0nmIsx^jSOGs%j5IdZ^&G3w!2A&EX< zG?rwLfZ$z2Sa)9bBTa5c*M4b4$HVpfFsB89nT$UQknq#f(?uXwV#eW=UBF;K0FMiw zt5ajfLW+sxVb8A0eK~%R41PHC=}_3WV_*PL*{p1$*Ri+46ar5L%Xs`E%lY$I){P%P{iU&~^@Y1iEh-os(cdd^wWBNMk0 zorA1Sz;PgS;%a=#5r?ylZ2kCC=j^eUvt>pbiB-c(MTlYbkWDkq?ybj|H#2yHe;#8N zQGUi#oh0T9?ya9@=Gpa>$PK@4;sJmRj_@~x8R)2!wOqN&{J9EcB};A8s3Zv{Od7OW zT<6nVCo|!d&5YoNMz4!tIK5Pirlyz%a}%+R*fNGHMVZJTi&(^2b=|uT+g!M-KLeJo zD5<;G`=Yi0amA%-(y?r|((}LqT)HS~7jBIei!NoCw+uL*>G8L|p?D2I1pq-H z9ibq|J44q|r=`I2!+C~|DJrVzS;Xy%Ng%U6v$6kc}SNNwFfqUPZ?^WNML(-PAwKrG2ptE*f!kd!P9J-`x$ zh>dbB?-8+c4Bo3 zcK0_NI=X#X%Sp}KCrcT1vAcQXxY``MVI9C>3sMu_J#dsXQ>Rj4N;=^+CGO68H({U1 zK7ywga-iB0q{q&7+S`d=4De*#ph%NsB41pxfe70v6d19Syn@ej%2QJ*UY&!5t z(xf;6b;imHnPDKQ3UzWKlG8lya0;@@@mZBrRb@Ae5L)iG--8FaW^DX&ZuKT@J}PPZ`59hGoVn(-^2) z`uN_E&eiOwK!#~jF(j1Wo3u*GgpF=42`*FGe)i=lC~Pti>cLskgzD4$DkmK$ig?Z< zvpU~$w`xjSUBnns0cs?H)8Uxu$K6Ly*Di6$-7(7DGs~HA8j=iA4NQ|^G;#U#F9jr1 zQ@uJwhvgPYBsW-ss{?BlxZ)ko?bChtpYup{YU<^mxpM)RZP52sptTcF{G) zRhHX2lstu{vb6xDD3Sn@2^j5xhysYFc=ZdAI)zsTA)j$Pe9J_{!zxg$Zmbh&k>g0# z<6%2@0p9)iI?ww+-u(F}X6e>c8zn(HTStjPF(D#Pv!6e6YiB1XNR%L$uwY%@(d4kn9psc?~oMl?N z`V3y8qPh1qxz^=mpx=;qL07Db+gc>UC;S)OLk|f#Jj7Sjn5Xr(0ZY zOeh{Q4%z9GHK$iux>Z@x{;_8MlvKdWHeSauOg%w;0z*>E2xT3=L{*2kOXK2`LloGeI^rn6idd#37^2n1G^|Z!$$+ zBpvZN19K{=T^J8@?*`fzTiU;PlBQFr2pe`0!xK9=(5~|_w9Ax~Tr41|Dj*TGNE`te z9ubFbjTjb-#fh}a(BA4v}+}RI*6WET{1DAUzyI+X6*R*W*`v%^brkdUyxR8+O zCP0lU+C4q~%6_NnzetjJ>ge&LQyXt6Vv)6PaQog~?{zdfn~!PXaV zf!*wn;vS&mI2>c+OGbHNw73S(;W)>pJye&Qs68-%{G=7@EM8){-A=_7Bwx}Yy6!P4 zus^(eox_I%EW17}Fk(L72_WIdH69!~B9Ny!v4WDkH7ocq?$kD%KH1wIBg92Psp^MJ zOh%fXyg<$X1k;0Ojmf^H^*uW=rWL$7dcTed18N7{ zg9F{OfEewkIJ&9Rh~}Q4;_GuLoeWg04(*_o-L(6__}gC-YjG*b?vw!0!VIhB(bY>v z@MYPTy_eEdXv)EVy3=C zRR%JCSc?E`9ev9M3NEYQ+MD=2{I2kS2>jg^8frS!H)%`}*!YBm=zKiCdR3yA*E_-W(E4pnvxgbtY0HpV=5 zd-zt9yt!#J-tZXdRwrllcGG=-QaWi_Pf+z3kDcZyK)zg$c44)**#`Ss_F>yiM-?}f z-Jpm>Mms>+ju_$5B9kw8vc;s5=pzvU3OjI!3HN(xGf~uRfN9M~T--fBm?q*77AL$*3XgJOXZ}hfopyIcSFIpfur0E~PKIEAjQv{K-_)-r| zMttkjiDh}IYMMx6kPv*5%>H1sh<7E(Q}){Xn!}EZ3!osU5;|}ZuY+707%j3xHp_iuk5{pfProKBgM zvsWGza+j!mI*Jc5aRSnS#=;pdxEld|mIa2p zzO6Mp(914~jW~Ia$A?F)DLc!SkM+!C7}Bp^9{xK8K$oaJI}@*$h^bd*4Y?glBMql{ z5&OXbw$ZPMziucQZPa3qEJ1^}3~(gzpxU>KEhzxHG1asYBg;>*J9yKS4~Js-R2ZHL z%~4G$*pgoROhkdVa)NFJ&fsm^P9{)WD=2dUF(dqLm?z!0u7vi_wR(W-M^aU={{V}D zfJTbBEvJ3Z-UfEV8hLkL(-PFap#L_e|q=f?pbm9XVBrq zPK9HJmEp6D9Vdqx#va)6Lz`sFQU{HN2b0qPLgW0>eUnZ8yC;7{e!bf*;IBn45j8}Z zy+s8+UWSe6u=?pv#iYbsGfLLqzEx1swbxKNF|}lGt=vLE3QvV6QH2qV6!7R1wz*=5 z%ZWmXCPqD6CTAJ~{{RvkD>`HhTPpQWq2Dn1do)u#Jt&0+5;1PM$cYZ>aWE{{WG1&Uw04=HDlET2{SEY&IPwMKP!Xl_+e+ zFyd(e=%XR^BdfRvSu=-Na5~IEa#l^Kt;@J93G%f#mOW82r4(>Q2=nUN6cS9(pt)5y z00YlvY*;njBHhG-wZfIIbf!|CI7TF^sU*!yd3S4D;D;1%O2R@;kgH^)Qi4>Vk>MU9 zKuTodR0K(?)UNdt)@&wohtwru#Gxu?N{k>yEN}bUquHmhgQwN6B=m08lin##ldz@P z1a%px*?qY0gB~4j6$p^4G>AKK0T}%JsU4TICOw{Wgtb|WJu^(}@6^E2?~+0TJhLBk z1keF{_zMmi-C8%7umezFY)XNEI0Ws-kK<7mPP^Ui%?p=BLD$v_oOudJD_H=kYa#$o z0nh?O3b|iRZuG8&ahMG7M<}BtV*> zyxo;5G9GBfGA3fCljrbispzT^Ncnr6OQ8*uDrLq>btxX=0_Of+4zEikT1S;*AH|C%HDzTj9c|Zj!?Eo`R(lu_+r# zK6n9A<5?S*nSP-rR+id8#ZJDX;Yb{Cl_>uJ2#MiV<yN0mk(P4 z%T9FASOPDvA{Rk8 zw_AB*!N&YdEiKNh#Q*&JcdmHVMXvmsPP& zq<^*+Q0ska`-wYBim(nB~}bTpM>B{8&Dr?^*kj`szuG(4Gd+lJZ8*4w@n zA<0H22~faH@q-xo&;d(xiYv5}A^8`Bl7naO?g#(j3hX zOmpNJ)}mbJJaia$^N;1#G!aw)T)NXxgn3IKHf9&GzJr3BHpSCxY~TtB!)_jX3H&LJ z)UwxB(^pGNj7F`nN@`kade=u&j9deFcIwf0DpOX{Qj~zH@PK0-M`WHoHG_HL)Rl?CXXAw<`dJNb zN5?91ete*<5mwT=Q^!Xbj-sVxA$`cn1~q2U54&JVI-76{ySFOJ?z@YGEjrS4fH6@f z2ar4sM)%EksML}$IMrwVI$aCKW$6Y9*Zf|D+bP!4($+wz#tKX>sI4rtUUkFN%N^C` zD`hQk7@lUkZMySCq^AukQIFvuVUJeAc1;##w*ej=BOk=prd3&Kx@XiJSEltuR5c-u z;*}UOc{48L0Ire&a0P+4W3A5$GV9;w45H^|sRSGjq?jf+OjLyM1VG{QrKKzoP_zS@2A98WcqUSc$I6O8ihH7wMMPLoN0KHYTg=yEB9>EP28*a* zgdLy@oo~ctP-mFujW`DiQT&t9KvrF%nZSx)EP~7#?k)(_Df?SZtU&SRwQBR*S}BU< zQxwqQO;U=n&*hz`%Qx~El`R#4*yiKi?_*iKb85fAo-s$ectBlZSUmT*W2#x_G`u3 zj>+fFlj#-z)1x|k9-}ayn1VSVG&L<8#ua9iNcQsKkc%-upaF5K1~x1mS`JPgwKxRp zr##h(RAiiyS3K%XRFxu z<**KZR6}fn^2*h*I0NUjo_=&HW7&2*UKucKN`e%Dq+c(~P+Asio#HJn5tWE*cT&2I z*AE8>Gbd#lsi3R~qWM*W=boPCY8?BJYo3C?1*myx>#2wh1c%%pB!QHyi+Id(21Zcv z$OtEStfJv1w*VnR2t0WEjv$Odf+&&eZ9sx0CjvS5bVp4Lc-|F&bu%T_=lqF;QY$4i z(q{~z1=T6(EUPXfhex=`aH)v}!ZDK#oD1F&8=a!$w7m4 ztS*R{sA~$`32_`MU6It7?9xUOMJ|ubuE?_lW{f2Zfb&0T!xWvP(`+6cV9}0$yUO1@ zxmGQZE*pikr5Fw%5EO+g4Wq)Tz#S^sNuk~;3 z!{Lz9{IP~$q{$q6I))zIq?%)NGKTU@p}RYj!=57W zIR4d3B}xQs8#E|%2*#-&)NO8E^$m{Voowi?6tpxrGI`k6T&FhvP;9V@>Nv-|_%w_| zDAlOgm?k1WDn^J|BH9wNbuVE&V}$IO_VA#^#$e*EOD}kU{^sGpuc0g898VpAW5hAk z14m3nOc`}(sahbis4NMwk+)sfYg{k@YJ1qNfwvi1l^T>R{>T(3!HKP0wH0)DkDi4D+Et@{L%s3fLzQSInwMk@OI*Up%9FDy#c7x_Zlk@F(6^qo+Hd~=@@XNE*p$zA5Qs~3hReLDO?4|juna@e{Gmk%zVHAEy%xlvd45l1eVD#IHc_<_>srXr~H}r zZh&%QRs4*y9y{! z*s0V4PAPzVNKoQRNFhc6_qG9EHAWIJBg%Hp%oGnmBM>O``a<-)D1a`D$2NI-yG5TRhV?5{sR z&9&6-96w%nY|}%#bQLB@nLpzuK*T6|g9KtIp;nHmMo>UIW88el4`phr>mSn3RXsm? zi-RM2PwE6T9UkkR1&f$kWoed*hI#%@vjuq?%C&J$(nkOUF?($%cQR`z&yHgcTdcyG z2~-G?24rG&@H+@lBphhHzWKdLASd`&hTrjcVhn@Al|PKW4V$sL-j{U?1;f@no077I z7nU%!re#JaI=Z(l ze$g^hB$9g0!_)_abU>n4=?m2!X7u&dY$vK&9#~|cS-xf{BxYDB>lu8vSsTGBBmESo z!uKOf@!J>w0EC!Iy~p+0M%GthAdlcs+0c30MpN-v^tnrkN0ohZ`hTF8`m59m5s2c{ zumJx6%Ii_TPGw~}fcur017a>lr;F|eqE)x2@$%{GtL9egclM)bjbA1Fk6lxxW?-Z= zYlc!rsWfCN0M{42)P@=zJCZGP?BPK)8(YF4dQ;^zAI)cMc7iW*jyicKQ?$EJxRePK z{jJQp+du%mhn7f_N)!7-BZN<%l^o1ghX$v`DRA1k^mSkTmyC4pbn;3swfG_;5H*9Iy;I3uiOpSqdEL#gYh0hdgCweG)fftF%++#3 z98?awQYGFyT$7>tH02hq6-7`rjaO_AOK2~0!qx<6b^NWxts3$~&}WHO2!l;~D&FCH zpYV}yXTydd)4*3emqAg8=Nc828DXYlG_G{H0GQL`cJTIlcw)$v15YL@tG^%I`H#P+ z%#YFhlTT5JS7Z3(_|0843@<#QlM07w7V^Vv{XD}%-rS|#`*zDtrx1`Ns3}PVju9uP zqMuE(j!$-#DnFud}WtxqtBB!ZMBbUvq@{?-; zW^3Bw$G;gF&6#j0JlqkCD^ZcKfSH-NlYkl@kSB0l-Qp^^PV$= z&q56nD@%2mGoE-k`ao#9C(2t%s^RAI6K^;Vsn zX!TioiXqjsj7e6f0f^X0PND}Hr_2Y_W=!bLNWgl5i*-*0HSoGs+XlmNEJ##&gUm3j zs}x9MeMbE(K~e^XjoaR47OWx5dnXE#brm@4O{H_d2~x50!j{@)3|O{;?aEU)l7`$| z@gRM>cu}_MhflgQ)!day)cg@KEJ7OkIVzHBXyK(=m58h^C5_~f(pX5lixNk-zX!d} zb(=G(NVRFT3_w$_ERG^ZglZm9Ld%A&E>R7YsFdv?DF${(l4IXg(H1F! zhcq=CC&g+p3W*~MHl(s_g;7FnV6rZ%Z@8a#nBc2*TD+tcNJ)W)&t5f;Ap+U;0fZPT zB>5el!^4dojAD-!>GmfEXO0>brJ}4sSZN+dnV@hS%(E8XzBtHaW$fyuZ*j%9`CsQ7 zQ)h@H1F-)937D zgO(eZgTf8k%UsLYJ>n6lsHmlA)J_}-BLgHsCVHsrdG8T${-((&fCiiZ^PQ&&*@VV5 zUmu7E;h&!1>Fj-Pe7lmet|x*NnxcmyfNZ2leCJ9o^WD8ojA`=krBh)So$64Thy0QdRK$>OQBw% zqRFsg^yD@l8{;#IN#iCeiaBDfsE`+p)T!`cwTF9?$FhseqTx)7-t9RgJ35NF#!+m9Tqg|WW_w|ULA?V7Ev+j%aXDN@#wlq3ui zh&ZWxJW?bG0MRb;D>FnCG}lip6yCtGxYL}9O5yME@_Y6~gWU?m7vf{>)7tm+XQ zWSx`_RhRP1C8t)cP!gell6Z8UxxiD`Lj6nQ(R3Hp7DdelEH)?0Ee#>23wVooP~(R8~~T)Cll{AiyS6cE%JXPKC5} z?Exnajz1$se=KLr>ykQMht$DKE*(>iQLZbLD^U^{$iUSwtU&^y9%2}qY}XeoyUy*` z=N~t3HO%(|G`8LgU=s>kMN0)pbqgvAN`N9jRB;3tf(WeR$^QW1m7ANg@DTliE*Sp+ zZ$a0A8wpO6(;B*HR`ki&{FRM*%gjA&>IHlsFH=Vb6AeuqGRsdTWE5~L#s!U9RfM;i z%66XJtN*9dL2S_CD;>QhC+8wvqL0uoPn0+a^;PBL*{C*7Oe!zH~< zqiS1CL-mu>lmTb|$A=Gi^VYjh1Hr%{I*J>w*7*iI*I014Oy`;}#K z+7*}HA#Ew8chH~#Eic0GgNy{s&dHj$Zk~F)^!1-GN^H|Xm|==q*acJ5G*cO3Wim_i1NIcD}Ufg$Z+cdkoq%z`=g0v_vz_L6^J`*sh9A-UCf0%YjpD}XdR<^D> z&{6K3Nlup=nL@{lVN84JOOky>bhf%5o5pcjDd&_iC8;U`Ff7c@Z5E%KTBYyRCg zG#E}|(H%{_K40AV6n@ubd&U3)$oeQf>vgr@5<+Q>QhcHq~btzhq02&00c7cS{ zW7;n2X4|upF5>xu(o&?LDMcq0s{sI$GBD__evmysdiBcwh{hw*>_Kqsxu5e69YIS? z8t-8fMJ1JxOky^(h5`Fwoq}2Njj-@e-+0u z9KliZu+L8<(z{6$meS3uD%|WhAZ^|5kQGke7G*6VuvC~Z1QF%$^W(JF(st!#jpg=C z+q66=LQ(S z0~iyGZR76S&@rxzZpP^~nIJuIq_)~f1!Z9Z0KiI!6FVYkLZj*Cal^pGUkI%xqB@z> z3Q2sq5+>MZ-M4F?VP;|OD`-d}#479QP=cg^h9yEkJs9ECc=gs^S#G_hxjI~EC@4%V zBgRLB5jZJB5SRpvK#I1%!W;VI(=SuQ2+kOGA%)UQis1C_lhc@&eDTy%&kaec2^doa zK=Tp(;~j`r_fIstlv=pUiYdX*7NUfRf`tNH{g_Eg$a7zVNjiwEbM4aAoWmg{g|^{K zPbn%&!ptP0X;M46Q6a|2LX&`8f}xEaJOiRxzx={Hs4ZGfZf9Bbf)~q=4Z!KBN!$2hoxy%CvYA}nxOSrDO94pW^T&2lywvhx4$0Z04#%)8zk}3M;v!5gzY4Fy zWyJ8@V-t+VC3?!jzD%-5d&)M&=5e-^+SZm->pIlx8xpXTmdgccStGm!)tw>5B|);{ zf?I4JZdpo8Tao~C)RSSnUC^C)G6M1e?Evj;wAfy;Y_9c{NH zLi89~yRX@(kV#U4v`6&HN<=C_8#1$hchSpCwfo$S=Erkvx7JDn%I`I{l(44CzhpvJ zty3jJ2pTaexAZB~{-|`@FXv2+m>Vx*`QNA&`8x{2@sPDNEAqvaDg|8mCPAxFsFir$Hb|(v^=$B7-cK_-J*@GxZjuE93Ie;5b~6W(vAIdTO7Tqr@Ppjsza_NT2-W_kg~OE2{Vcm5@IGKr6y=gn0Bp`W%jAM zWH|GoR>@tuQ=!IHbOC5QR|!mlFiBB71_qCIMfBC_v!fj<#B+8Ff>c&x6Le1#&NUc@ zDH%1GZY5h#uwhj+Fcwdf-Z!vl)PHjb);=2FoNZ zCE*UJgsC&59y2}j&UcFayJfnBG&9z$lG7#{d6v*uaEDb2?_lW!D4Q+z7)rK6`Hc#kf9wUwkQEDnf*952!G_5;HTPnJZzVb2;d06O6&A?>~Kqy@PSb`KM zP;Irr8l78;O3Qk?r6WpNQ7r&~69;5LzW&1H+VWN7ptEbVOze(j=YXY_asMBb*tZsh34=tXA={z=0 z-`;vh!lA6|EKRfJE$j!|hqDfkokzoP#%hI1+%fNO$AgzID8*5D&gk7P+6xcPfF zR%z}Xlr1FmjAsqLe%-aQC4OI|#JwctY@aPmRe#U=wUH?vn9MxNb*Iae3%MgT2#h7% zL1Gh2S{YWEOwH!)s}a|D~uSc^(Q0X^lZerkL9r-AtolA zq==?9AtXma1+Qy>Nu)ft1b|DX0WzrXE>$D^p=5;UM9=0DJTT%&N|qPMGS-|jyo%8FVftWytYC6EKXCp)~=v!2XI<7X)gM|PsJl8}OuQw6lCDobV(3?*p_26f>Yig2OJ zeUN3=?{~?4-9qKdxzd>L-A8n#K_|jdhJz^^KnEI9&-lP~%Nfiom@06}2Cq4i9NHz2 zy8wVdf4>onQ&I{TYPO|^yG}OwR`R?`?$@3+ZXsRgdf`x5a44t~-p-)pl)+daVsJYO zO(M4JFDFBPmrC6THmb9Mr~W5Xo$8z7abJsE>l-yj6>najbFM9(eIIn=sTi#wlNQG_ zlVw_Ugv%19ADktT^93?{kLEnq+^)r>j`ob801#89O(VHNoWb-om?k@y7+-wW36I*S zr&OJOF9400Griekd0z2f**2(Yn-O-cT2xEfa#Af8aT-#If{+3i60oBrN$d4oIDb#G zUI~KYc+7YzXX;*`ng~rDTxo&jIK@>2;c5(3Z6yW+Vs!W89#F>MVr;ys+SM8lo zbX^1+c0mlFAdvp1!Tp(1Qq)RyC1F4_x=oj_EuD3?3#Tq#W8N#gY@4jW_im<86wph+ z1NOsWR004nDs^Ym&seG3F!c$#txHCgIll|d6!qAKUh}D|B&EX^Oe-E!Ln5$bl~$F} zP(YFa<_2N`H@&_~3of~Er6jty5};H{(cL=ZS7W=?sD}!zoGqbEuyG=`T3?nZSKV)MPJIaHa=~ zV0eam%$0O;!4Hu2wV89zlMrSiK+;X-lVHjc<#wUmIa|~w)j=+;V5jp1X>g@b@8#4^ zq%AHZyi$S^qEdf{NkW2DCH~Md+>-AlP2NOH%{<;;YK4_6P-(l(0gxpmB^n|~C0HFw z5NV^+J{L({kbN2D>13f3S7#j8i&RHaskTVroC`Yn7cRgN9rq2}Mf4UcKwv!4A-ooQ z&0s-KdcX;A_X{N|4X6qH!hA=-pAt!q`#z?w_o?6fJ~}1oibw+ zAy-?yMs!CldSn@Q5TL^AV8rme--U`Qx=MkFQ{pEuR8>*Qhmzh&3JUziY9w)@ua_Av z#T4gu?SMyoQV0(LOl9Lky zqtO1I&WfBj(X=^mQ~>00JZY;9r=yxkY9zFBJVwy@cPOlT8~e7f*7qH)uNJzcCP2gk zwsyzAo{ECnv`Hgo&5=tiCVF&emE-}^%m(jwVu5E?>^u#;KRyvWl4lRbPXa!CYbv)| z+q(cq3cjCDRK~OL>^7N5RNv;sn=2Ip7LRqc7YfULHNA)h=I$jibjNZWT3Qu>xuio=d_K;vE7WG*>;+{%hb7S*ixk|i}zBe6sb@v8kGRaP#eX>D-fCMRs3PKu=2pETtB+ZA;!Jm)v{f8?qx%(#qLjRf_O;<#hS9Bn-; zF#wKOf=dDgt;$;|PP*FKkga!V?;*)tvEy1+mf2c^afnl<3ezniDq3q7H<*hSF0INI zq4_MET5tuGGU^*s4}zrxI<-oY1b`Am%+V-=t@&ru$4@#toVu&#Q($#nCCu0|O*|?D z_4tir3OJ;Jq-T)>N4(tz#rO8x?4W6(aM?j?ywuCcPM+#PaaT!7$?sGMZN;TSQd?Xm zQrfhoYssZxo=$OU`ASrLEi%|HDJls8Dj`~MQPi&vsoElS2P|d$TheZJ zhc4yVaGG4rlKN9!79T?*B2>*yj5R%OAqb;ma>NG1%}jgtR*fuoknXddp+#9Z=I5_5?Nric+q*H0*flLVB4*Ny%4VO9`LxIu*wr8 z6;YtXF)V)_^;yykS3KaA7)nv~6BxxY(@`x!I5szqVOwyF2f1pesD>!&7NQ~Lfa-)I z@KToUE!+!yEh|;TsU!0RNqOZUr70n0YAQ=8a4j&hT+*cwfGQ1TmaTFO&AV5U=B%}r zt@MON&8@5Rad*(rLe{2>OFGF(P}FF(1S22Tq_eyI|J(`VpuVnYN!o8 zMHVj@kW$p5>}uL(X&=o5pxi^NTEwxpZcxHZh-H_w>qEGb5wAkEr3-L(QrU$i3MDHF zFq)dPEXZY<{oVb8uQpe4l3Nupq%T?>w^p9<1juE;5S;`C7zHFuiUakz>AHv0etw4q z!E+WLny@@lkk;XN{UZ|%OmVq}Pb?AoM~ZF8W&>n|T`Zu1B{qPVQ$(!_J`w_eR|R0O zl>n6joInRjBWSF!b9hm{nNqIZVOF;-tRdE2``R(7Jws9mR)Z=)AS;12vy4(swWgje zf#XXygxHquq>EW}6K2(sb0-2<76BSD* zm`MykB}f~7!TtkV>24pO&J*d*+5uczK_)r`@?8D*J@z^VggUKFJD-x)-P)Ca!?bo>d;%-N4+m+R;9=?4#BW)!)aYhltVCy_F z+tNkJ@!~S% zVw`;W_hXGHPEri&5sw4-d~n0AylEt5Ewz$XvoUdNTiqIga!Ay7+u}Lxan?3r&+p+* z48N)l**qf;X&8=DH1cE-+sejF((tl=jK+sB_+$Bko> zk)WoI7-MxRO@KEeUhQu7wZ0=$+m;K|NhEX8&K|Tz?q3N20x|RU`y;Q?xjhrl8?=ic z+{VsraF^F@hjPFR_wCIG0%9Y}ulIUV73I@14^iss>zpTTbZKQzG2{eoVRaV;RfX;b zqT!9bo+qBx3<1gg-n=QF$Ur2{2d`n{8#dw5#<|6XJgnkoP*t^NHf7p}Qos*%fnnkg zG+v00(8>7GlX+&@+Blt}2g9PK$AijJV;7R@*>Og ze=n4sBOh$=_VsjQPPDWM=SLAxu*bRFTzP|Sg~03uz#yLIP9s~G6U5*;G3Vz=1(Xiu*U8SPl%cvLgN{|iHQ2G(5_VX39=b3CBKuUNR2hw`*jCdLm>5n<9 z4)s;(lMv`N22IQvBO9y4rpIX3u0@h5Hmkb}tZWaxazG4hZJ-x7;4J|Rp`QB`+*=~x ze$2I_Qr$spYb3Z6-N|tvAw@(936l?Q*72`+R`>|eS$DhpwMgkuj}I9biZVT4lkp1a zHcG&APFKzqcIFts0K#82UW99LQ7hkLS89tL=_5+^5kSW&BM(14I#$VsS6?&lBw?j3eyTANSOe1 zR6kWYd)00k(hQ+H=Nv~Ks>~R1sH?+Pf<%UuAWg!}6^khz@4sRRzkNanShsDPH!hr7 z(zZ(4LyK7qG>4sGq@!BYk_sDBiSE#VgdI4HP4{*Dz3Z!#+c48bmo$epB&ouwn4OY# zK{#Pr#`W_FuO@n|LS{4hfuxWFV<6Bfwd~Ejn~+E?sn?l{yN@RTk%VA6x=&PW9Tab$ zFiK3-a?cA;=0~1MBd3+6WBNm2WbJZ4du@%!j-c}=(ysBK03=5akCgQK))wbXYD&|x zaO>;$Rq%R4=vFP)ze$+>e$1Ulj|-nKR8rSrNY#xTlT7X9%jHJV-bri%3$sHQ&?mga z5#<}Y&SI;l!qCc?34||9xJV`kic$;!6ath~MAywPYWZ`3n)tT~LCrtTDA8@_GzTI$CTP{QeYzGmJOjfrRNRpnO3B(OV zi{@3-e9J2AlR^sYy9<$FW#GSdSi8A-wArC5anuw_%pgdeOOFgHNm8I-TwVoaa2OzPPa0(FHg(K74=Lffha};+eJ)?h*hF**lcmQHS4SC>aZnO(!T9l}6JX|+ZTsDb-Ms#M}g(Ih1#Mk!XZ zv#wONK$$yAU<9T%Bme-MW@f1m)Ms21DfC|z>NOQ`#PO_tu3A=FgtYM0Rb0s(O)KBa zXduv|TpI$qYs?yP@8-9q_e7PfxIqJ^K==w@o#uxo%T~6`tp3e2!Asgm{`5(YDy?jp zpR+ACPM0s?Z7pRzT70Aw>R-*@DF}fd#SEl-hw9KCWo4IWw=J}66ibb*B_X+znZN-% zQzz^=4i$tJnG%1yr9LUZiIR4H`n>#;>1LB4^&cr^8obcCuN%auaLWA0h*C77nNA-= zv+HUhU^7N?+32g=41RV-Obd;FD7)bD(M8N>zQV#Ij zxnNP=6%{E71epOv9vwraJqEUE{5G?E*xo&!`ej)SJTYS!TzHfoLKU>s>`+1vVzI_W zww(unH{f~n29%c~AkG{Biijg$hx$OL+xpc4elHz5hb8*&$MMLbwLW;maC~t{-nX85 zV@FoO$GQlb9dyuP@e}{_S0NZ>_RpP@hqW^1$)i z!l%9Tu@76c@DfmJwPC1!hoKiXH4DGT-8gSx_OAyVK}uC%(V4X&uQXWBX}KA z?WXj0QhkldaIB}CIqIlE7O8zOK_KwjU>pSb@u6>_KA!UrU1!Zzl$fOsU&As+T&~Rc z#eO0uWP*l@Xdq)0G|@{evozDjs)~m9F2pD&hj}(q{_tHQ#?S>i=^+U!2?W6=RCZuK zR3F}4`Hj`K{N>nCK~PC4MxqIl3`h_l`T4~rao(0y(BP8hyt9kpxvvL^N9R}I^*=I@ zv$c>_#VW^BNLc6$u_z}%$AZ1(+??BVAm%pfX(Z`N@Ka?`Izxyh1yLtVg>5lg-Hq$Z zceNzgx)!AU$RZaLfgxCdj1nXaB*g~XVJgiSReP4WBE$_lwaw4wJMt-$$Dd_Ny~tJ| z4wH`9!xDOa7@D(8q0~IljeZ&Vio2rJxLymMIxUM**W$Gl_zoF8MlY2yxrH-LT_r^< z(oHT6iuplYk+ur0rt26ZHTw-~C(ZLkWx2ZzJ>I0LlIR45rxhe(36z=iiHs|s{jw)9 z$V+#&PrA|;0#=kP=>;PQ8xtv&5GH%Ft}|7!7p#2!TTJx1-!0`F#FCq{)a9y5NxR(s zp9=X|7XJWA@6MTKU4?GOU<_N9XNwNF*&T3Hw1_zUq#c_ku?EMqoc6?|i;}Q5CB&s^ zj)OfTZyFsiUXkOycIhl#Z|H7K#v!CkUQ76Y1bPNDRzKsW$ebg3g1CK9>TAcUh~1t$Yt3hd{!AMJB4i?pGq z8Xyvr;7}lu0Y*m1B1n=VF%-l-FM5(K=0(%Y&HyBX{a>%toh&~>Y;Aon-b36)@D4Z zRXsE==Av9aT6{`4N_P{!8!YPsDHgMpvEjA$S$CCyyQW-da4t5q1O9T-kbSh)Tb||l zz$vwP4ndL648#H; z>Be~aRx58^s;%z}nu!ZYh$;XSVFO_MN=^eEwEOE{@VNA0*3PlNU3$l#lcsf;{WLVO zQb70~8%a>~aI7-VPAb|W^0MtR?HV0P)Nr$Mdq~gn+_^TE7Dnw27%oezRH&5zs3tby z!jWZ}<;9bI$`Rh_m?W)ANKqy*N{ERuj?NfSKA-S${529nCG`<$0)wtSmM%d(^_bto zUP_Nb?Lv6WSErK!WQ zSZgV2e8}ggS$0%C6Eq%tQWjQKI#_5gZfAz*X7^d%T-DXCMbq$#HarD;+K#K=%0BZ$Wz zjb2CNW0msvUVSw5o7Y}m!`@k|X(_2HYNI}2SnA{Rq>5!xV5?BByNS`X172i4?c9Ze zrC_H*XRS#DA6>q6^Y3|=FDAHqFL&-?#V2O~Vtj~#D3khd#&JHk`Ut1#ZdSwMe8bcH zc1o3=C38_FH0sUdg-1JLnOLsvtnA956#~W=-n%q4nW@))$51hiicTL84N3cfyeD>Z z7H#KDGj7hOU-pr>Ukz{T#w6R?UzY zfVjB5xgIA3nHBT_o8>HL_T`s=S{5WuIFTq&^1y>a9%Jg&1k|T4VmKri=3K^^rlgA# z0qc>WRa%)S@pU4qCyj_CzTm)-w2lS^p<0WHB?T}%KWrU=Nr+HARgRfL-L<>^TX3Zz z_Rv&<72$cHV_Z(r{6N9t4Hm3_roA-kEOl9HFJ>?0ZC4wglFVajm%rGH5rIs4>2ESL z*SYcF#@g}QH6_A{f;>&|>nS+<3G%5+G+}qv%eJ{sc!vQ53{E^_hB(NRNnDwedb!bT zUX8lTfmPu&Fv}f0IH8GZC~6@rHqQlgC8^#>lxhRs;`SZ5A%x*H#3m9* zcI}(ZQ9Lsy(X^z|w%|e6U#FQnx@#%6OGo-4L&)HL^~PQQ0LgzKmL0}W4ZD(dsRB_L zY}178kVgt8w6t?f>aeIUDNw%kfY#pkvtNg9N-A(R2|EQr_7)1cP(lDITm<6)8H{IV zloJ!vS4sGE`a;Y(`!>?`3loVjx=cS0nslz68KT1|EZ;efRFE$d%oN7}(#kFl=3YXV zPb)QAnL@DDslylm1f?BeJbF}mtE79mmbbesx0ybH-UODc+QU+mzwWmrAGL0u3Iqa% zlP47#a_g5}I%Vpo)s6$wOuB+Dn&ql$tUoPKNR1O!R)}^cBZ&DSS*56dct?M6Yze;N z#tTVdlB5XOKh69}+w7>|W(m%-mhCQ77LlxwHEC1iap_72g#!*JjXrvI>14eZ>gEyD z{JR8SC0SBwr$bS+#9aKnUABuAjmTiFqKg~fw0oG`es!%5VpGVe+a=wm@>{O{-5@1q z6q&?M1P+wWARUx@eMwj1;~LAD%(z2T;}{)Fq&U1~-dcziZq$>+t+~XAPnODVbqB)O z^K)tWaZ&km2q>+9LZ5}CZP6UBHSc&#j+jnx#duGGH9S;={o-?40JrgJA zTZDQ~#Oko`Px(h1s)jEkFnJGE<)-*4s)Cg!m(3c5kZccP2^Snc$(aw8ttLX&Pf#Na zE0LSsYO5#QZD55qbdYxX&`H%yy*^p$H3lzLiHvJ8QcE<|@8?}(Rww1-l1uxAKm~?? zcw4t2{qxJsrRBBSPl+UjbR2v#dbseYZq?0gt+R~R4^`MY_2biaJ(jbzOck_P>~qr9 z)es_w&S+U6!?4(-P}L0>V$w3G7xBKl%AB_GNocqT@g&LNj{(vL%7N{k>C~&CLcV=n za>-b>2a~W2)rnBcMT_Ms>WsIG%2e#1<=wtoOOF>z9efXloDEu#+m1An3RD8q)Oh^r zX0<^rlB4#JJr5$9sA{LCjavt*3bin+m0x{A8=}}-a~|ORef8nMRF4p(XTor$Ep+oz zQw%{jd0}o{oP;daK(T3Z2pWOd_*;eUs~&yyr8Kem`3P5~{TvS%d&?+hlTD5KGEch8 zU=)%`1e0!221Yw-$`Mgn*AtiKDda@ncQcn~Ep_$agaj z-q8pll?!8Hvqn+(5hAEIOzzFm33U=qIFSRdP!z@HL4Wsm4it@q4MI;rNk4@? z;8{|;4Zvf<>!X=!91$R>xl79GWO5ZixL}~Q!8T?B;D%29;vH0_NsgjF8YBFRtPLwd z!Qu)?+v!oU`e`UJ1e&M{nr%kt-^+7vauQnQme%_xL4O}~wGyCq5lpECClOOB=x|KK zgw0n~PG?6{IOuZHpD1OidJkm62E&rA9HbkWSW>avx5W0D3{_nV-XmB8t^!lPFk}o*WNX zS4@ve8}m&b8<;8At=$7f%b3;$JXnq^fzxgS1*m2S*tQn0thfbRv5Kacd(>t^jd)ro zL2g+4)@}k!k@hc%l6)#3(j7Y#I_8;T<#sNm3Q^TRvv9^LAHbo(QHT5xPw@z>J#FiNNVx?yGjE**vw1iQq6|c5{*e#y0Xo$nFujVrC!29%`VrN$93UU zdQTbZ=WPqKtA?)1Uvt7zlZGS}a7l=ilaE&2wOu$KSk2uc&UjB%vSu>PMUGU|R^Yhp z1V3p3DJ(uy?jCeX-c@Z3z>6^4C56@4kq--`6c9mAg-JX*`oY?j4{-!kD`fk5uCy#c zpV~Hdrc9)cl$eyLaU2u~qj`wrOs&;Sl~bI$ONPUO6~I zPW5wjBnyDe-3_!iw*?mIJrrux9B?&ipN8!PFQ=S`){kD;@7 z_hN^0*vl%j!x;kGNg~?vTivE~cdwt}5Cm=G@zOBI8b7sAwq@5z8z6jsFe;w29%IFE zT+u!U6-WXZ<4-M*=f_R52GIk*VMv#OEvhAgU(!7L=ScMnUZ@puwzPj_-Ybsm7MgtRt z6kV(~l4!_v1E!;)9)&Q4!)Zcd*}{5wsYGF8kcxsOaLr;;RZxHts4c`+E~_%TD^|fL z&|oTPzp!3QmbL(eyQVl9UOt2f6=@w@^x@X-mwH&pIiu4)Zm!Gur>D?UQsyLyl0jN4 zl`BluWx)$QBRLm0FA24@9FTLIj@Vm=9%wET9w8#)Zr$)xW47p7f#|;hS+NGj(J!29_ySo#JAEAY>*T!)YetOZV@{9@Wbt{{VD` zNE;LTMR4g8?wXnNJ;A-p?ALO;ge^!Kl#tm2tR-DtF^^RMyidEx@AOicHTqeF?4GZVr#Cq*S7`Bu(Y{R1+oanb*m35$6Iw=DJ1IvNEI_2Z zRYxtMs00BZ*)TSK6}0}4H4r3D(eLQ>r%GZpNkXY6Q;EVqi7^`^ZAo@P=a5mM zWk6swD-?~RX9}iYQGS(rxzP@};=L||1Fyw!>Iv#i4OSmRJwjAc7a}QDqEqj73>wDc zg%=sMqX)+8Y3K@CLHN*dd%b@0{{Uld^3$|wX=>ZRz}i1rNn}2hbwZO70~*UXq$(aO znW$N2MFwmC;VH z=0>Z<>GHi?DN`HyRHJIBUBBd$%yk!yND9Ze7bUy#YBQ^1W4s5-Pry*2JH38QWe^~W3P{uzK*X6g)&mt)J= zdS&IOlt+kSZX~U!td_E97B-Ry!lu&NZoP%B-JWu%R7x$b4xN&Opb~$^Se!WUrfxDZ zY6h#DQZ_;zD>!0F(vFyl*m8$Ib?X(VMZ>yFB{Y8VGGaNm2!M-ea}_#NHHi4!aA@82 z()L@&_|G;y$qJ@_Eo|8FKRrolXWn$uI~m5kPvZ>rg96FeNIzw2aePj>f{hRpOG^?l zBfXD)SuWnYj+Rr?D_XpxN|+?6pB&E_ zl60px3rkZ=LabL(Vn`{ipzaCOj$GR;{m(jlicmd5Q%`RXODEPPq>= zV(pD%u-9fda5>^KON`?6btPn!Ga%SyNI*~p*JqEjg*Pa+vC!qoQj%6NTGXID;76r4 ztijg)*ho7<5(XZ^ef3b^jQ;>Y`j0QD{+;zBE>}JU)BJY>n=N^mWYbZKJVqIwv6iKw zWm0O9gT&p>mdV@>WFASD+U72IZnoJ$7HTjb&CDAN98nJ2c(0_HKa_t24TcpJ?y zQPU?>B7DrBSfWRe83#x4X+-&%SFBZ$B_Ji8CJ&e zI3B_QBSU^m_JAtg9DfO^A=Gz_q-~6PaQ!MLK{}dp!(!bu&ayC~o6D-hsu6^16w0iV zQ#o$QEM6)s9ey|CS#|g2UN-I+LcB>Nzz2$ah{Sb+Td;hj=vK}L%ZEL6TloGFJ|c52 zKSuHS6z>4Ew)fJlm=uXlg+f?0^ee5oi|$*O!>*l(gdeRsZ%V$RX}U+$>c*kUnXXu{3FVqk(8kp+TM4P! zPSrHEB*g4B5ljbVEiDGzmVXmXC!ZCOfIB2G% zWK@CTFv}G4h9YK=?(6{yZSmr)zcPJ=!WNMP6k!B(<2aeeXH^B>Whh7>8OK&TeK-iJ zQ}l;jp1m!4ug)HXbM_e&_*OL`#`4u!sa>vC62>@Vk#53jbXB$Y86j^I%+bu>Io+#y zf)W&PLz^aelOuul&J-VN5#X5OKMzVA{{RrrO*DOZ^!JV~4}-lXX~QYzn+>U^gfy2? zd0{3qxWy_0q<7Z+_zbYRQ%Wra6a~Q403aR*1L%6F&9Ze59s{J|Qojx!wdKyVbW;JT zlBS}g7r-N2yN$eyAd%&XZ%I&DzvU$Ymi91y+!Ls?kz9tPg*XPCTFjDq41i`wM8z?3 zw;XLnFmaK9=*QiS6VF`PHzE4e>E1WezM5rRPdQChQeF&AB3wTX!!g=@O2_g5QS<;CxHtCVpRzw5d_gT^0q=7DkDfhOdL;9 z1BXZ^DRua6WUjMx`zm93kF9c2)4?p@QQ_2knwp(pr}7$I(_NZLSXrAzJ8l36gUrFF zvkU8+>zzI8>OxWwR6<&BUtdzifD&l5uO+@Kavm)Dp5q-C$<4!V~fD@)E5 z=>tdrlD#Su;wh2RClOO6z-8+udxVgsz}qr$Nhi%-%4qb#={F+!!t~pgMjM^0GUh4L z9D5n4sH8|uY%`onIEgTc9e!GztS=mpNAA3VocqniJBg56_K}htt=Bu1FsBryDIsS| z!6mhcQgoyg6SM+ClwxMGOM0$Rk>-|}jk!{VzLclCfD-cnCH9sMD&a8@l0d?%kD~o9 z$!(ESH0F%uSC(+-Geq9q$}a`#a)Ej?vP#4wCvlN7*VilUOZA!MbQWt@o;Xtp}agxH?~Ey2cDxz@KW ze$CL3l>?`{Af-vi0v87lcG?eKZ!^|+NxN|hF6dH1l(KcUuu!0+kt#jpn+#XsRe+cp?!+42s{Rt|>L6 zi6mXRd(J+{Hn;%Yb`xfWg#KX3lcX|?Ite9M1Ns1H;XSqHF(s5n$u7A*m0W*`m!+z1 zgXOND8d@bSG8rVggs6~5Vn*e$(CSH??AF_G)-IWFtgI;* zp(%}uR>FO!3c=3bds(^9vSi!718GZz(hyd)9SI;3AnchC4m)raYo47w7W&@F*bhZ| z5tuVXQ045wQBjSWNPMW{k{D!;XsOB<@}pQH07ex<`|P^kP<`&}W|uI+9Sx=ESV>xn zP!k4BVig1{!8n-dub3s}I{nbi8hSwhyN_>^~Qt6;HDXB~-Yv9HLm-Yk<6lkL z1-v06`_Z>=@9C%938t1xc$FG4H}0ppUB#7IfhSR;6MJiNI750gjB7V{b)o`HZS?l} zZL5d;HGNxAdPnPQS*JEtNk@fOQ^gf?Mdl{iDWA`#if4@_k~&#`NfgZ-Y<9>SX$hoK zmlV^I*^EIRB_tRkQdW=J0I}d+lR6Zv34vLQpKgKQoQT<_Ax@!EfN{ZT(xQ~9NkLjL zS~V#ksW1qdyB|zFTu)IQEUm2RUMWdDIbR3Nc~Y*PYO29}D;>onsiVYasi=uQTAwcO zjP450G+~?-+6N=WGEma3NJ3N@?nzRgQ$pR>4z;Oqr48G>rq!qT$qG_P3KatHwn6=o zzCgZhVB9@xc!ebm{{VNjVMuY5p$b=cyZtK>AuX(gkY;N)R()f2htuw5{{TEV?oGro zOs6JlOl}Nc39W2GilR&(4s5%PZJkE+rNmrs^PVub77F9u2Mpfbq4YkE@5J)oMyDNd zE~&JeXNXx@Dnr71#T4p|DM#$^t#1DSXBl?)G5oo!rrWs|g@rQnVV6)YUKf_ql3=@T z4xa5QCNU*D2_ng#iEm3W%%z2N10djdg*>%bJuX{dfn)0Q8Ly-G1$JY|^HXL@ zT$PFBDqKQ3s*1cie={mdv{c3qnl`9hQnEt`Xjz0#yGzIol>%CF-r-HKuuE?;4x;)A z7Nu6~Ei&dPaeeNjvbCFD@4%*zQc14vs^56tLpMQeD($SnZImUqk*576)$7rVX4#a7 z2yq~|lc*&GNh%(feOF8BL#&xYsVh%cNB(OldW$U5S0wEIX{4JFj!7a%CL=-fKQGyV zzNxB!{{VAwl$64uOtSGxhkm6bAul_OItp~S;R#YBMhkT+PkA%0`)(?CLoK?q3PS$? zn7Nju2FgH=@hqt!L;$Y)y6=C4h{0GWmv2otRG73riSTN;Op?`BXN=V`9(;tzC6Zq^ zV#>Q%1>Np2U-<2X!zr|FY%bISVLH@+p7lg&c!>!Pw~zTS#icf~5(=eYYfrwfi*vn> zq`*onEfe+(G^ILZq{x#VAW!$>g?i@C#5zuhRbW_7HG%&CF{(K`G0?$RPauSfOxIsE zRYgnhRzE(YZrQX3QkLtTSNZ3qMqJCbHw#vl|dP$!+g6B;aU53j=)EY|$4C6%x| zl~oADY2k^m%q)kbSc=lgEENqP-0u?r?fa@NW0cqhcuI&OX6@jgAwI~&=BqeLbN&^#BXL9n4mgT#~%cV@V+ifJ2r71%*+@$G9)*2+K zuz0~yQ~_1Zh}BlsR!QZ%ue?Uh%^(gu4fMNPM)1A$;p<6C5+*&v4xdhrJ1ZUYbr;@J zhe_w1m6nGOc_(Myz=sl}$8mNy1@{xF7X9ISY2nJa><>sY@Q=Xlq;|||SFH2;()y4Z zoHC(8ENrk83PWlDxN%`($L~5H4MT2tRygA`^78m&S+}|EXefcid~0b)a5a2K(*9HO zH?A$!3d-46W0Fk;CL2x&ElhpTsi;#T>8{&Z0t+j0;SGt!T|zg4;(xhiC~RUd?_9WF2L>do2?#wC{6R-hF;)KnF#Su-w4lXPnEgUw z(c(q7l=3MjmZl&_%ZTIJ;GN3gk=;Q1MON2EhQo`Hom!RmX)x2O7!#Vl^)g{X_D34zSG=fQ@a=-s&rN%_zt1s=-BDJtWgBOG*%kv<2Ns`-3?p6dj8q%Oj#KKdGlqm&;{t#VV#Bw}2 z>Ktn?M^8N-YQ&?7@fifHnR-D5bRh&6G6U}_4-1zmz{)fJ@ua+bDN}231sGTChzd+c z_d*C#Q$8e0qya+byKTv>?v1Z;a#WWs8zeR~gLs`yDs}ylfju}URXwlZ{{Yr}GHgmp ze0MI?rV_bGR7(|f@{PHfg3!o{w8rYCz4P1tE8pLWSD6b#BZu+ntGV>;(Co$2+>z0LO)=th z6}X;G>b+Xxbrj`_PWT=jEljOT=F*8aMy<4#2F>4Ra0x<{b$S~_1^#JTNF+~iT9qeN zveXmdUX>`VGC^|PAQG-|?~e2{oLy$Q*=@u(b(ABzN}^CMo=OrN(&m{_5+I2iHEbof z)aOexe^vb>VtGoF7pJ3^rc7I^ZCO<_hz1>sV~bA>D0r#ErE0Wcq+_}pTWQzbPi*71 zi9^n6Pz;-ZnNpAKoNnC0LnumID{fS-@V2zTPKAOMGwwcnZ;)>bcM54s2@K^r5RtFG zV$`imAx>#5kfIU+;65Fc_VdNFM+JR^(#5zJ$-MR3U z>vy_QA!8FauI|@*9De@ArMAyVeStT0BS1ID#YuQ%u$Kyou(Sr9fjUY>29xZ?6KD>v6jVKp`Zv zc4JDDhj!~_B$cofrD#w(R=8MDQ)@EWn=}0FjLy||iD@ZQ7da{xwzP&xT&*FL1glPj zld43iM5<#74m~uAga}vAQ7uV0XQ~HjZ!C2 zk+ekB7W&AldaU7s;xVa#s&EKrR0Oe8J|l?BwRbTjoyWO1*IV}(Shd|++oa?BKTK3l zuuq>8IM+qDNcR>`qGwIPOzfR3FrE-GkJ5-XA}4tnX^qQYcHPBE3IGds8URTofP6b} zV$=bT%69R?Y>pUl+fdf<9c#m;oA$>Ptk?4QY!(jWo!@0_bP7B#VlAe;RXT@G-UHXy z-BJ5Z_^D@yF*CrWRy9GhY+xIN@dRp4ngQW*MfgPS0P*9GUps3kw`~z03cs&TQZW22 zx~)=ou>P+@2|ycQ2Q<4Qvk5|irI;vXW8Xk8c8)Q5zU z0$VWP#$E7F{J&XhaQ^^`N~Z~*$RrRYB;o*=QhdpXJyO>s{-*kmi^Us?$^AXjNajZ0 zAajSn8Mg|t-7E<#bsu8=!frfVY^g>`WCC>sWBGPcVPBd&1OcgJB3#;_v+9rDN#-E_$U2l&yjulhH^uxz2w?zQ!cGvIULv13`*3<8ckK4~DYonEb1 z5~6~to>h{LDvBnNW}T4665y4w;Ga5u2y#>cpf@Qh0!E_ai3BVy0mfTe6tK(af)G-b z6q7jik8 zx;s@c#)SBlC=F6-C8DFOC2BBuu_%iC##N!Fw1gcesYd<8lF34lmYiFp7SXR#feO~C zSSfAR++TRcm@(lBac?N16b*ZI@{yk#jQ;>KN_(v>F9c{yt~Ui2DrHlnGkM8Oj9O(w z_>_q~okFPT2TQUC^BmO$MlF}RcTtLE3W%8~W~)q39>Nn6smDKiY#I6NmzEF(EJ-g7s zOK;yLtJIlwEtV}V3n;bjN)+OY$tqfqRpN6@LP;T4*I!J2n!Rb|VV*kmhE!4Gb$Ct{ zm?F&BZ1clNeq#$XsSR9}DpBKl%5A@*rwsd)DN%FA(VQ(Qa_QipwV@7|!d(r5t93Hk z9S&=7kIk{BS#4=r*6L8|5R}md>hH#P*`xmemC9U7noG}Hn^#hmIpBX;Q)xj2C^YQ& z-Gsr_CkigTeCgJA%oy)c`e)PF@QQcLSwp7zb1uJ`M@js~TAIk_n!1{xAQPk#2?NzZ z{!FU*gze%sSxU5bifJI0M5x;M(yr`k3(%c#;uM#iN|KJoyQn^`Fm9QCBzY!}rzTXSNa$#>m@334 z=4DDR<@TtGnqMk*sAPGJo0QBYh{|@T922J}Xj=!_X&RBGO#<6dp`@f~DL@UZETv`) zheCl_B}$o-DBKq_z0A8ex=P7$#uS3D0!zL3fUP>v5DHrff*L4rAZjGhqRm|u=@xjz za?ee=kt)~IbpHUWRJcwE)D<)(s63QXyaXUcrxNrKYhF*KMwm>-{n zE*Di#RN_L@K&v2^+<+3r1N*ARR*e32NbZo9h#_hzX|$oGg*ymJ7Re5M$XP;GSWIbk zDsT-FuIp|k#_^Wz8fi+jXD?Nn-&@KFxlPuKg8OSg(+B{aKw`gHDAD3{fC7qfB8_vu zu3o2O7^OtH5r$Z$d8%qcQ?Z(T)svcvyVcYNbV(#7nm86HyIws3-W00Nd=SpJqYSaa7@^OsXG z2{R6O#U{nE38E1-MO{nE=^9)lDjMZcZ=$V&>Oi*yUD}F)QBjDA$KFoQ-BI>>8na{a z_UJ=M60ImmNYt&Qfwf18#GWM33t!}-sfS~zCR5vB0YI@{z~52e1-y7GYEIc4I`*D_ zO2PZI1S<$Q&sRL{q|~w1C0ofOY>{5f#D-$d02{1*?{`fBx%xP66bR}4J|46aTS^9c z{yjZ7VTEyQFJW}23h^Nkjp{=dx!N66kQoPJZY{4Ym!>9qaOmni2jhh``6K)ycw@GD z$4DDGv8ky>^H#e>6G?Rq8fX+-urGZIfvFc9YlPxj`nT?af zZUcenrkSt`XR2y3CHD|mhBkM7Pr5YPo*EnKqqi2Okx4P2z*`>b$3cJDZYNdD$m^4YW7Fn1(W6_s;*JA^3}+8s2ZcY<<+dAOb+C5x0`5>5 zh!-LM0K{8UpzW`I7q04Y^y9P3q9|6z=_))@B+Nj^*Wa?S$%BCbSK1vIvdSU=S+5vL z3DkzSyY2DQn-AmipIIJUdMTGTQN#!vWSP^$Uaj}$qVee?gdm0W0SBX z+-vNxw!C=0QgGNr;TWEg&e{(-yQD}^GLst)$l1bn?b#Iqd>~T>pn;0T7QbYEjaUM} zgQ-8^Ce{aDC`>*gCcjK4+lR7s71MYYR25N4`4Uq* zW0BB$xKNc_rsM#mY}@J3dbZ3$_kvLt)IUw1_m zT;vK9JwqP87<+pv57yHVZ6X!JROzArh zuRJSa&qRGd=~hI`6|~(%%Ms=m#35Lckt8p%TS#t&Yc$b3UO_v zY287;c9UfYhUK{G}AgR9tD*tZ?5g~@>%gR(@0UCa%Fj+<+CRkP3qfA$3u^y9u=tg zN|XtJ2_yoMw8=YR9fjsDqxAm(saOPkQtB#9nACC9$Az2@K+<`tvL!rotDUx*$aet6 zQs&z5wK|fhIeSdOPrdYcn#5(d;($dw?XF{Dx9rNs_-9#y*q_?SLAt4kZe#*-? zvV7QBk=+uK@8$$2Ng%CBBOeEg2>_}D;ZrfLsO8+D)EsvU>K9Nxa*^VxLxQFf?r9>L zGrYY;Hsdgc9hb2K-WNTutDL|wae?40hG zt3nsup~WdJwnpw@X3LhAS`-QoeqI1LQg8tajXKw>Y@ZGSwCwe>g4E5Ku?j|cqBM-< zV49w2ofpg`NWxROH>ROT2gOCWEZlOdWF;$1D8M+4urPrW2XDU`&1~TxnP?~waNuNh z!iEQkkyPQG;iXJSy!rBl<_PuG8(TbhVdA-pfiTH z(|orovdnM0yT?Vc64IBblz5e?IC!UosEkU2VG*=&pSQQ0vA?#rAq|I6@|5bCTjVSN zP=ukVS#jlrr6os50G%oz17-a=^h@c#9*d>eo@na4s&TqJLYEf}TT;p?>0@zC1o9)H zks3Qk^2xJC_piFKGWc*!L-%e=ohZELeGT`r^E3dDb`n# zl2Fr3ONEVJXk-B_5mYI;9LVmiCON&E^0yKz03QQpQ)2SGczY!$hHc|U%nJOlTv&RrEA@bL~)Rkh_H{3^k1?+os zp)D@EFojV`>$YHO+3?(t2fqzcrCndXQJM&34H}yRtdiIgzi0#DpoF_j&Hn%^W{V^r z6Uvp2A+#Jl6udvpq2+^RW_mgJ*1aCEbI1AD>!g`m2}Ni!>IyROs3uyC>I=x}gV4dVe>O zoF~KUYcQG(z{!bBr4lSYotEUwSGl&03fprss4NCMoUxePspKj&A$oWcxcfx^02E?6 zVv$~1t12nCSDN^#;~VKKvAnZAgDEK6aXK|-T}{f! zst7maA->Fqt(t#iN>0w8HuOr5Rdg%q*EIaS<@JiN1ueduaKMzSr)VkJTHbXQfMfkO z$8ea{r1GOl(*4&^Lxd!4u>e?U+!JznjoDkDmbz_yB!kzt35<5}$I`lyoH6;UCtKqN zI*5f2TsBN~(FCPP=Rie;mdF@wHXZw&b?iRA{K(avKR!J2D;TZ7SefAhK^PA|hpkvQ zpvY{hVHu=o?z&P>t)kXCG0H~SUq`8ipJoNJxs=={}R3R#$5KWtXcQe&Qi+NveQu3OG8nKRZUe)wREx7Lmcs8_%zX(L{hHhSsQ7( zlW=X!tk-{gKgl0@*;WBgG_|1VvTTh=B`N@r0UCkCZLFcocQbnP#!&k%I$Ll8l^6Dd zvjS2?{4v>$J0DEmuzLNKYbih4Dzi4=IIj9iqlVyl+N%z$P{`83EVTGaK{`gk3&u+Y zAxRnzGnV$(x*2f~S>=mLl1`N((Uh$wAi+X{fgs_sW}Lh1<3AGB)ysP%q1%Mw48b6; z5w{u*>c0j4s^pq>&AoE!R!GVjKn3!#d9jFvOUmZU6JYhtM_UO|tc@z7sL*d>6wWO6 z@oAf|6_sW8_fHcY$hT8UP8g|cb4y_(`awh;l@qUZ+_rqPa`P=EAgjERw2(iera>qC zV}(G$eKmR>>Ao-hTB7xkQl?T2(PiAbjKfIsTIxTUJkipdc)3ysw!-`vy}g^ocEEkS zg;HRIIeBgtIN~6W^Fj5ZbmjSb%h0>cDgKZ`qs{^SYbJZ?=Rz_iQqyJ*r*&ekDwvkD z52&Z8!epeXrhPtUnyxHbSmi>&z2wvpvBJ1uFv~UiguBU~Rjt-kmR?M1ZEh5(69j*( z>?2_Wq>Mo|m6QafVy^XMHru&$Z5nx31tu0_!U&lF4O<8TXK5k&)FWoS3gWlg9+4ML7Yy*p#2N0l#i=A3S2_{>8@aSKT_Ke$7%w zm63)ZNRF8FuE=J#PTyL%-MKBgq@5}XAf$*RU_WsYh9DCXBDMq`z5f6M2pF6{rF7?U zB(TU740iS#w^Z0`+TI+(A-LP_cIL7E=)8a4D;)+wo+=KtANOUz;WMI*52P<%--b?d z>i!$ie@i)G@^(L+*ifXfWlC%|3aKDhmY$xbcqe8g*}S`{0kqQm0dHq#yU_KT-OO)O za)v>3K~jkj43x@1nCqaXZIb3Tto~-`>q0S-wJHY^0+Kjz+W^H`CsKMZ(f+VdK)qba z_%3k%Rwa4}F`O=%uVk-eltA?=%L_;qcM?F*U$-#>CeH72sZFKJw#jgUve{6Wz!e1I zs0Z1?XcULsWcUdkB_=(8c0QF_-CQ1tIvpd`bsN#{D-|s`W;NJnPVh`hgp@yMRZ!GO zyH9bwSJ+0J%8aVhInPKI+rolQ#HsgCx&HtWVJ3X1)`fPexw?>xks>4)6cy~#COW8^ zkHl~AQ>T#8w?!=&d198HJdJ}R?J8DK0jW}s6q|M+>)(=s`!(M(HGelVhx+TWw+vu{ z53LGDNt(Dk4$nu8dqy~oGqV`tD_0!d24AVnxUBg+OqeRwReXZfs1*jB$lgGoX&^er z7jX=h{l< z1cF2oXujx|O~4Vh;{G?|d6mECEtH@0hTLO^Oi{+}UH7~`{L z8%pdjK~7?t7PKl;RzvRI@v`mlYwPVI+G)sTw{;l@ZajAJ26{di^wway+z%-mIzC?- z*sJip{-b)u{5(2^=#Qz@68x3{Rr6!ZbxBf=X+CLWgtgSk4Mc1d9T#?^UPxAt+>2Y3 zTbOkS@0lOp1fL1%3Q!aNF~(xK5!-G~jITXn{Eyk(q#=9;qEJt$+q@pBwT~1hciVgAPF)+5@ICmCOApPI8Ao< zEwD~iY}Kj>P-(Qb6s@ErM4yo0AW(l_M^Kcr;8c$B%XO-N0@5lLxN?!-Y2FWW_D8%m z7vhw!86rl*!=If8vs|=ZxZB89hZ`mo5(z0dDGCQ_NZI`ph{l2}T7p!HT5%X=unQ@Z zR}6m0wx->I)8l?0vY>ILZYK;nDXyESy>98&8y+RnEOL4Y=!uxnyq;|hP`1e_>S$)& zPcq7;*JL{CHQIHer?ZvDM_or=ofv<@J(Lv{K;pA)%aa4q1ee z8vqi*GRl)|w|3QU3sh>;sG2d25Lo4aM7i-r~)&|z9f_f#pcHJ=vM zAd-?uB#ycW{VM(+XRTR>`uouQ&q35I4wSmB1ZvoJGrS-!lVR1w2NA}9NYwJm0KKkw zInMLtq<&d#lrBM0)RLV89YPMM!(>epZbt0c+PpI&?|R3GHcAwQ1;|d7gCb)I1Z^~A z{aJd>$9g}~3H=rHy9~r~)L7j_6}g^#N`ypELP*W!_M21wz;zNj%FN zY4*QjLXdG$NtssMPgh4x9dBNCrtcE^(tFJ(yOH5TdVnRd(nbYabZm*DE$N3O$DFg4 zCzz<`TFhrH*3#mTh_-~1HIOT`P`AAzfI<5}=x@if7sCw+z$!NmRY7I{!Bvkcp&Y95f$m&Usvu8BhQUqvP!1uI>`_o$4Bl6|Utxho~w8_Em@!0mUn_JB36Y|D4emK+Bh zKp06MY@UhWPBqVmnKrJ;s#neauezP;6APiq{+%lDd;3Wz&IZ?pAc8^sXzk`o zPB?xeZ3u8ni%Cr#Jp?op?qad6Ys)NXg}vo5M#|fbu2?nuA7>m~D{T5eGv;QKHzQoU z1sJ^1DJuX0)G!|y_1jJKIJJEqAkjtdJCsW*g_MA{CDE)3>Pqdl;n?>a5Fr6cpWQ@7 zP-)gdBF80VL#n|dosBM=)F4?l#P<%WO@is{8u3y_!OvA{rvCsjtNv5wewWJgt-r}1 zX8!glUa75~+yYOK>ulrkM|WWuDUs|^H`Q@j(ULQe0t^l$dk z>%KS{0R<76Zpg|~AVWoK2_%l5uD^+?(N2cYR3P+hGu7}E1z}h|A&KW|A3qRH*h0l! zTF6;E`l^s-YG+IDB?s6b+?KKTfmT&;q=XPaI;05zz#M&e(K}^Y#+4BeOcErVV*^GS zN_v4u1X**};NcmXF@+An7Iu#p;cacaU&D@o6O~P8rNLnu4u^0i5MO*VOiSZw8Eb_`% z(bLmW!&M-pI~q|Vt27Q3!^EtA$-TolEujnVDIvI6q@oNAdZ!vOYU#rsDf5rQlo{)$ zvt!sX#IYFy)yKQusHKIGM*Y!?qMPost=M0;X8!;vUfsA-xcVrHI9uva$4NbDN%>J5 z$~{xgSRQ&@XAGjlDDi3;*g$?xFv!}$Dyy~Cl--s{f36?G zgC_p~zLYrADjfx}!>kdAIP}nK>Jq0W^#>x><~+BSFuII$D`|?-Rz)e2h!+vPWFk3H zswgUCAQm@zNqxuN8IDc~O`&OF3whM*`$$rJL}RBEkQ4^N{6l6kDGlawlpPM++o=Bl z0*V(03{t3Ah4C9f8!-`1of7JWR$RgEMa2!i2SDH!jTq2&4X_l?vMpzy?nVMFH zsvzuAU^TEwH^xeEGkv>BxL9!9U275&uKQqANPv(CF|f>S5NP7xIMW3d)@e`>72HV} z3<)bFj*&fM8Zi0KK4$)z;&?w(dSJK?A%VSNmjui);1tl*!BYzF`5M!G)L5M`_hgFu zWscIs&kN{G#zMhSL3ZRRB1%od_8;OMDLo@$z`>*Oz7IbrQx<@M;vbf8XGkY%dJf*4 zYnBt$yj!XiaA4UZFXif7^}b0Zq8Kh6w3s@vBFP1uW80U&@(9;Iy}igiP+^ zCl2xcq2Iaq(pB$W!&_Unj*)KO9(Zi);l`hGS5&Lz$rEDuoLGG=L~_p`n+6?C7m~$y zJaRxG9#!pPmL%Th*3@5Xk+8t~oj>C|;g5YAD>`-2B`poVYe*jfM(5PFeya56=|83! z2M4JXS+g5T%=4Hejs%9(^wIekZ3(9U#C+N1Mpk9rbSC!~gX${)=*>1j$ykIKo72>ZX(%d?`3$?7RA{P@BZO0- zQUUG{1SY`STNjY~;Qg>vk`GaolNA0{nkO~P5o+a)lql*^LrX$}K$1q6BhZ36s@ij| z4VAjb>(8a$mTK_PRfA<(Idc_Ne2pk-DBuF2nh4POQplntj?$|sy|o$|_UYHE!bxUX+(gik39vr7#j;_3HGbcc*Vz`MW6k+RYs?>((D8 zPs-hOu93zuQ4321^KLNVbzdu3O)Lp2D#s{?X;4&c01ir-V%K`PFOruG5#6_eICN~r z4E(AYUSyj)zUk|3?5SFizVXiy7$o9gPgFtMLMN!~jZ@NG7aYQIdIuOS6pu_*r;&Wg zCXg(2s`1&I&2SktDyiFB@;S{nIqZ)7AQfpoBrixJ2H7XWsC0Q&aJjrq<{3kabP0_L zM8=|GA~Aw?@dO&CY{6JFXIC)Hmxg6L9;%_5D9}i2CSNvbK3)~pq$1s#>@~0#;h4!? zRKu#{U*Wim}@dD z5z$ahBy%jG5;XbRaD3gdtp5ODGb?SlBsU8#T>QPtm?}`xbeKGPc6rf8_UCK0y*IC5fQgBcZc5E@WjJ_j9lRZiFR}9251{;D!hGGjlWp>1Hgj+ zRaU9NUBrMJP@s2S=2PCHOOEk~aDzP<4m>FJtj)Z|p7EC1#9^tRpbo+aCL|mWwyN$P zuJu1H)Jhwo$`l5pKy;* z6efe|-z>t-T2L5mLk|tJAdezaeY7|9*RGkPHnt_w{;OuWaEct#sSO@9u*V6)F;Q=l zsBa=Q3q?}fV5}qk&4j(<7g=q)S#v~7Df3pPW7nvk(v^R2b7!RvT&x9bDF{R!ttk)> z8U!oz&tI~RX~eP)eZ?_aEa#GI7w2eRsz+9M8A*^hAzn3GHPmgAHdkKv-EZ3`=v?5jcUi=?dcU|bhz}My}d3$(tIUraNOU6eDz)xSBF;56s{r+ z^WpN@{K@5aHv!F>JwdvT3*F1D*4Qd-vS$KNl1E6yaiJP-p1Wk}dDKtzTv}m64WUC0 zkyJ%hTb%GbezPs-n!5Ng8VQ;@x_PSSV;iU!SMys!d>Y-2$9^{32y8$~N0L%L0-{CS zzpRH`aFMoFv+*>2I%SDvOdFzg@YgAyFyl4!AIj(4?eg%z7}g|g`WdE`)m@1H04A1A zP55@&l7t?a5zq%8Z^DIb1ov`rCL@oYCYkE;9v6I|F`| zyRPBm!FK80EH>IUDZdUlm>UnuYUur{igs-i)z#O;9-8^?^&_Sk*Q8mSFmyMnbR!7N zSS?(bZEYC^q7%m=mZ^x1WR1}Iv27MA!(R59uC!bHl4N_f-%ogE=wbtAN<-lLOhOjUc=Goif z1E`E>_T2*HrLhJzFAR402aynZ=w5>o#5z;e32-bLNact-#RCw|tjGjq9Fgx9Cu;-a zZyk6g6P7>S{{RZM9k}y>qXjRxTqnp=pI$I%N>OHPv$Ynqq(Nn|^5koI^sd8FL9=)= zuZ{RoylB+eQg+B6r6#{gB2mYu-YN!1>3Gdvnsa7tfg^hN#A_-7s_%?JL{bKbA@{Wd zaPd{W`AnL?J(n$D0-~jL;F!an6w3`4ZPl_#C#UT(9>GNe3(Z)^M{~sna*8&Vjy7m& zB2?az(MkZB2|BY!V9VcC2frfc0Uw*p6=odQ!=Ngvu#S56j7pS0^I zj+~BMKbW@%_?tRUSlW~9_k%Q^-N_*EU%6xM9=k_Tqw9%bxE?bDM~%>oK`8v%nn=Q3 z)=-C71;^=0?Wh{tk!8UOJ|QqQvFHbd|_akdb-Q6rvd3&8tSkg`(M zl9$kVbB|{-0T(ad*#{D&E!0fNfdgp3@feMx)`}FA90*VVK!eU4D$BA~SgWh7%v~tV z6)Y;^m(8S}R3t2}JlGgSr$N5qfVP*nAF#SuZ8s$#DJ1Jke%L!eCm8eNLEPQMsY!_` zQb5OVhYxH}9nxvDT?SVEUDO&uOIwCLVpJaS30_A65?9@FfZUJ*>IZOnIlZOmQ)YF< z0k#Josr+cJ>44Lz2|G$-iGvu{tzU?idy6&Z93ujzTuz#+8OJeMV-@xCP`X=JQ5%S@T4r*t*pAyq4uSQ$pea%H4{A^EJsaU&QSFeie{|69$}`- zc(rHqI+}FHql+ID&|$d720Wyrq)}z^YBsG;x;8q?`b(ZYdA+91aFnf61j4kz6M*V5 zCVFwF*vQp(nIHl+3_v@2XA*cwq1P<+7peKvG1JswSw|O*D5a^#WW)wMl9;Qfjp38c zqYkYkEC^IOpd=ll+!$pW<8yL!H{PIq#t0%$0yv~_8zzJIxhgEub!dVDK!7$GjhG%J z@uQ8?E}3OsmgU-N9IZQ53ffpJ9;R7jnxd!81;0%-M(2`9+_I6n%0}G>GH)t>TVSb0 zN{mS|qwUA=s8apH;>?JH5x_@9P>15-M*URvqtf1s;8n20T}gsFEVH_8f_zsIv_wY4 zi6jxlqWf$|YjP&-68`{7S!_WNNgZldk*M$(Pn6d~%VtuhEKSmaUT!;=5LOb% z(o%Mr?!YoNYm$;lH?HoEb+4hGn|g5-Zf8uzhvS%aWmQ}?H8he5t1D`nS!!yf(Wj9j z^5aOo_KkxukyLF^K6|_OIZ18D-|rIgmf%P#z`#2;D2V|}6A=OgPFD6uYh!bnWx-a> zwzb9w+;%e7X*;q z+fq%n(DC5+fDWOK&vktysj~6^Zh;DdniGU8mfAaF+(qxbVDMI=Hpb3#^37P_T)mP1qeQ|v&{T! zpxdWzwo+sqa2)kj#Qq8x=3pM84pXOS;=bDoWTJ zs0EcBz)D?hQ>GULr8?E2Nhojx_irjn7O^R5WKO8UKnv;xrrgMd!pDgTb3vUXEgBqY zK$4%eXa*(>kp!4Fr_pY&H&8NHLppzs$x$v{&Un6N$dyzQ!UTUUfjs{J)vQjEAq;fu zHXceWu8dYvZ$9<`R3gKo>+<2%DJpdhrD{}x;0SKrNm2Z}N>eI*Wis-V7Lr_mxKwYwBD(r?cwX!2Kv>fG!+E|6`*VJ zsFIYmt)!_O^TwN_mZDtmv+cXmD-&#oVh8t2t zf;B5iRw|mbo~38l`Zr5S)V${u_||UBSn^}iVbZ|VtBPWDo@E^kJsI9(r;8~{1a;8c z%c){z19JdEcQ+*v^MHkgmo=@hfaS)Og{*&(=t`|#*4v5x<#Y&1PK4?hJ(A@oc@(QF zVwSC#w>II>py6SMG`Q;Az$t3Y5=yO{``Ad(Oaetfdc4X$zPeMCUpnT@Hd&~0t#q{W zVs)<#O!!59Dh4egQPFN>!|C66mMyC%m+qF89>}9x3shyONO1~Ig@%Gx_Mv)9!6-!N zNm5Fklq4l&sX$DD&`re5H(Pif{H>#jOP4K$C8Px*Hw>_UE(?ypFSwm03)E4o!~<$i ziAsON%+zHsMtxq-wJK!|lJir^DKRvnqPn(@f))lry6z)=+ZZt);B-J{gd@+0&dO4~{CI>IXnEOk?!ROuj{BT@>@k)c`~kw&&25j!$~!&%9VDwvctG z1gMrIf*KH_!;6J}#Oo<8jVW*!XF?L_DQ#7Z*Eb8zvdiZdN`E`NO*7#uI@@j3AOv`( zAvnQWFo2PO8q0dOnxT5c*?s~D!Z4h@han5&4i`?Xy5s&VX1M$LJ~V%3fUXEk@Zbsc zlku*h?jQ4?aF6$pB7khUg;io?K_ZlZ$#NBdA8NptCqr|kxQ^w})+20l zhvP=g+Bp9J+Bw@tqcMIO9;b4TO6mI1jO7eQp9*N|YHAhYZA%RVX$x49|Xx2AXXBS<2Akh2P?mPe&;`Z(XpqxaJ zv*YE_(oPglKKPr&*eKpn_8VND@mT6*deQ76RjK`<=tY-r8S?oKP6x0rcks!;LSqM~Dg)^41(N zir6r9VE+I!H9SB7q@O-TkKVfgb!!9QFJd&{Y^1GV3<)vp=)=~tYj^(u$(iqXB`R0? zRFm?ps`Bj*^KVgpma_F=iRiGIbM|GHGZ?Urp0;%o`_(~R(P0E_2==$=&ZCj@&NLn> zSV>7zlw=@+1J0!b z=sOU`!-^D@0#u^r0x}CICv00+A+*{Rd3{02Kz!n08-}6~Gq)c<5z(Vj6)h zB`r33n2F_Dd0bUWYg*=YiY6fak}rN9t+o&X7NbeucOCF90Lqi4#}}0+!jiOt+Ix{5(OT1o-LfdmXKsY`r#ewn4@})p znX#A!Mqb3I@!T>;wT z8Aw8L6sYJ^2h(LKDVZ?|aH4Bz)zYj*EOncVlM%Id0>1ZR z&8mZ{PM_K~U0Q%rwUZ{?99+6;Lx|F)YYY;j1@-Jf9`&(q%enGxybUv#+aldCbe2;8 z0PL1QXsIe{0vr2`5OCTFS6s1t=afANWPD2?NSMAYnlX%X17A6J%kq)p@(42Qu{`dw zVeka=qE=N%-sN?>7czx4a1b4g8!i|yprPFl6gr|?(gTPJX}DV4BfN=DOK!crwqw0l zh`R-*?b)}u@Zg^DR_WDvl>`Ep*FD3O7E6I<1>}kCSn{^VAGM zr>lpjeNNdL*>0uje@9OfLo8~~EV4V52w0L?&bKPfa{GL}1hfJQ(4?GBGLn>n3vU4v zI0ohvd*;+a>mU0~$r#FCX4=)gDLIx^B+0}FJWE!zD1ekDDUzT703>iVo|@)LT=nSn zYAK-EPm?ob(jjnUF1>rSN=@03`iau zk)a`4&@gHZ-&B_^cb*ifRrQ)dj5SMM6rS}mM#3dLJS0FA1?rjUWySK8Qd~kZW?yhS z*tniVTkRTq*6`O}OwS=rw#eh4dnC`}T^`8PQpMj-=WYSRY-kh5qKOQ&uZh-6Lp{RD zvvu!#6JkLF-X!-o@IE{-3+|E>I8QxX@ThAxA;p^IAz12~1}J>8Rf>|zg-ZRkBIMk7 z-%Tzx=7u71$J%CgbLl}gPm9)-5KS3|GYgx{jL2JPz3gll58nDNFWm5@X@X~g$8WrK zR!?s3)Yb6%a*mEa!uzT68m}&A_4HNlfgyAlG(;x@G3j;myI%!a7j3gBv=U8pf(+fO1y?Lc_X5f`k3lX z0FcUw>H3i>7)Kbh3^tvWecC%H8h+}VTJjN~2?fhaj7V=75wVtLK(!kc0Fs1t-4aW# zV*;E5B(PjTJH)b_PR{wjPAaC4qMZ6r&K}{{S&s8o4TWz!R-%P+4zEJAjz)0s)sL#!}yZ zrRNresh~nsqiyDKhO^;wn=s>+<%?T(G^DFb#l$HqN;|~&%WbrG$p8?PkfW#ql2`pR z;k4d|@XW#LlhndXhxJ-4Qig#t+|mjYhhPm6YS`){k|zlkAxr*`N|fr-rITfWVxm{> z%HHl83QMi5cxBdMIwioel#Crioz{@FIGI|?NYSct-)Gg@gN)=^Aq&e(PB?CoJKp;2 zDjFyuNhM4<`&X3dN);;ABqS3x*Q_7Y4_-Q7(hin&VX+*m{dU0;hXTyhH17p05hf(Y zj*}69x{N{^8hH^Bl#TN?=Wu=H3A1?WTxoY8AuXf3E`%*XDNVw)l%#7_!dq=62`CJ? zB!>%yykQ;Gxz9IJ`!m1G`>UVIK3ur9aY0TkMUmb(%Jh=L-f=2Yf%_W}l<-i6&`hoB zbEkbj&e5`(!mBvYfDjjQ#1-FJDaC~pwD^U(^M??kmXiVjWc8Kl2Nm@lg;wT? zBV0488Fx0}{WhrH!b6!c32B;mF zw5`Z0LR6wcs6VTn3+hitv&Jpc-k@Q#VffA&B#=~7x`VOeki_0xh{YyEWox=IO)Lo- z@=Fd<5yXse=WQfq ziYl}b%1O|(Mo=A=HWABW6kEQU4M{vZ1fyrRcJ+=v+;|GZJjU1|WGmT*9Y=@AZKiso z9XqAe#t>Ys*th|E``+olYxlA6(}pPV&mV^0Z$5MuEyq-2*R$DDsc@FuqNyCS5|Ks# z-2JWtUqFg1Z*ao)Bexq<_!uHKlhOOm$k=_feQRJ$NXLNb{lH^8MJVWKng#Q#WL1t* zt1jgI9he(PK-4p802kM_xK87mut>yWAmfJ)ur`u-RF`FxE#WW-I35C3_MbDb0XWcw zfaN?_GfXLP<&s%swbZWSp3oIV$*{VgZ?eOLOMEpXzyltE=1IT~2lcG1%J*%M)V~7> zI-*lMK|MPl@bsl6UPi^KskXTmWpc<5d$(QXuV~ zv4HaQrs{ecikSSJfmE{#6WtLBWnDBEzQ4RQ;+41&jP!d+!g<1hgLG7Q4o1O-1Fwjt zB!$F6N}ke&kgK2#?=IhP*acDryBq2|o){HlhYT<{U}qkak5^9$i|@BxOn8?Kpnw3^S8Traf?uuA$~= zL&C6HoN8sKrY|8n?OT)XYW7j3$sRWr91gAC?}sO6BBu=Uw*QNt?J#{@epj*N|c4&M!QxW9kS{4gp6l4oI_dG=M>$bdKuByBw%9$v~HdSlRj zp!Gir#7r8f&o#C z5;Z9))Nqvnw1G$0ml<|OT5jpq+EeS&&{+xApd^IO(i0{+Hr5>Z(46bjxTSM5MmEVFlpOItTR*t zY~yZ)qfpS|7pbyH3mQq37%;KnoF+vCFkx=-J2LHnyhIjTzWr@rJNv!waqRKpl{<*( zgXJ9g8Z5fq)ZCv4jhKq+p?DTigY;^lifSAosBCpy7fQhCh##bB@}D zvmM(ADiIivOkzKOR?37W6wnbcL$0iS;G%!M#1N@p~o_S z!Hh`T`}$*TXP}NbSzXz*VhbU*!bOR1-VJlw*4jm_#@r-+ynaM=^vxex^?VlQLq|xHTkB)5z%*X>iO*_ZG?ywp}zkfbk;y483w11!^E90-|^TF+F{8 zu<#X=Ic7-JlSRis2}mVGo`J;lMjpyL-A?oe>Q|)ru4KV+ysIry%5?Zg^G2d*YU$|4 zB&uk9=B0K!=e?BxExN#sM+y7ns3}^EBS~7er6IryH7zAb8nplhshvq6DJlRNlW)%M z?+a`=)xb~YOQDpw6xy8bBs-)nBLqe&CL=WiEn5gRaBr1{y8-EIxl!6u@rqjHt zd)u`qQ*mZCzvXKV{7zS^*^dvg6pE}q>@ZaiJMshYcOPxB(Khfy-PYobw+DCZ7 z+aswzV}IH=_m6?GJi_ehrr69GcIA~^+qS(wmLK2$9 zRqn;6Nt@c(IE_s`Zd+90D-uekFf+zPbZw}4JF4EHdUKUmtRAp)G#D-vAO@2FrZ9go zu98U0LLO8H$&I|icPY4QhT1hE_Ll9b58ho|E>e<)MZ$%{$XZnMM*>#GyNS7ZM&(Ia zDpHV^)V1nGuX0?gH+S+G9lp0UcoN6Nn0mW{V?7ka zVTUR{4MB-w6xA{;QW)xGN_vH-sFardBB0#X76aWD(1mkO@zxab6#IJYko=dNZ3#oo zvt;^@eD1eUw;Drg(+OHp;cPO5nkUFplv-J>yYzzSea4cYl_=^$O4}tVgpDOe1~N`2 zaTJI6%~WBMdV#DNc3Mh_r-qtZp&ew-qC*)+3K_lf3f#&-xX=JQP1zgBxxTq{DJuoT z;%Q5HqOcRMMZ?8TJe_*KXiP0qw1ASDm$zfQ{z}Rg2+~vlPzgF@l$|MnHtfWXB-XQ; z-X?k8qFHQ=S;@7*13-Q40Kd95)N5{LmR?{$80_Xfrw>|y^R}f&o_Z+UejXSeK+OGj z!646Bg|M6|8PRKMr1^-_2qhvnjLQs>y7{SaLLJfqR>t=VR>M~pjJ0&20Es|$ztc-t z)VwwfPha<;M+6cM!4=3~s9X0kT)DSd0#y4*Q<@a#bd6poRMG~w650xhNRK>V-QI8X zhv>5iz_X4Ug6DRIY_XbYKbF(9b#S~;&dcWcfH+zRTX8F8SAC;hY$oO8IXckcZse4u zNzi6w7?5xh0VHcqnbSDPt{-Mula}eaT3;)14umj;**Jr8(J-rposFdeA+-XsU};RG z0vYPFr=FZWDSjh42EU*gg)v+&5ycT}7*onpA&JwN86y(CqJ^Eioy{pEme5{i-GgVl z*~4hGSz0hkhOI?C=Y}-^0;eFr%z#CMp zK?+ucl0rgK2nI=`MUB(08r3n*MZCFTkz9bFsoiG=!otGd&f1Q2)vOf<40ic#KN|W! zLB=`_R}Oxm>Nai28LzDQ9)>AeDpsq4Ntg6+Qb#Y51e;HC@;34S>_Hv5%#HQlLzvz< zcBv>y2u6`GfOMq#$x%IZHe^^M4!sSZfl1?fjaS2W*T91&J6?NZ)-{Gm&j5pQ3YV|kjZjyxH^jJdBV3hQ-KK}qZ zy;Z!(9d^r1)M%s^xN__^n{%c6r@8KK+h}d{gu*0(LY7vzB$7VWBw%(yz)mK)&%C!T z-sVqSxTGj3l(rB&DQp}7kv`l^&sAR^tQ?z(N9p?t#Br=fY*q68T%qv_fEIOufn{l$ z5oeM+3&;=`wd@$1fU~yEj%g|~98An(vN7o+PTn|SG!DKw& z=k%Y{20p&Dsc3SoJhEbVjFk12d$+4mEhgFFr;;=7wM{)B2_lI94$!Wdxpz*w^uq$rx`}JqqUR*FzYcsOc~);Ya}7O4G`b)BwZm zg9OcT4eT$#?rm&tvh^noO{!<2WGIfD4;{6Zos?#0EZ%EH91{9g%7)3*lc(Mj6{dv| zl3Ho-$ro!+PcOZ)QZBZOaXQ@!odm7~~Ap6JB}?_(Pg`FwejWqs;F=>X3RMEffct=kQ$N$4bP z@fa{C`{Ri6!)`QfJty^_DfDZpRrB>H4XVbnc5cCOT(O$yXx(C~d?yx%$*FoLf6=W~ zBZR1feU+q*Rm!U|;nqi-ySulnU$YvRaV{hsiqjyZ@r5LjBWB!oQ6~59syD|ka>+{4 zq9hz(D`=6?{3nbkk&YC_UHEY1=(9@V)ZKH))qOU31jip0^2dyPj_?^JH;^cMo2uN2MrlT+pFC5$OEQ$YxdmKQG| zg=9)tRLOVR2sUGFcrSNy=4o)ZRpMLDEoL_Aab;2MR1cMQw=A`1b25}7;b9Hiw1lZ} zNB{s7pa3Qcv51i{c2Ud99+rB^)(=VehokPY{JvjI8y2X{*(Wr?nJ{{+KMb#_g?Wa#~Mi(?J7R_G>}}k_-6FVwn~g|H)me3O%~Q#dT#3DxB0-VshAOdLX%=T49iJ*4XP88j_sA5}h( zdZ|-`P{Wq<7fJB^w6W6Q6j)@`nTHF*sr>U$?=n=aC3N#mI~k{#$s@a;v9u~K2yeI3 z)@i*CuK9V2ZXZw~UF$vCLQ^^rg2`5tfJhR8WT{Fdl4~-z6Sda2Hr+O6%38#!NL;N& zQ7R!o$-rO;*fH8@ZR=;Kzgm=Z*mqHJF0EqOp90SdQCElNOg_G!%{O5|<>b1150*$?5C!tcznTWuLJiKpO-=+5~?Om#KkGm7P%PW+{VBfL7)_ zTBi@0L~~P1iPby|m(^M`Aws^}srorU(o-G~Ixrm1MLqd8q^&6$xSx(Z0oYE{L4zjt z5K{xXF?BZ=upPqo+pl}yhI1I6Jo{+@ZcHO+5;jf)qhT2B!1Ywugf7_Q17mFsWfoGS zvYk6$_*+gg4DJ2?bYfcozydJfAQ8Z9pN=9h6tu`W>m2D{P_Qnj<(72BGVUQsh*C1K z8(x}anE|%8Vzy)6#@)D?#*=V@+Q1<~2s;dpaM?wnklAf3f5wngHCvG@b z(ZeX_3@fP^E)&!os_M9AX`rOU=;qiRBTD*pni&e423Vc-Q=!{qZg3kmvm3j7?YrO* z(}XEAwG%PZ_M8t*a}C6)l&Q1#AgL#$lo%t-f$24_wgvd=b#tLzPsX}G>f@(SRAPB+ z5v#(hu^hQoE+10zQ%YhkC@Rd5pD+N{S3zP5=y{*{r(u>EqiBCEd2Q=RSWCaOOeg|8 zSSc~HjbtJ>1v!%me%aBbU=$@#uw(*Uc<$l9j7NNg$|&6$OE@0ksJL?J)*0Nykvu3c7_FJ;}Rx z_iuadH|~9x>^{C{`))@&Dt)@P1Wq&UpVaIJqG>BvPN<>;Hv>?@_PFh*e|NtQ5UIzW zO#p5f(}42_9iwI&Mw|}`qoI{C2{RU1!}AmqT4|#KN4kYsqWu{L>utmff$#*KZ^$O` zugbi(h`<~MGE#Br+0uR0n;AvW%xaS`S7&ao|{9CoxPX zIzu)IIWDC{m1oSRl1&Efl?oS4E^Tw)gA9)3TihXd40M^m0AL992{3k!ip37wcX;QS z6N^BV+Ys`4bc_}RbflT`!x}o@i-%M?k&pH9dRJFS^f`AfQo&V4PGx8L>WSiF)smeB z!QC204%FIDbI2s_EvD(_54gf$xs*pzDcH4g7NN_K5G$W29X{2$glX;q+ixG${YhyHS5qBxno0jtwd!etO zI-dMBw(xpVA|x50n!YrrXQ-!H7Rj}gSd~`2i6>s*-@mYUa8QFZfcQ*sp<~rwN@jfB z(E2RBP-)TndqmaIQX;#$;uY0$G^?>mV*AvP*1n(~AMW+nCWH)6ti67JOW9)_>V&k}o|7nJ4}j(z6CA>!#Nqy5KHn;IGAOD+8kJ;d zrcEqvcz5|G9dx#tMzJXbAvlHsVO&{F|Kb&N#;vJ3lL4Axt0wxvo2l^*F}j|kGK(>xBqcGbaU4^Mqm!#a(C zW_+1VOPnw$X)zi~`urAun2r^Yd5|m8Hp=MNKz10Ju1@B#jeX3JTVZK)yI zXu$+5Y4U}AyKtGHqpWnbd9$n;L!-EucEe_@If}lXbuqZ7!j!ymOA8I{0jVf;vYT4Q z$BKf;B#n?n`Qh-ISAVAEO*MfEQCgtw4Z#BqvZ9&trf#Iil7F8Lq;&%fhPw)o)6nBf zJk?u%S>_M(zEvy7Eb`J4OfhdnbE7uWL60wxNh(avFa%Dhff}$Au%3V_Jl{OAF1Puy z8j=E5Ouk5({T^Xa?S4l5l!Fv2qCD~U%v5vi7*U9@#kveS99!mCWu z2$V@8rNnm&--AmRn9XvuloF>}N`}lyNt5A{V;BcwjFE+6O^xN&O`V0xLr#?XYDrGh z)|n${5Dqo6PvLdeTE3h0_Ke{kWnLMH(JVO0iX$hL6R3K6y6J!k1ObNTEa zE@vn(+;)n(iDs5e#>`kv^A$AcK37PLJTJ-M;k~+F-I@l7vv7wC& zuM(&*x0J>>A*cH*0$pPOASCZBa%5b{2srHKn|jTc4ly2Dy#cP%{6a*|0N&ok0GDCaHI+klR$`TBL6 z0E46+qjL=|4I8c#ib*uE5fI$*7qjhI0QbRD+-qx#jtApYDNdkDAQL+$r=L2=PUKu9 zo}7I~-)%#{b2cqohtuIWHWf^;z>nomRZ$v{<%lu_Lw1nb=x!`;e*wd^v?EfKao_>= zN#WB#U`Q|k!=%=H^NZ)vk!mmuB3EUGXlp8Aflk@tTW(hH-hh{0=Gu-TQd;j4rQx&! zcpeAKfur=79A!>#w`x?BJ5s zNpZgkp1K9N3Kfk@mmi@_PHCQ0+(?o!JF6+!cI;KSDm+%*&vWC$fSdsMQyQ_SpX)9Q z{J+WbqrUGmZuqy`X6?Igeg6Pm@AvZh4>L|{75~=M1EG1!pQSnP62tSoEm6XpPH_x9 zDA+U@g(J6-=F{#P!Mxn9#g3{+0FHj$Af$|ANtx7=HiOq3Xj^FTWk*!U5IRQ8I;zdG z4kwl|Jgfa9QlwSBAkngz_JCF!vc`@Lkrl0H>~_7z-RcR_c5sSS@0y7;^H(^< zF>1GxMsXanM8Y#7gSE$$67xm@1K!jy(1sRu4qzY-epRWQW`=x%vrUP|hENrrCsP`_ zA$K(8kgRj1!^}mHEP#hnTd~+kN$z>!M$BSjm-)(ywvP#@!f=&|JjF>P^Cfe>M2~QF zRMqZGO2Wsr>=#JZ+awbvjnqgGD!)3VLr;a`5_L9uP?6D7-lWGHx7ks7QI^C>xNY2Z z4Yi114%tG@KoFV^y$F{N0gV;xTOISWZ7yxeIFnXXPF8w4v|ZC|ne8B`RvuWJZ@V-t zaKN?HskbDzkcGDjf(Y60@*v_kjueLVDSZMwK|`77Q1*%u1vVQcEco^p6j*tZQyp#_ z71bdB01ZVDB)`hL{{XogybN^R83Y8@N=QkQ(4)tw_4VvNbWdzlj|s=GpN%=?d~+Vl z5?5gq5hZ37iXumd(M<2;PZUqNJir0lByFrSC=y0VEAEyBD~$(W>?2_tN9cHshK#fY z5J-|X9*NuS=&AAKx=Q?hD*9@P=EE7-#9CDq6wHhySlv`!==Soe0J9Hx6}7lv#wQ+m z_fq!IRI0J=mE}Bh)Q3=V)>Y5AHC=8kQ&miumNP{FHFfx9JE^Oe5T%aGJn$&mDr393 z(bbKMNfroI{lXAIGJH@ZkTEBqnA_FYLc1$vEzpn&2N>uBqo8cV*+m2K8S4!J<(7dQ1gId$I^QgHkxC#9y9h5WT}#pPW$T_R0wYi=IiNLiY6 zG?v8p1grdG!jf6&b6$ z&YqHeKYk)!k>lx(X@MlhT81{E#wmzLix849DDhfG7a)eQHuqd_QaS9M2reBsYzpWg z@s4^ZFPc1V5>V-s6NgGqN>51lilhvOiw{~}nK7Q3bperjx6(@a=&@yq{mSX^{{S)w zY8h=}wJ5Anw%KG1quxBs_Q>8#9^pn^WX9ZPASm@L4J!Wl1IC1TWx}r-(4*o6B|!fG zNNiVU!B<)~s;^ba`aeVyu%U(G*y8W+-IX-tO@^xmMJbwXd%TG90Zg zDNeXBX$n!1#WNnmKFS|t;UQ{u%o2o^8UFW^OFoJ9;k`msSL9x$g&6K5SzB3#Pb(eu zaLDF=l_V|v_*C8?ExtR3yC~)bZzC#c!+ME@8Cd>_Cj;bm9)s0b>us8UH(Gt5;D?ilUCo9Ge8j!`-uP1sj4q zqcTf?p?pLi#CdV*^r!Oc#boa3SNAom9;Ivw^5A;0;YM%P=clY^9j7_d1}iRc%aO(W zz{08|ub}delUVlwWZo^Ymf#Xqj-c?~@cvEBD?4M$sQDV0GdmyV4ToADG|tW-Z5?E7 z9?GfwyHSVNsib?#CW%TUs#IIJ01>zXJ{tX!NaIT}g+u8fR6J+AtzFhWoW+|1R8w^` zB4P2#YJnh=7t2VO6GT7C%~gh}1xki8(hvpwlfeaz(n?^MQcl_Xf%&Il=^j*f1!Ro)8R+o*EgrEk<~tnVIH@-MGaOVQj>g!Wp`lTq>4W}o^}WVvUzq9$)@Pe z#s#C}XeBDru8E`D>rm+L2iyQSaZdy0HXf?2j-BFoMFk>OVn7oNZzORQEg17usyv>; ztaktn?`!td!6Xf|Pi~+FJrp3}@V;=a!?KQ8jm)+6l#~=j+{)2QRU$yB#1DIO5nwdz z54V-qry5X{hX_vsK=PXUAml88gY>&2<^Gf42qU7)ICUNy2s#T>Lb1DA-Pywv^zcNV z00XFdc>7HX$<#^sba3}l?;W4YpoW|SclVfH`V9a-UoSXQL{Kk{)w&}^8;v(!{f3&_ z+Ufamb4Hs2gF5tuR52tRJ(a^PZ958#GULscHg-A zIcmB@8KaSc;Z)gw48t&(t`?e&X~;SYqJwkvoBsd~7;F(uZJ#t|-B$Ap6IbnvF+5OmRDkgE|?E`VLp5w=XmY#Pjn}*vfgB=OP#wy|LG-Q)M@LDEQ^$qG)eAIe%)6ON zd*Pq3GMt_pwCrO*QcLP z-jaHCp6Ia}UsD-+stW4JWtFHfEPZG5ASJ&?F{RlXU-zs)z3tzG88Ve>O4&(KU#1}W z3PF?FF=V2q-3rua3?z<&v(Bs=s$YiQTk2;>Q?7U~Q)sDhx{O7dpBu-i<-w_)*#7{% z4%Nasor7KSMFfL!8v!QZS9NyoX0Gi`kWyq6;;Hyhit!CP2$dBN6agm>U>>A&(F@LW zewlJk0SV51Uwr&B?jZ8bhv3b4a^U3JtGVn-w#y}#veHj=PXvZDngKv18$e(i%1US(gCbuy_0s{$ed zvD?$LXvT{-RkE{Xir|=yNUg$aqiU*2;5Lj%vJ{e-+q$Q%eU)P$hA*qu^keIr55#koQ_*Bz zqe~WB%@J)LOcF}N`DP|9pz^8++{5=-``?kx+J7dp{?I%s9VjOsI6fikPcouh&~Vgn z>R28V{&(Bw6}#nYRN%P9O(dGVGZA2J2pU_%=(xT6>&T|__HG#I!ldh1eXvg*v{8D? z)H)m=sC9WGG-FLuNt&r8j*kzLmKKIZMG@3Mr*M*K0CBl2-tNB+0~47#!{s4rApM{u zLJ0o&c%+`1K;?$4LUtTXrodKK!=`y~2+&0dOgt&RhT&n_>QrknIDz1MR?1TrXQ zdC**{>E=Xj_PLR{cKP=NGV@7ZxL&LVl@SU~Ajl+0#{y2;k1j0AB{LdHj<9^F(t7m4 zxUl79V^RyQK2%WZ3?Clk2v2W3d%K2l`AX#q>?sS z0ltDl2iZKCSz(-p@mA$aQFH*1twk`bQwAV$2N>Bj7R=an_KAe}Nm$qne-Mv-1sFeD z^H*H@xsGNUbeAt-^j>6Gju!VZA0?S!tK90NbwYt5W$b<1lgxw5>_3;MyHN_$f=?e8 z4xBa-Mp?dG-dxjUc-E~XC~cSoq;1)-duv+1Q8`l)&K|t-*G;g{?!)I4EL;+;Zq$7rnC%5xEzZvz)2?6$X4 zhac#+uk=caKR=1rM``kRri0aqn8%1^OluB&F!^e$FV9XWXQY&?FxfN=OM42A3^UHi z?l*eT*Pnf*wx0`}tap{L8<-FLDG_~?m`7aF{#6>krwM;&J&%HQ=UE~&BKmePPSCe*8dzjg^dX=;T z$V;Ibj-;h{<02;+jsprG??!Ud8H4RLids=XI3yh&9fJTT3^v5T*;XTv`WpsP$m@dR zNU&7=%}qsAk^~}AbwsJZXv@NjxlQarJQ~ zPeff=!>GE&iemju`8-1nsKc8(y9f8i=C{w6v+^-p+QO+=<@Y$C@iq zxd64LJVXPh#fg+B5sBLh=*N*cg@^Lyb0W5^(rle+w;I-vrkfhR7yVfBtITC|>d!=k&zlCj>X4zbUz7z~an zqK)bwQl+PgHklM1FZ=emzt}yB@C}%_wWN>Inxf!n9Q%3a&~IWH0<>_QZ+?h9}E*fu)zNSrCNHVcG+NDvM{&;<}$gt zZrl;9B!*p3)>{O++PnivSXe`e!6866wSpNAX*6iZYuV+k%eKFiw*iaWOLamYAq~Ez zrD{^ggt*yCbsQ1`fyZSU4^MuLdO7K@sW?V(>0UjUXmJ@a-kVX>v)AFGD8+Rs#cL)L zM;_OKSTrm@$+EjdcQ?Jn$jqBV$^D{IQ2oA@cdYnQrnS7_SX2PpgGyFmASfa7+T>I_ zy}hF58|7r}wd)qjY+L4QKn=a9_f8fYMv|!uA{|Y}E`hucNyOguFMk$zM#H(nemYzHxEu}^gC0ylWVM8r$ z)TfSBw3|?;mcf{r-Jw>u3-6F3-S;&#>X=YZa?nd%*{S67Qje&)d~TNaS$O4W0Eq+ABkDjo7!l{&N;M5rrRDF7eHSRX{Ntcr2!Oj3Mu zZ0Uw&YI>@COBjN>k_wFNTJ4X`O7h44ij5 z2m7idprGMHUOSumc}ZW0XH!izh+8DKEAM1(5s8vxj>2fM=yfZ7u3*l|ua7RzXJQj`i(+pZmIK|^c(qd{m6GI2ms zNLp2^DR(zFzus))Cb`W20K0b=@2n{SDo1nvPRijxtSliQlc?$^QAyiE?^Cj_C5n2U z^%GS>)fA?WA>_=R3J*ORkmF*8hDed#sQrazW%C*1d+O=|V|#?HDs@Q;1v(Q4SP-wv zx2IR;j)VXdgaxhERESAJ0-Mnt+;($>W4XqcY#3b=pD!=r(bRd5wsJymVG#jAAOeH;fu-JZ z_)>sLI#qIseepsPyb$pg&TSf~n3)7J}aB?U%gqq{?ibM}jDBm(nc#FCO0l_`Y<0+AvVM7^T# zrem9Bnd1zp7KzJCP4|pCu;Yqeg(xX~+_sbgWFaTKJ`F$uNx!7bxb{2I+&dc0k=4m2 zJ<@F9HfYDGUZ45A6xcpCR|uIUdXn`m1c52vcxi+}z%HZ$?Pd0oR5hOHK|R4IOT?i; zN_;L-rrB(TB`zY|DGajW5QUf(%OwE)!hx&NsK7+`wGM6X5)>V~B)?)# zo;NoR4}ArI;=OCi*fXGECO3sFh@_BIRYc9LhzDx>P5e&~wvQT4J9?%#^nRQx zESy*6@~7O{rH7-;p+I}hY_XAXYS?{n^ir{Bj#SHiE56XYHDM~5)M^NSKW9oikk``03K&F-ik}c3Dy3PI> z8Bc)*zzXuYL&yhF3D<&(^p6@-;ndnwC%HO`9Ck`TP;F^YR#xPwH#^atN<<*#R>53M zttuf-D*QXppsx_LPqCl@aiB1^-s{%89L!c?`iq;?s zTh^i!fI^U!4NaB(&Maygt{@bZ_+3CqN`^M-I@YXLv%UP)!@3C_{_{41LXadN6_9^q zWPf_170~Ab`CFQ+@DE(QB=ogMLiKn?VZ!nzF^E&Vh_3|MdVtMFl=3{R-dJMJK%Eq^ zu(g;v`%67uJOJ+)1tcOB4Wm>oPm%#ki-3!!60)Hok`R{58n8v)>t=cCmJ;g@<_xx= z2@6f*p)M7qAPq!9K`khNIN_yh>Cj;{*@LAygAy-PaeU#{EX6F%DO!k(5Y0~37qSoDo%9`%Asub8N)7Z)GeB(GB4 zTUH6hASb!jHAJ|8QjRJC2|ycEWayGlY^TGXV4I8p;<2Y7G+M`R3>J{i=wvqlq^ zsxe%#7hCfV5kZ87#BoA!+?SRwB>30PRK))PGlsNrv~fyJsoaHgus06cWFY_)mXf31 z6oYabN)n<;BfE4wmedIG6}ZW^QuOpI%+TgYZQOY*+#I6W=N|o&AGXY|uuZpig(thX z3Q$tfwd8_QH4##<-1||F=bpNC7bnrt;kYFyOL6*a28xEC<>iiu*1<~C;$JBwahm$I z+fggo)q^g8f&*>`6rDy#c-(}Iscfybz;n7=DGKh-?Nn0YU2#OMqpWvn-pWO#u1{xj zrMT*|Yjs>L#cN4-x>~{*?-Hd38Zy!o;UJ{qK@&fsl~u{sA5NGRT_t~+LDD>aYIjJg zDde5yr>$_2x6Lm2Viwx!>WzDBw%Zgug(ZF@st8d`rAZ_abfBP3%5@`APzyqu5S0SU zge@;6-e%Bp?D5p8xL$K^l>$((fR(Z&j_AVG#VSgaHtLz07WEwN_}*Nl3MC^YUF)e;?%(y4ZRyj z=|Of+h51Z%0#k@R?Qwd@be<@2nl-RS`}em zkxKb~m(61w-{l`ROsJ)jQ5swVZz3@80Bd;DHwV2$PA#{p0*H?Ml+KqBk%%x>hk-aC zHn?)Jn|lHmzWIKk;ui~nDcCaf5@4jMP)HsXB=nPo9;)iM!+lBhPZz|gD(8w$giyOq z(aczhF#1@;lBAVk_HXel)*#wDf=qO@Db~p;SNAYsNi&NqB`fjW6Q>lEt5btXN`BnT`;d2NmK4Rj;JpyTy~eRp+jNXBnexrKI3Qh*Nrxn1&{|+6H#bTF`>>W>dB#g&+`A6yBsI%`x5~ z3Q!&55S-mn- z`m*T7XF>YiSp)SGCSuQ)aJlxsd-q?UB3WSUG`oxJ+#nYKl;sO@6I;Y=pD-9OfNpyt-RtN6Z`<=kdlbdB}P_epXT{~

JLetf&rD{u8Os=7Q(@t8zA9xfz^GvV4PK^&KOGAOnbR|-dpcbbaP$ert{_0lR zlBBYfg(%Fezi7MN*7Ho-(O}x<%(L9Ub!zdr65@heDJ+z<=}M=>9s)@o8Wi$2IG@it zbBju7(=tbuGrv_Hv(2JfM#ifpmN-(Vl`PnOJUh?I3&^@{e|JLe^`_IR8#)qr+Qz9; zw3MlgRScjDRRxl=d!U~500hk~Pj!6Q)>t=|89+ojTo%oxB}KeoKH~KL+`<)(q~ldr z>QB=5sP3WRn1%`Mt=8iBNAXI&@Qwv8;2?z;hW_cdN zHL|d5C9OYdHYo(SVIUzeuN$Ze9phqFh*?+~RT;&)d*hPWDGO@e;5&J6<+tqZN>YWi z4z#I8HAxcVrd0Eiq9G{>nb7|L!{-b1@s8#$r}~+y!*N(LjV2286c|1wO;pDf#*j;b zR98nTs!4}OAO@*Hy^Y8y8urX{_O6>+T3Szp#+MN!sii481S~n-r~vv?;%xX1m8el( zdD>{+Hkh%BQ{l&7X>G;5vD0*hl#*1Ng^BKo5h5^A5ofvfT&C^(d%VixZ z3ojG^&XqLbZOtWwx7>o)jOxb@a+JTBvy-%?lMP*6jcIdQZS54{wguTPcbbem%85gX z@T89jrmm-FS_}(3^@=P=Dhht4^z#RvDp~NsRG3yBv&ov1%#0PQE}%yQ^HRqE4)9J~DO16qs7-^$26txULI}CpE zv(HR|BH)EvmLx&>-6v353PYXZzi8T$vKFwV5pLLZO^~I6<+)2s5F2Q$HUXAbZs<+5 z##E;oTRXl~%GyJTJ^uiCrhjU_18EO5t(re zb04Irg{Jc``ph;8xfYiY!397yF;I}J5qZFA9574yZh0r=sCm}X;^2cYK|Uis5|n95 zk`kN=Op8sg6VC!0^*b$s@@763&QH?%wTz`#`UKI1zgMHb5i*dPp5mB+17C)39S% zdy{0AR(?0#Z6{3WQqq!`5=j#~F)}cj*-M!{FZHgPovOxH#o7(kN?-Y1Ud8z}2CBo$ zur%cUlpnA)eYfHjU!gll{w_b!#d3eW1Zw_{6BR76d6Xegn~QKxj625W9RB4VFXR3K zKK}sWnlS#Dsr_I2QR?;`)t;GUEM6>5l4^QLWRow{REVX-Aa5-qhFBR)^2AHREp`_w z8BYqHx({hAxKQF&f`uffS9nII#vp=JCIlTr5z|5K=(gSc@ylGxZ?2eAOG$8~TpsTZOrMv%HhP)pt{k0F%hXU{i5?S#SJG9%EiG-CYY%QH-w6@i>p_DJi;*eZOjheJ)KSe&K zD)YsD9hZ7@nP;bm7OKLjRWM58WRjjXs`6DlpvF&?0&TVpx8Lo_hc9{6wuG%J?-T%1 zbeRrl3sN8h;z~}XCum2AjX2kAS>LRQ>vr9G`qe7#Q0nFOpe1SuDko7Id()s9fU%}< zin6ay{{V&VSdY`rA)or+QBzHcV;M@f9>OUS8KO94Q`RLO7Zxb559y99#EN7>H?S&o z8@LjCH&mAr2}o^A2SdMhw576D+?0230ODFw6{Slk)Z#!Qu?u|1+xE(a+Xy}Y@NsE(B%=|bMGC=59pXY%v`W%~RM}8ViHS;v$SEds-HrFl zyGgbWGy5l0g6DAL7ehLV5a~$%2V?eX8$lg4T8TtjRSdeR+QIi0YXf#5ciMaQxF+}D z;JE|vj5@t&)x4li$O0rCvD1Lz#;gO-pG)zcsCtvhIUg-irFBjricy7*MBf`n6oN?_ zL<-l56no>iP;Yg=B8>e`Ic~PvkhP5nfJq8j(l!FFGDrsr!i3xBe8%f;{ng8gDMM_m z1p^Ai5S=DOD3b}F;)up7{{a1T<^KRg`8O+Kypge=tt77 zO!aBh{Cgy3%vx+Brke!Cu{=FsiYGJGQd2!daJiY5IN~8r<9qfCZs2#BW?zxgld(a} zNkTwUTT;>rmb4^mQgqCd!6{mbQhH6=ZuYyl7HwZL!d(iuWv4ZjcpGtH1wbSf6$ua` z1~WS<^1lslN7UUv==D|)if3e%I`M>M(T2f>Q%?>hMYg(Hn%an#rGHBm6c7^i5$+Ml zR1iCmE&9`Z>QG1bK!%7dtl+DpmlicO<4Y*DT9&3tp=&|{j5rg`-r4&?Ii6sJwP;83 zXRdq2I;5$WC8VLGD4_UM^4##WxGO*;9)R2N6Ud!b^(^(-k@MDG%N;YuV{F%f;kBZs z8S3hysTeCuBQ!sx#Al2Nr}EjAS5^z+Q)!(rjaMVQI>U}78k|&+w6a2{QXIQ+Ev47o z)Ka6Um89uuBVNbzJil`SSp1#M#rs5A+&bQcCAQRqauS$dhTRH1+ggAm;0dW23-G=4 z*^A^XvzKMeGGds*ocfdIT)R~zO*SP}gHlC39Xv2RFA_o(n|GIar3ltGV9F$GH&gDZ z2ojKPQWTUru(dYAU1cB^kWvI0uI?TT2HO7sh2=K4CoWp(Expe7Yl264W%@4=7SRL{l60sl2})H2q>&&IDV<3^6+r|H^UE{)P4%-~#h_k> z-EouNCqeHUFsKJ=XYE%Wfdo-FjvqCOu~OTga8+YwYlb&tb8)4++h2zVM8~_IZZsDe zRGdWg#|h}Ao(X};JfAe076H)TcF}7obK6gpa=%dLPrz_f(seWuT3nUx%Dx zD(t@ue@L-sEaOY+N2^rgJcXAk;H9QYiH$pBxa^=V9feR7{U_<>AbE==t8_|PKMGoElHHlGWOBGVQ)Eo%P1bMbw?7QpAx0SYVoJSW)Vm;4snWKl&N{= z!|WFhz*SS^7HGkeWYi6!!Ns_@)O=drDsU1~%EOO^cW<~04mPHlM2Bs{r3znpp(P7g z9QfR9mEH2V{$FC-fweS-1Ig4sCzmNb;sR3k+l%5=`I6emLu$a|iA2ObB6M5vPs@0Z zs_u*Cx$?GRY4LgSJSP^Y7@bF#Lqf9r)aE_1$1Pmu_h&G|t+Es$Y*#mUEc?)@?-Cz* z)G2N{uIYUC5c7EkXKb5>G_sbSWhI1ab<&>g zGbvJ9Mi3L;IH9S<0;~uhP`?V_Sa};4r@<-m+!=`0Vj~8olL4=Wv&^cFh*s3Xh{iVs zBPV>0s)3Y%Z)=L!d|j<6Y8R=(+H@%^3veM0DJamT73fQe)TDxdWjcvUqbah!+xKfY zX-+BiF{Q5gLgBSHrL{U*LWu!MI+YqylBE=oNZSB*1?bPzb|#VH_*O*6UMZD)KUd@|>4r~+W4LRqbJ4hsj4!oV zB!wA~izy9tW>U7-UK^Iwl@^`Aq>!L+P*BD8~st&MbPK0MXlb122!WJwhN{Q*_plNC-4ZN7Z2jADi`kV6&R)V*#(!$gd zt8%wc+7#z{hFopU3MfK~5`+6!7NsGuln|mpip1^nHg(G|T*rGp- z%tCr6%By2DX~KDv*)FhFB1o1E<%$l`6zTkas>L;VzvDJ0O5{679$%Tq6I+kUe zENlM&BXb7dCD}k_+Ng%c_PF47(#^4C&D)*Y*-P%)AvzG10ur00EUE^*LE{P~WF@}}Y^nYC97h5{#KF@7V~HGi?3(7EY<=??HOrRB*5GYHwBi({9f<@2ap)UsXPir* zzlUXaRB?PNgB^J(@vM}%jXX(A0jaN8!x`yOj?{~4GraCM1H6X?u4i@So3<8PVdA6) zqXjKTyaxgaNW_UHDgXr-3QocEvzXnyUQ*q5=qK`_XjkNtg6-i*h7ySVn;L=rq0&e~ zgsMW#W&SCB8T6^quAXFmr}QHp{$+@z4IJ}KkV_(@@JN%$k+Zt)+art0;f{(Ii@TdF zsrH6my-QHk;&o1vh$&Dp#K+3fxfAfJ32q9@oZx>g)N4%;PC zN9F#CFPS@Hf;gu>XZ*tf=_3JpoNEoSF1`?$Zk+1>fSv9vmupNWLsNMB8)0p z=ENO!;f>|cxN%NS9OFH8f!B8d_X$n_U^*aEZ&F1DZt0e7%Rn9UG--;)*Sjyv$*X`a zZlGV=%v|5M5Cc~O{cMs?Km-%+nmDj%yDfjmLYt0~q?q@CT6gqAC}up7>V~T@P*Jl@ ziQ|=VVW=uzS%o50NbTfpqVGE5s#1n zRwZ30yDCZAl0oVsw-@O}1{vxD(LM#1F$GB}@jNRT%2i%iI{=ayX`m`37XrpIp@*{k zKfAO@b>=ZCQV4_6M2~ErWeIZp#daZ^w3t=9s8}PRDiiKVpE}V)3Bnrzs(cE$Hq>Et zl2Ft{P;U<#G!kFmyAA3~HlaqFO|-xp?LkB<0z~b=agCTp$l6XaE9wg@xI^hf$ek+E zp#y@_4^GT+R}GOwH!)yU8Fx8ixFqNmDXOMb1gR>n+vBx~zq&yh>N|MyeYUt4EFr*g zQb(y6A9$=gVvqz2K71Vf+A5f?+l~l8=@yYBvWKea`^1WL< zc63Kr;m~O{)tWEaTTTF^ttBK!+!ca>^O7fF#L%tlpVP)j>fJs+>*Lam90w@k^=n(4 zaqbuVb1%yDys}f&huj$bfQ&lrA9i=Ec^*N@ zGZfjirWTDPD^{c9O45=_N?;TPHxN#LW7|0%` zLPylcRx#gPy;P#F=pReJlHi$p41);6aNGk5TFTj?iQY!9#_F)zNMo$Ts$_CxkztB8 zP?1F%q6^9!uacv2a{lK2`A@Axt#91C46CbAgrIB!OmQb|0q*aWn?7AjVLFM@hLUt9 zW5Oaw39!rX$YH=JlGiJDO2d<}2w@ea^=Ef16 z_(M!&Z?d)~{D`-=ww>I{tzAP|lU@Fm1Sy36VQ5rfpoD^jX*j~v5OyfRG(XC>7dp=t z62+UU5+_jZ(n0?GzyqYn!jCto-%H-G`oo_;toUYItgp(3IVm!1GvV}EcV+`kG>Jw0 zvn|a~lhIMPyi(DhHH%2kB#iEUer^+)?+I35>TWJdlyyEEb=0Vj?~sCkA`XO*mgh=9 z0=px-neIWlR>;fH<-M}fk*%)rGL@0y3Q~yFuyB)!fC!B+OY@JW{{T>3JV|Ra-bTl8 z%2;%In!F~hAYW;D%w{`V#5IorP9Ee9a*5a!3QtA>PH&vZb5_kON{RCc zCx^7{!htfo+A^#ga3P4(K;8uR`gr8T^TXZcNBVWa7~zS)aoN}Ac2{4^&^d}d#gyvA zgK=@#ce3hr@aMbEC!dxyoLcEPP98_~AYwr{M+(SZ4O*c4s=HJ;xl-DO9^0>CevVX6 z4tX@;2{@h@V~G=tk1?~^HGLk3zX$G&`o;9Yfc54+sp51s6_q%Z79)n!;PldpI?7qB zVKOyHW)A~LC@iB#1H+i1zdfe8xp!jN+V`4~tt;205iuB~$s9;Lc2+BA+x2mj-Z^NN z!jhdTN{Zu9P{hDNh)^JjCkf+4AJlhJJ!pCu>y|a>*C};xHBW@(r;3{i6qWUKk-Zer zEk!JlQX{yIJ(66amQZ&9Y&j}q%w^lzXx?V4W~Sjfj-5qswux7g3gxmGK%iMcL-frK$1wjHAr6|HiqXhLNMmum6S)T6) z_FN^aRuWq&(v<=dgeYJUqyx1gK^T7y+$m4^iGC2(-jI58hV`GLxZWY0GURnJ(c>RG zNgQ?5Q%b~BPKiss9+pxzZu>~~1Q5W0zTkG8jr4hTt~K1d1xQFGNm@tUj0jSAjw2DW zk?zj<49#VWun@nwDh5K5B0#_ppkw%BPBVcOO!c`>GQkA(Q(+ackS@{+DS%YAtVvy< zcD?@3v~w%KB04tWc|VOy?>y0wB2E|$v$Lv93^-%6Z3i{<@q6k?y8xtsHk<0q2pW2)vgNXlC{S8Ki6DqpJpjQxaf%eF@tjj9W*RJS z2dOdC;Zwm;PUckwWmZ~=dXL z)Co=@V**5R;GT?YW>3VFVZCwm{{YgjT3L13QJ*d)svDycn}$-gt0ZKR zUWx=L%xQ=&9m>P{^zT-bmv^ zdj);Wg4zMEW3PqBZYpdUno18EN7GlwOGsKc(aW90NIlfKwY4Db_TRT)P55vTOsGvH zb0r=lI!#OqBl$sO1pv~*#X!BUVQ;)}#kB-tdT5pWM0D}v*H$yvteMm-gM#3>v!~_? zTuL0Bm$L09BZ$~RL*!CCk{U%TYMe;~rbXNOI(0s5gdL#D`BMm5N|pUJ7#wzTYm-RL z9dq**_R0XQ_gpGG2BHCukLb<>;&xFO%-)rs^rCNvF zcoRoMrqy{*KlJ`eN}(D>nkWVzSLG<#B~>E%L_Y1zWDK?~Yn=zjo^eH`&q0y#sW!nV zxny7nP|~i0hLv(^r1Sn>%oO-VHf76LdmL{C#3I6Hl7I416_(WXPh+_40AFpE_9omJ zhmvF{;GrYbVk!r|vvIVCSx4;~SV1RZKvoJoOm%ImLTvGxsPeWCTa8v1%#lY1KY-$t zOY&~jR16xnifH2@eBGgpWk}wngMMT6!+q0*DHtVKc}#lNUbOO`WCuu5T4!JZML4M> zY{X0sBg&5aKB_bS095+jj$wJWqL(&hY!fYEuTM#dQpYh#F)0k!g1RvsV#*_1Tg)m& z$O6~mr6iFYF$1J*+0RW7CoO5Kf}443!j+PYB}ABzWig~|fjAnQfMES9$7iQKKft5L zamw6p44`Z~GuKA=ZW~EFnKPqMU9cWUW%E?Bx)h_K*Upb5kDk>{vX)Xx@D8}Ao8+m(dpUfH3>oj75#uM45s7Y^zk2h$&2T{!AKC5YyQ zo`)soTv@R>glioa=%Jy*(X~oLC%k|aSxx0CKm&nH#Y$zAhT$P9fFcSB0FNn75x{JU z$IH7$lg=2=^HEnoB1UYhQjI88^4$T-UNVz1kI~_~0)rtFE!M_iz zo)06hkDX$!ZDgx=PeD6+Xk+MJ8Io~HGiFuKF9Z}=&Ko7`Dp?oGjy2p7P0yBs+pM~h z0r+tBhSTE;*hK}By$TUpx&AJmpX0?cb{p2r6(gFf2Akw(mIl&Dn1c+gme5Jy4yNST z0m$OXDa)Kv3BkiYXJI{4fvL+Ryf1=OW0$92@aGFAl_{%d)Cf(A9jr<`qhl z?^Aisy9-4iD`Da|9LlpsoB<131Hw|Y>Q16j{BSXa2r_8O`oTygXiAHCDJp{iEBI$* zgM|d?l5-6~Z}b|ckw)@L5D3&?U3fP9+hh2X?V#UvT>k*5xVMw?{{SUE?>753i+zjz ztM<0O--kE(wDgLnca4Al*Q!6oJMi4D!>en0-O+e_sdmLJO%mPKM0MX2nMR^Fj=~A9 zz=9)@jnwl3cVm0bMR1!7+)$w@Rz4X!W1#;45=O|>kuoY+&T?aA<7j@&?EduhE35h{ z^fga?E$hu+N-~pV`icaT1FNchMo8py9c?tNXzDhG9#q9PkQKtV(#TDS=2yPY=2tT$ zVIvfg!1Re6aTFW3y8OCyk%Z4!>FPCVIAi77iD~MvZSqpb3d<9SiV382S0Pod-=t%^ zaj*=aZK5)PCf@hBC3cAdk~@tZFqozuq~;n- z&rkfb58oaw6I4kg(2~fLMopT^EUcZ`V`IDRH@&-YjiAzG?57-5;Y5qnHZg@iLo4u% z$5k{HvbWEC*p$D`N`q*km4Vt-{pkap-yK*n8`|RFj+p&uJ$#|ukfYb<)$3IU)BL@O z=PIg*=_;O#785(8IbpfBiy|-=y|q3c9!kzEGLeNw7VRqJkO>@k{3yrZUY_EE=Hkpa z{cMs?Na~MHmuOtFx0s?y0F_DtqyiXT;M(Ano6-FdM=Hsbe~k0%N^1WAO4ZbvPK!U` zS-z^T3Z7#}Iap*5OJ1O`qpKcufto+kK;zwzZUWAXIaFUI#|wI3fD}3ulZ1oRa3g5L zffSHs3fNp%KD4UBJuzXJ)>xIWtkYW^OfvcPHGWY*VDjvdt>xa0aNBNnwZLtp3z;Xz zNr4eYO=JaF_o~C5nlxCC;n|O5euHM;Qx)A##OW}cy%iE*64ApfKh5W@+Nny))gnk- zJ1R<`lB^Dd0C+pe^6$@uIu)Zv0tO{r8$<#~9dkk(UEB$`b>%*=QVb3x^ba1K5axbm5wwD|OMhq@=wev5Q79-l1d93F;z--_2j*O4o6MJghiDFI0%cy6w; zDOOTPa1SlKmg%zYTG~oAsCBPq&aIS5`E!;q-MVlg0G~67_MAUjQ~GB0v)5duh3D+U z=>ra>%UBH#7M1bQVr>y%Dj)V4^wf=?l?k>A!j-AkP;fIg2kK=RNR1c zzEoxzdahY{DIq=LRGAzgMEMhe^CqU-t94#my4p^j@g+01Fo1o#dWkhc`IeJBbk{i5 zV0nTGaBP1r)tG09DUNDdnr9_MZGBl^-c}!JHMNN6J}#{bDpL<82qh{>_7HlyIB^EB zb;g{vaJH~gv=}3ZQ0VxB#8sPM`SUOOv+2`jJa|P0VWNR!%oOpICCLRva!1{usP4;q zE0PGcxsLbNu4OLiOzGN_@;zhWjY`ctoYB2X`-j{9+tZzwSE&DsKCNf4g6#yxm@Ix0ckywmdP z{Ik19+ImyOd8cn!@}f`b@1ofM08KNEH&ZYuM0tN5ktrHBdwhjh8`6=q_f|j-)zfLX z164dMuza|k3fiA|{6`vFym@EkUGLkC3o#$jRD2b~py5n7MtrEj@oXzT^tQgPhPw`i zlBp^y6{MdJ#3BS5YI)pwZxd_ff(Gb|M#DpMR?dU#K&2~+dbaHcqwwma=UMWFCJO{! zpz_od(dE3&QuJ7b1uVW`!SQ{be3Yz~y2UDgq*A`B(3Xcrh>l4XZ$JtrXAdL$u^m-H ztsk`Dc8-J2K3Gw}^h@fJhoV`G<({m|Ra=p9ie`>_IM;kn6q`&><;V&=vA5|W1U1g( z9l+q}#P`VtF&ht8MGtLmAOx$;KZmUZUakE-=3h>oe8upHDB~DTGgNULCRpJy!Sb^Y zGB}l7TI!GPi(c0H0x6BOhT)RRYz&TuDX-s*mB5)EF_5sZ$tq&`=hR{Y4_?M!VkZ~J(F9;(FrPQeCd7Wb}UKn zbK&j1`|wLNBLW36=FDluSIf>6EGJ}PP01t+mikX?cz5IaW|@iz@yTraQHfFkzlNsd zTn_&L0pX_}Op4GHg~X>iB!q{txF^1s1bhaZS`5>GRIH5!E;*bq{65}h**w`S4VEbN zKM+fIztP1JTOffnYjOI+7991cbcB|+m%WaFdrkhXTH$(ABB+6l6h5H!e;w%>(&Ko3 zQOtS28>$ZQ(q;TPY8qfIXw6Ko9XtVVw6v}VaxcRivD7IJTeu4K5v3wHj7*XMjku9X zZjz2xFcGb`W6{ zl1mvQK{<`AMabb@o9-n>&C(I4WCFl#wAt4!S5W6U=ANq$h(KelsCk5PhWAQ& zgtSlvJu0b2TwLYMDrL1j|}f-wFs;-81U zfwxHx0NI}r@R;MqeiRGPVinjg{A%#!wDglao5*XtEKE{HP3#mP7au{t0D+R)JK!+{ zpER5Z@)#N^NmEHKfrupejf8mtLdHFdHh9WXMPAo3s!JNh5LGeS>vFoOT{T@n`1TH7 zC%kXZ;S_FM?-CD@5$^RJTx)Ni!JF4MJ?g`tn1@cY{v%V1X0DnFIvKGF#EmAc!z4hI zQpvH2X(1?Lc^lq)DL(c2jLYv3vW4O{qZ#n*(r_PX*|!2Q!lr9ClKVkpZ0S}JDv8yG z9x2DH6ByA0{8lqwR_e#%Ba}Kl)Y`n=Qq?jl)94GI)=ffWblkg zpG;~wxJt~Z6-@CUi0hFj*+Z69^?&%RX1ubsEtaUdiGtQgIwaNEIi*SVpDILJ$}ohL zHw3kh8+iExvOD1r~qt}O3A_2pS5|ix{)d2f&tp1j|@#{y@&rq@4F1w}J z)pZ_nN;s;pyb^kZl7*SRUYe!|YJ(|ggB7z6duRlJ0pPnS%&uCyTjjS7vIs<|B{9JX zC0G*}n2wrgG^81Ety>R-f&lB)!>5iEa{8P-eDv$8d6OjJbQmzDrY4G(s;!|)m!oD` z5_eR*ax^5RsmAZu}b4f%p;%@>~UgEtEa#^A03 zd;u(?04d`-2H!okCgr)Pw6M&xMQr@LZH|&|9ZFLiMgwmOo!9QJ^>eA+9>|#ssTr=j z7<|i_4P8wuNWUX2a2aH$k|L_59SC1=gJobvwdP^==YB1Bag+d&a`Duy2>X)?01kmF zL=CDwR0G_*r!&0j&fVpyL-Pqy6TzTd+IV*wI(LeJ{J2(~ z78DX09NB{1M~A@iK34Pgw(VM#5#6B(h}oqeamNVbK-}9tedpYNTotWqJ3om;2S#d0?K#&i%F^U#kw5I`DW2f8a*ILPb zA6+P-^?mq=X8hs(a-_gu8K)V?7OGm`m-)q~tC!@`SxRm9glKkxcPfp`ZFvLd_FvEM zR>~bqBT|$Wue-vi0ih#OrU}OZDiamLp4PL0cbYeB;A9Jj9sRA+!%VfIB~lj(0cwDh zN(j_qaW!eZKlE>oXO5C(*|SepJld>(JO#z!lMsm|RfP;GB~c5$2$yNFQ?uVew)&XS z&CwZ)ed6whrxl@71f+O|rIM*TJSi{^q~ncqM=7~w+iOQhWf(5$(mNDJyBMyQYv9U}lXK(5<%19IMA<>JtUB)4+wTH5h6gJCM!fDy2YexcG&32Wo_7OuF8K2$Ts8T^s9!1%W(Bq8l;nnHW*Ra=2_Zr7pDi8uj z(r_F}Cu9s{lLLhq*Q)i+mU8VsOYn5elvr&X%>_LwQB;W`lm*R{#=N zCz)eY(^Nw5x(b zh{gaX3P{6~ePv=4Gh#ARX4;Bq>6WSA%EXE+6;gR|IX1S*-$31&v;>|v`MYo7Dc~kY z@$89;c^w3xNXJd3opy0-|wo12x`);svJuVOjF3gW1VeaHj$t)bC)Q6CA~vJoN-D4Y=nd0x0RJB zEu{@gAGSzmNh?aDysl#_GHKlVIL??MO32#h zNF+S)UICIybw2heZAEE1LR3o{neY&$4J{~xY;D@zupckyANdYPSpva!m zJ5x?j!?|YdB^~1pq^9H{r;_1q#EXWR3M4ITAxd)LWT>>6QB0jw>y@LM$ znMo@0j%14|MO`i$l~|2r7`|bnmQjk}l<7X%DDfH?Ldh(8q)YaKC}{#VZ`8;g=r|z* z>~%^mH>5v5ut-YV3kr3)QW^;-z40Y9k8}HAdfDfHnS@-hZwq14hFev=n~6zc>17g^ zSb0RH3&Bn+VN!@e7O-5ehQ;Y?qdfr3W*?l)oln7N@dESFiB>Ex52lJ#l2=D%Q7oB=~eJMlw?&-!8WzV7d=}_(M{%VI&goge@Up{{R-iOUI=Q^O$oFr5>kslQUI(<#S{# z&uJ=5F3J4Q9EOS|Rh4%VsS~Og*f1XMpsMiSIcnLLJES(+a7e){q~h~%6W%11X&Q(P zX>qYCN`eD`$-CoX(le~O!IbGi%x!Q;PzSiSTZVL)7_B8*!AUsaK~)-zsf6KKZ>+r` zf}N?VQz!Hn6~&f0WTIe|bu_hdpdld&WZxhv93+72<{e7}-*u-DK%&QIzNdDV2UfW^28DFIM$@T+L(B5@cRFYMDwM3qo^j6#BpmKqYl!|FjA8(+U}8wgGS#@uJpBMx@f zHNSJ;EU59ul-OJoNealxC77MA8BU|!_rW(T4y5)V*lWVaNE}C(;nl;a(6=eYVD-_V z^sf&7zGeC5wdq?BuI?-aE+11Z?#9DZ7ZxMieiw)UlYj{)Y!L%g%pH*+`>Q6iQ>Q0* ze^0wdALDtn@ai?N4q&FN!#eHN3|_l^6uE2D{u@mzRHbj3O)R)|G+sA)mR1S<>`!icx2tUi1T(`Q7o-G0$kNz$yzTjZc?AjEM26jBl=%;z_G6Qy~*t9p!M z+_kAg6eNI>krGrtzBrR%{-Ut#27-&Jm`b%HHW||%pJ4H?`|dKeRbD2fc^eQj0=E(o zX*+M+0`ekLs9Rdpq-xUHfNjc@pq5lfhJw_jfI`S3qwACkV;-Ek-Suh?=twj;S#?utQzt zts_7wN*K!6l>pzcYaR>@+g8a_ZWN%4hh%EDkPzI3l=nTycBR8KpkZ0_9m9VQzMpkRB;r-HIHpPJ zG~22vq^ut)1zS|pk_z4k+Fh=ssA*ewg~tSUW$Q;A(XBcZbP%VL3oRu{P+C+OLy9dE z;nMQEvZW}Y39N{?%9?w7uWW9cLfgB`2Zceu+9|Nw`1sTlDLBJoIKiQ-trOxo3;m}u z9!#you<9I#gW=!RYH=1R3BoYkZl)P=Xy8d$2;r&@T2oVf{nEnr^3b6v30O#0kdm9U zgdtBPXbD?~xI)8$Dof!(-9Q;}X;ns>w3KGw+55YcG~(|bck^nN6fPdMLX&P(Qanp; z06=Cm{{R*=$Lc>ZbeGcxNs~O_xQCv!*;6mjU=&a;DMpl-Rdo{8y><~a?#j{Q^`31t zO)*dw80D1d-2VVBvt7!xE@4ngiXKL$^dRa5ZxR&hi>O*k6xxE^aRDh>bgkVRYyI@N z{JY4BySZ}VYAiTheWy!dtAwBe6=K$hS$br+w$L%yR6RIiH5r@HH&=6}KB+z{Ta$if zN83&|wQg#hNKi;T)w-Zn5o!Pc_Cd;T2nc->q+s5O?!V*62S`{enA%w>SWN3BtzxHL z>TFtXCRc9MhSPnd48FrH^e)U! z8#d*K^aejObeABF*16qcZU75y)G0ux?1Kf9D(+R`Kd>WMDiW2XzLE& zcR;06bG&Itkmvw+$bzpPtuUAv>6q}$R=GZg_Yluyo1NeLrKj54`+B*1-D+XcpC)Ibx;fj(!^A|!EHmIOstra0cjv+CI zJ}Q=R{va)A?Mp~#ufd1_X;TUk8e{+nU?*9LDMC>AI*?y04k>un%LdOS%X^|!f1kN0 zOThmCb#`QH3L~vjlhHF;>ebcPQu^kqpARgu9MvNGoyxsoM_+Vb-cnSKWd->i(x(vz z*%HA43MVRO{=#4nXUi_-#>aTMEm4BdM#IB&QJk?K_RJ zLXpxd#>%?@j1)E=`EWqyE`S!&kfI1FX$p-nuM24-PvuboI|_9)Qlu=ccLYh~KIs7M z-cA;u*|~L`r3oQ=yQPCFQ7(|6PNS%W3Hw4wnw{$N*A`Ip@zlIe6UHj1IMoEWlZtr6 zPaP&Di{;8l6B5IxT4<-Ls#x8YNNNI8#;gLii*dz*Zmx=pZYviZSy5WbLY`%&)U>E3 z-QwZWWeQRxU@9UQb9wF6*{E? zN^w+B0Q^Ndx0h-#`b?Qj4IT-A*5zzEOhR{>rErSdn%Zd$Mkq(j5=kor$* z${JLFw?HBzyi{m9!E6b^wFR$I2ZZZUGD$VnhdU&)xz?+IN}aex+kv1GgK*S$YXLz^ z{hUN8L@yGgnTo+(_?7yG#HukWii!*%wl9|H@{L{TBpzl7OaO*}g_s3J3O)3+hxeTG zNy<`y2YTiJC+^yS5Cdlquy<&W;_#0V#%kAN*;^s7p8gxTRq8xr!*sdS_9!w;p9z!> z2^G&bekMMqI)Oo$@Z8-^gjZAM)WMe+jp&(0THw|gV!4i0EArMGLT%mq`?==wlp$J_ z>#LXw3Rxj~Q>7Zfi3msuPRJcKOuwsLpEL9;NTC2C%51B#+h{C5 zXv-s0uC56HmmXGn$a<1+Thy zQr%&sM~zOBqGu5*I+7&Sk=EtjtMvl0A1(C{`R-!sjxUI1eBD`yM}*TP*q#McE83R` zs6fpY6jCkW+--KY$5wWXfNoZsq?S^mlCYrSoVag8i&KHXyn6b7WA zk%$dmSY-)4^^bDKT+4TMXl&dprHiKfpyk301zhS@l9ZW9ok>zs78DhIX3aU{H1#Jm zVYT&GRaIVZ%J}X^r;?%yyh!4X>4xGs(5Qx;qp7E(ph}5|)#w9i?R>Q8SLMTW1^q z*eIvZQy`g4NDa}FL?n&C`=j0#7B8u`q>JgnYEmN}nH^r9TQ~~C%)x!)o!DtB5p=SJNCt`HfEsL#f0GgeuGYCSMJ{blFiAS| z+nH2`Yn3cY2ZX3Q-bleNyoDQ-rW2(ulqo5(QXIGMnp1_a<7jAvz&NeCHfg=g23Kcl z#nWm}bD_;E2(y{FeRoVMRQ6!M+OXLKX#|23fh<0TbKhGtucd5bAIv$1uCo}<*v$`5 zveXRG?24Zn#RYaZRZRq@IUYl_$X#CBv~i%ahtyeHmaQpgT2jDoybdUbPPL>oqErIb zhLTj?kXF4e8FU()J5kEA%(p&irdUE+v|-H3=|W{owqv@rZEHwULU9NQDcSa%OopF` zPpxb}3C}s76X;%R%z1A(;W@V#SpHtBPvuoHQ_@F-Jwy;r&pcJqs=8E2%oG4sLv92v zu(MUe%I^Zm*0mLDakxndN)@3_IO<(+B}#Ww%ap7lLQ|%OJ(6~4S50@1FHZ%(`zL>C_7|M{7T8f2_J6(MP~zoY(o)PsrS3zxIORO8+&|D2GyIt{ngwk74uqoOW%koIePTgkn7y!!tLney!nHmLGxO*livgg3AUOB$ag|7O43- zaU47rLuz&R5~O~Qdl1J%%yQ4~HKge(hQM0N0!omDsIsR~F0@dlhj^yl8qnR!S#4rm z0O0r32J<(cn{C$1oN32gac({o=nbRt=^oeR#`4s1ZE(G-NK8m`ozkLn_FPE zts2l8A*C|ix>TfGAqqkZk1Q;WS{+hKR#HR*d1aQ{Zsndwm%fXqa|eGvd2kA}rM6TY zdB+l+D=0>Sgy0EMQVua#@?~G7UX^|)IeRbVXx9YlJb0xx7hM(!hl(r>X_o|QTG~kI zAQI0mAob*+s6YgylD0QIT+8pa;(NfO-MrE@H>?0sgtE5K-M@bFlw6dRwCkPemlBkh z2Ak$h?+$&q@4awK)+MDn*?rFT=&aob8gWi6p$T9x0*gwW003k_p+nLSPjQT6GW0{Q z)lPEe7t<^&J>fZ?TtXQZDk^Fk*{Pl;nyy>4%q9VXMiwg)+laE3WsEA(=G5wz%2HIf zol7TDTW?8sNLrrnTq58y65A>6)Zq20^%O`?$c+(ccUJOQ>o*__=9v?LOjC7(h{$0G*MI}lUt;dOV^o>Qv7j)~8V<1N2o+s3nnCEKSmGXDU2l_Y{~-%8n9)uBO8 zp%Ja(y*lT+N{kV#AFkY|HbeCxopOwn;+-flddQ=MMu;PdISQg8B(f}OiYx-N1p{a; z-;(C;{{V6Wib|4p4-ioXbd@G&Y$-tP3L*`4*L8Cdn(pt#iGjyTkoAHZ6#_mu_?rzyabu*t&sgFeiRuWDRpB4%f7MkoH9&SrfJ>` zhee4i)kw5#ethFNjXQZ1aZ|(vKoQ7H=n4;b?c`^7dKr7UQBJVE3vEuNvI<<#;v9IA zE#VrSLW*7Q5}hakYD$I!Z_jS`7ddmTZp$u)kd%dH3uuHSxIbn2W>z)2w-if9QUGm7 zS;HE&yy2X%`ZIv_C!!e#6wVo9vY#*E*adE1I88nsgHsG}%qa;=J?e$RRHvRHdd8d(%d*wE z-&tmttykF;r8%++FbAJSJ(bE;#x=R9;@ zK2>6p&~*nDtCp`bP^CIm&{qZdt=@IyG)lxw)+VAuWLXBh6(PHeFk!F{`B*Ajz@ONV zCQD&U7RoToiSFY^hrT2BV*tto zsYuyJYJ)WO3oc}uA5VEVp%vI3Q2uF=FqNUB$8gG8imG{OjeK;Nm0Wcmbd%RgOS|qK zN@*)AF$^EMwtnq;7SPbOSTwf3F{Lh-bv%aLP-tsi(v)3Gi;v29P?RJDk&KSm+1_0* zH@VImdh5E(9`6@!`-p96SZKJzWxWYQDH>9k{i3lzAOa0HKvs1_benadq?C7$sl_%?P*(P*DOO_Lm7-Q{8n$NKtqm;fN9HbrEU0Qr zkEH7F6jV@25CjlReOz^RkD$F0&KL%AhP5W8!{W*rU-_jSO$7Mdsam!8wlPgrOv?#^ zlDUG?L;`G#Ue<6*+l;*~2GA1#0@4E6Rw*k}w+?rRQd(DZ{GpT{@jcVctGi2xS*(-n z_ji@OnVqY)#So_r?ca2?I*U}6i&pl_Lcv&DtciVoElV*nlNz=47pOV6sQB$pZqBvO zi{dp>xu~nD-qJIZW4YX!7=inxwC)MFB)dywTBJ6Cqyc~jhS@%65_p-NwbDK0wqq{0 zO{J<5+f9HFlz;&A5Iul&(2eQeF~^tltu1ylMFUer>gRMS?H~jKp_tf~?|WMP#{rwm zZTW@@P@^Xd3`bmbY>LIVl5zE|#r+)mxx>1(opA1)(B%3YDw#KCzUa8cAd+zy59tESumev840F?p<@kE$3n$1!Ay~8~?Vz|v~ zMJG`HZoIVxG<1fQX(o|lsb^3Rm?UyNGJzJR7cZq?G- zGZ&UyPLgge*3&6U7p5CnZ8|}ND@9}vX6S997M((gsYxw>cBe?-L~$l!lMvwk zq58AXe9P0my5;E;H{zAMC>|z;o`oL|g&*H!mdK(l70&JC*-v{Xde-gl&D-9g8uWe0R+}^gqN#QfHYPd4uhRn2hRFcgbG_fFt1YOPx>I1Rb6d!m4 zrM;T-D6Wh&rGO3u$tDIJ0~z6lHO?*UPMdcQ9uz3!vjBQA_G8goHT35!ejLq|`Y(^; z*t^M77AIK_J65#RhMnhf9K#xF(@ag27Y`bPwE$f>BFS3F64kmNEAO<;z&hXvCKZMd zN>VgxQB0M1wtUCtj%Ec-8`R#n`)38*G|@{;_km5O(@-mQUD+yH-2??GI1-YQh4mrQ zpTo|R(zbc3$<_1AnJ6i3j)@+x<%&$7gX46Azp2Asp)@83=5 z-JA8aTrXP%YGDs*TPSTn5)h#s+7FiDTaUfF9 zaxbZ{wYqcJM{e03@>?e^xIdD)C=KXvj_Jk7DN}CX0FkkA6ZafyBi;_oGdzazS8Wdc zl@)3r9`OK=<4!uqLeNO*38U@kyQSSp$A1+}dp=aa)g3*R7Z#+0ozo8>l5{D6l;a`-u_=rRJviY-x$XO}sVWNahJ$cU#ZDv+ znA_~D%IeQqaQYb@o_eJ+HtootrD9Kiv!eZHzcG(B-bSrVEnnuRABWC}^6aJCp(#!s zCjsxCK@5Of3q(HI_~vHE!oZlPhj&{inAbQNViBsYbMH`llW0;c84~&e_`^4C<*{~cg z-ex~2`)>ezVm9I7IN`8(PTDQAPk7qeI|wJPVs`p$t!Fj9VJdK z*tIZV0*YKtC9a0r5Mx(&)LeoH=RbFerCHppb&?NEne;F~iuw}lgEszmyVj1ADobIt ze~i&6k6;m1GuQkB`EGTg%nb=haT+vd5vqW)K*lqDy~)tr+>ztq!8YyO_qOV8aYD>Y z;uVh_oOWR}A>P|Q;`J{8VZ_NG54i>m#w3tLk}=p06dBPLR^Ce8K>I!i#4oo`76(ypqef=k>4}U>8O&=^5Hbc^n z!*?6&XHW9BUCep23+gr-hhufv-UkLQ^jIx+3qSJPLsG3BH9Yu)QmK$AEh?fG)G5wx zz;{z8-yF^ROw}6y0AiIiooh#kDC;9alc>g>vjFUvu4nx~ZzgfOkK3CIhZ${YAw@Bz zN(um-n?$5X2_`Y3PlJ9WeyK1@*(eadTnh}Tsi3S+Ca!?hM?mv= zRWY5VJ>h#c(m>~7EISw7e4%N5n>2-^#22l?QlLo+I+lJLJnNe``{$fy=iWBF)I%{#$fw77Fe z5(4cKL^l985;QSZe9gV}!Y!}&g>7qC3AeUWOs#W=c1R0xNjL-I6VpK(CAh{d+oZ_S z3XUU$r%(%#!%6BG<3xuN{9yk85?p2}D4(j8i9stD6cpHQ6$T#`oG~}&y*pBL7pYn?ao={GmZWk7yC-{j`Dl&1Io|;i-o!(iUY&@is#UKds!bi0A zlSa3oT}$h4Upi!S&V2QOg>>4ormA>n%e0>>gJTSkvZ~DW3H-8((}Q@)sXBeKq#i@t z$C72epS`0f-II9;1TB`>2}-dLb(Jo9KtVhO3vDm1H-TC&vo$iG_%fEEx1ln6{@4J~ zU-j|n2NUT|Qowye&6#r!Xp+<$Eb6P_9ojxZ=MN5cNOqFm|RYO~c*WvXs%S$p! zz^b*GlWQ3VvL4ivzXs;W+Wtw~RRCHBKtYiN6gE;&pi-oih{L9-z1y5OU2P~li~VHo}`NlywzP5i~BsG+T>ju^m5lB!B?m?*YXX$Vjj%06KGRLI!f zt>V10wHg^ii7ljIp)NFsG$;Gil@OorU~sRX4#hLK_m_8?e(74=1x=`&N`ejxS^gsg z3ELt}$&%2~A2nw}N&V(!C%1E_VXd$6794=V!VP6Y(F75SiK#RXsdc~K{J(VY*uEQ}JRidM;nNp@L(alR0Wuo5{%8hc$cJ5u;+kqY6 z%a@&4yJ*tN7UC3;v9$++hg^ZMgBvO)-yDtn?!`=7thT*KQVyjg5|bq=DDec4R5l!9 zaRN5O^kwVc)4!{HcNOXX073GOIh5kU=?*G>a|ENH!|FkiU~?3d4AFVu6+Zoos5@`8 z+nIauxR<-RY>SJlzswC<0!dLRD#VegM8*PORtjeuzjKi&8P)Xl1Q3{UK}TsJDIqiGwBuc6 z`u@4%gtlkGvc&;WBL4uP<5jhQN`R)pIG}+-2KQLn;A&T}<9V&NS!AU&!`Dv1`;?Rf zEj$zfQ6@*)Vh>d~3wRXkj4&wxjynpr@f|fc2$eD^+>uD=0 z6EQ7VibyGBs)k5V(ngch)S?288pT*JxaLA#_FHFZm7Lv+*Ij5gtOnAS)T}W9QbJTQ z1S^geBVF$BMT)PQaV{hPM4|)|1~8&Q#{m<81_&aLkEu?r=3b8UPd9aflMkTG7&ctO zD{FB)FA~Hjq-v@)Pbz9?=ZXoT5=uKZLYAe_!(010>H;NxTh zeDn}!jBKiG>xNpBB<5OAW&(B9bXlk0yjXmzP$PE!TC6 zJH}31!YU&9i?b@!Nw_eDNgL$&s*AZHJCFm+vRrW}i7Jqh(qr5Q6Ii+0Hue7iCS_LE zly@mw z1`89^bpT1|$Jt0F$aya+S+au-CpQK{VnThZ>xV6|Hh153jScAaf zMbFx#ESM0n3LPYI^%NB2-6-oHPSScA}n| zzFcmyq3LC<#j1p9=QT77O$sDYsa2*#7LFlsH6)Tr;B2|C$ZYj9>r!34n6^wwQivLq zU=ySOAPf=!7y`%CdX>MtDfoRtTNx<-dwDp<5W7AP%&fHz*pOK1$(1PLBi%~bPXOC>nizFllB^6L6`j&KT=)DHXtyL6T<6*677bG`vs zp8~OtIH1853g=deYc-bt0JvNvvPy6tv`HzRu)IMu$&>vh^_MF8N~`LA8BHD;Ux?G< zRF(DhEQfss9Z;mMp`nI5%Ck!QUU^?(XwR1&!D3~XvsRs7dm5T5NkkDcKp{tjB&Z1B zai;fQckVAT?&uV@>H?Couup|0Qj~#+D*|VT@bRPX_!(#Xgt(@5^nuhVgz{#nKbYXs z)F|6ch(Qrh&_+GfcS03*joNqb!>g4G)1kzGl_fzZh*-p9wM53#rVms(L; z(!bhH5|wO#FiKOvdYo%x$~o~2UoOy3iL;u@C3;!Q+i;Sf-DeBpNCf;ZZU8KuEjW~( zI3F=s{{Wxc2U{u;h9k(<2dOo%OIk&mWc?Id12P~Za_Rtk-uCbWcx%a24M6qQJE%dT z$JXAI$JMT%=3boBMIB9cDMwbc=6}(M`fjF`kZ}Iuux3 z792{rPBo?GABMJ9&X})GvFN^9riy761f4`~U9<|s+^D!B{lOd%xP=rYW651n)$E@- z9zH=@hY#WF2A0ARPqGY2zd(u*Mp%M&p>4~s8jX}cM4j&xd%+0An{QGP6PK-JP~EwRpqG5(wgYQ$h7Q;=*A$# z$03aCxLV_Nw9tXWc9i1?NOWmbc!YxnF%z@SC?K$fDCopVk14|niTt{g`EJdl&)<7_ zBXzB9+imu5t@~fb+&KKlhgS)WzVFj*B-3C2(5j!qYw;Vy@_iL2qu*6Hl8mb}iafEH z>o+&@V>4|SUM9y`Fqzoe7k~GijgRQaD~Fl(K-OZ?oI(byRH)lLR*2)p#Erjr8l+U` zlIGzf^6%o4f=SsQ&{tRVPYs6%pyTmJ{5-Lak>|>eqxA0%lB)`p#Z6`x8~M=HL{#~* zz<`nFAlKd1&~6)uzXQ9qyvoZS8C~jvWk0chfdu$`TQrm5Gxn=&0w|j{$_<)|k_kyT zPy6BMP~p-#>b(6q`ijLctnG*8EOQ%ryt2Ydcqhb|ACi(d?*gRm7DSDR2=Pe7NELfB zsTmD_3Ox4Kg8%sN# z!O_O$3nXeprF>*S!If@6{UU%G6{=^S!^r*=IMa?8^UpIw&q}d}#VKm4Q_X*qbb^|o zHP-BfURmS0V$c=1A7q6A7`Dy&S~2IGXyucI7S5n%Y-25E+L$uUOFS}pZyiM$E9A%* zYJ(8>qW4Yir*R(X?w}o8ASoh!l!fIKoG5^L$m#`7JC!iHCrEtC(v+(4ZH(=u1i5Ha z+-nB6nPIQl(&`8KJ3q81fD`I=e(D5g4|o9S!`aT-4m~&J>Xf5u*o#LL;7KW6K?vi@ ziS8|>w*_kgNFd)%2r~yU)6w`+JfS2_7|O$0m~p0=e7Ga0W|0+E>kiSaudAj0&>=`S zxzKQh1}JGd%`P$@Q7Jlgj?^YB(pfW*g9Q4E%rnr`VJ@3ok5 zet_gm;B^8p#C(pzIEp~}b#a5h^dFcz4GVa_35)dq03NB!IAqaRWy3)gUKf~@6pIjn z)smdM>h#qHZ}fRpRIF11jxH02mhT160x%<>^m_2=rFOR(#?2=XXMyPT;CPBTeyB4> z3xfK5>35^NN*2Sb8iIWDn5$W&l+jioG2xXJH0kflN|Leph1ys~hE*3r4Di7IO4>;K zwCf|UXeXu>5IU$syfb9d8%`>KwI^l+;$~xnilB^pEaqIToGP+jYKf?8=w(=HS8!#y z0z{D+PS=iPVI*$1Srx;BVmXbP#oL;JnKM5h)NnNqA;7Fg!_On8hkORV56t~Lq3CvN zl_}=MtE#bV2CAZ9kx*Ao;+`sL*@wGBh=jBFMNng!)@eACF+pJ(#O##;jHYlPbc|0} zk|n;|_`hayCHC8SAgvW1@I(%+Xg=*E~3sS7nkUjm&ir%^rXh zRejzU8h9QVSQw+CA8L(FOIZ)(JZE>Nhv_2AWv@UaGyQaNWN3=;-fH7yyCt%=`BpQh2LMdSGCBqiLX4s*bl0$QW)HO*F95;#(_f;HP&R z<989jv#2{>(Q0(iu)dsUGf4${U$!i7 zrzHL7-W22)joWFI=+wCThOLD?F$9ss95IR=-R}}|m)mV)z(Lky6v>32EwVPn44%EZ z1s|x4kA?b-$dgm!8H$$;SDO)}D21}taobU>iJ`Frk-qkB_|BOZmXM{T zGXwo~uqO_cCNLXFlJ9^odVJQuj`Co@MCvd!x>o zZB})M-FT#HB~(rRQU@Qr9Zm21t>dRKg6)K6Z5Gvp>_5>w52qfg$2(`0Xt1>Y@x*hm z)rRJJFYD$NL)Gq*Vlq+HQprhKhE}8h0HxAaM%&^pFKzVldyH-G4&!ODg6(dc${#H_ zF$B*+1Bmn5D17^U_)E}5DFu+Q_kT$lKH`o^&Xl~daM^%kSD71QpzMyB$7N0VJ^Ojxr*h~TgoO@> z*hj@D(y70xd1t8I1nRCk(k$grkvp??ivtyWE2(w z9!IJ=>Mgusc5W%Pbr50#hXWkJp{JuAPRrO$MkACn{S)H3H#t(S6PRe>2hK2~d9?VA zHtX!J!>1x@dmEp6JC$-czS{4)SO;PIx?`kujlS+Qfdo!F4hE$jnd5l}F;#SfI5O7Z zzb^Io4j}^H|IwhH~4_e-r{{Y#aH%ilW2M(*AOaiW1Jjb+9dBq+{4&WRsc|P#~hCyNgCN3xu zCWY)co5spiM8~l3Q2Eu9eg!=grNJQTe_SzaJt=W`Wx{fFQ%0n##YqvZtesuG?>1?q zPdIk>SI0qXKrvj;0f(uNaIJ>BqXc8K4my7lXVSJ7pjCw$t*!1MVS8KPN3&iX14}qi zSBtdmDV{^P-0FR&u>-`NevU0cnoMXj#p;AC8aFJ27E*tQiV7?aC#2IJp+dxw}TJXm|XucwC?eFfCOF|hkMdexg0oIz1UmAFMS zl&9GS)d$^BtL~^D4{r>zy+4^*jtM@|6!MYb9<`2xFk=*1epqM(Z&YMa7n(_q!2Xl$ z>vEUd@wXN47F?%NE*Tw~GX$sTbrNL1J|PYy*@{{Z5(==Q7CKc=a6Xk6C}fOtt35=j5lbMGE@8hp=dzo@Q7fv`T%q0@B1i=J6NLF1iH!8` z9Lg9?E=t9y3^hwj5SH?StV}{tDj(lUgl`Mjf(HdoSt*v1(vt^IP8%jiNHbOp7Ke66 z01vb0O+E?8eNHsFZ&$t#RBWH3~OBYccTT0h!ts zS`Ps_NuHfNVm6*2by3z?b=_d2;aMa6;Cu#n1ByxGBciul%Uv+(rW@9}k5ai`4vGxv zTZS$ZQHnt!XQ`nMvn)o=4~Ip6Wdd6XDZ!({@oWyC|1O;6SN4%I{kpqbwwpdRP>13*ZNU{_2bgq=b1WH z{&8}a9LF5X#b#-!=0%oTRBg{2?f|+Y4>xV@O4xVdLoGP*C|gO#5Tuba#6$xGb?p_l zE=9YVg3gi%Aoc7$L>@g9jp_$g`gzwLfn=Xmn8=3+g4dr z*pe(A2DjiD`$2C0hTBlutw0?lM2u%|?x-_-EFHLMDnXKi1P!`YV_@hzdIf6*=<}(W zdjikhPS5>Nm2g_DPYKN_g{;)&l1x%WCORkm*yUxEG6%N(EvD9fR%%pu$cjvOhYuaPFeRLr`7qvKF9rBHgm0CuEf@9Xm>VKzL0v=W3{8>jqNF z(y~06TLY|?R7X{co_(=X#_UFlZVA4Y{JE0-y_GqgS>>&-PL+v~-9*mpnKO%K=D}N=%>yUl552-98^#Gc1SW$#If3Xh6RG{pprDH@sVa7H`4k0tkI|DNf%Pr(WRf$vOxwY7iCu6g_cN8_;iCT4P0R~hf zz&u_oaU>9^O0cL$Db1Fv+XmG2iURGH{<8T;_W{8~Nymf=CO8aJj7e%kF4^T1ZA%N1 zbRGiQU%5Wp4hUaRP$QzdL%TqQr1ay@#*U9lbM`aRy#0gq3k7vJjs;&$T>}TXyf1bl z)JX#)Dm^Vdxnb8NUR#pdo*6|T8lf=;&B4Zmf3B<+Ml}b zY|QtCP=z6B2LXjZDgypaEahNe_YqF+Ds--w?HuJRD1`mj~A^gf} zV=_#Xn1EoCOxAb;>cLLl6e8X5fQM2cE!&7vu2Kt30H(^47pJ;e(y$CSZlDy-g;a%U zxfTvB$NvC5Y}iHR`WN1?5)*fF$Y;4q^eF|_2r5bhrP6jtniR7RXRhj3uAfd2<_mng zQ)ayS#cQQ#plZ45YGYwLQTd3FqzbGUG)w>?z`LDUTs+dy>#A0gT1OxGK*t652wR8%thlB%Y=doTu&676G5+~ zEPJYd=944lPM=Q;W4Y%ubweMPI;yGSN{J!EmKAtEn^~$o53RB%2-+0sXXb>Gk zZ6UH!tq&+lo=Q}p$`Rl~LuoIaP9dJ@#i>pdG~-|Z7B%1NOAqE3Y+fZ@&7H1QZVC{E z6a_q&3SL^5A(BuFigpx{_MCiauCIEB>sLfF=ku)d((3$Y2Bx9u#8nkk7`M*Tq<9-O zbp!=zc{!j!eFG~6m|MN)9i1j zopJQb(EQz9B)Dfz@I23+XPBC%mN@2`qN1Kj;*EFGZ;2B78R9p+z3oX7>g}FN*WN-C z-h_|LLurM+N<(SXja}PnF0-itDnqJK0l+c$c=L9%jITeYxvi|^DDRXa7Djj8*H_c=9Kglqbcx8+#I>Ri* zWroQh3`+JqKggPK4>sDhC%bH{&wUFdcR@ufNNRs&gN+sIO2Sk^nKtn$dzAr{>!{SIZtV^yy=?b_0$a!PLr9Bu3Qnk66DlA!{{Z>$}l3!w+z9zGqoUWNj=@tiyX5&=MOxxgL&0M;Hh9k^MmRL4)h ztMKTlM<-v1QMB~0Nfg~g#_Qv8dK|HsWsI?nLNt)27$maj37fe(YEQd<7oQ6*DL~+b zY@R7l;ClFN^Q@81ozY~=f780R2W}xME*Jw7f;M|Gio348W(+*_57pLcjiXe;GLBrp zpi*$+bu@4lj6$0n`=nk1r?thxfe`3u;GGz_G{UV&F!Ml^_iboi2qdoGyId0Dl%y9z zuxE7a)-3mBgEH;q&BBlEhR*eJbr~CWJ0q?MB&GVqgDznBA5HSyQ$`@dI$4!qt($!} zl&2HMsb+Fyf;21@3EpJ84M8n(NSiCVONG@piSEc6d$kga3Ko1SRoCm14(fy z3Q9Dj1iVwDQc%x@DkBzmM<{uQGNl$*t){b8Ijw}Z-Mes-mXPX3zU;XI2nq^G1z=(* zwdcRZKO^KXTX~Xd2~IuJuQwXRD3%j5GGh3iAN;ym2PUIkdmc>J?qah?8kWW`^>uIylrnAMJ=@y;u){SRQqsJ*ZB6Rf!-fz*mJ{Yl zAX8HrqEj zg@MrFQj+45;7iE;kk@hj2L^;7oK*zHX7r+#kMR`s$wz@zVWNwsxE*xZomLl23{W&{ zc_vzFd1g}_EgWnjrdA$JG;EQ8+lxwfiB49^lHQc9#i){mAp%rN)KY?^padsZc9ktM z5|nGyL9EWtmcGb0VNV6>zICwD9bbuhkA)>`N=Q z$GTU7Lzi-;Zdb{vLq$ZjaMRMoTZ~lC6*8hJgvm5^m6l?F7a@Fj8hKA#1URe;iVBjR z{{TW|z~T{sQVKv$r2b(_#RRrg;zeWTM8(+6GDff6Q}-yly)G?%+LpC7Y}ypENej}2 zN&##tLPYSPD;KYi2)#f?EFo7pvLoYd)-(p_`r`<+q>msiK>T zov$>;HE(%$E~8KN%UqHNhhyPzd1iPC=c+${tz)ick(Vdg#9AGQQ~_?^Rm6o-_RC&xMys72Tz zJ=MGd6s=_-XpZ!oQ{gE{Yq_j#u~TCv%K~B!@VF8{Wm>g5=#h?*f&Lj@956InGdH4s zmUO>0;@xS>U(KlwSECeq>NtVd40W3>|H&sSNZda0{m{%*wt1MnFc#sPS_O$tyzS&QiUZe z{L)#bsFIdOM%lOs)80COyk5edLexrK!D@3)cGdteg)S3tl5j4l zQ#}Pu9$L=$Wo1mcR+Ph4SBgwq3Z90f(CnT#7T#=uiB8B3&lIs~aJGPKsKOSJ3Sfd9 z3&a(qtbn4OYjCOLc!j!=2^E~rZcc5VU0uCmptP#$!PF#OuTyQXn7Biz@1+V^`w;_H z)e!=OK9TizBK5}#%ow*!BBaDA@P3U~<@$-|qQfbpOlu5+IqGX;^C$xtUO5-aAbE_} z4Yt<}UM1TS1G<1MsjOUU6d)wP{gx!`NW$qv$L3~a9lRUAb-N2;7o}(}=WX1jDRK3a zYWkFvHgvv5u%w-0bO8iT!m0jwh4lju%H1i-HI!I(HP%j&;S_j%ZEZFeO+!V9;gvH> zS2bh9NY4a0G;*w-lwIB_R$15=s~<*whFqe3hk6zO<=G zB!882C|$+%Hi9fun*-yKxh}KL8d#y!Iwgfhm zgz5=lGaxynBfC&43UyB@B&tc>eZaiRu5#zpri$$@GX=OyQ9Jwg)&N*Fj62XS{MOC#OO*}Esqmr&h)p5?oHWFcVN|kxI~L&-!}0>#eL%! zdWr)@PU`PcRpN1EM#jzpm_12)#8$qk zVT1@;P+BNdv_4rX>dZxic9u72ds@i>OH--=O%NPbpt7Qd8&b868g%Gss9ZNB8h3QN zIL`7L{JG_&xMJV(*K2Tsg*Jx@+3s5_T&yI3wWtRQz$sEh*1H&`WK&3Gh%%!Mo187L z+#RZ;-M4Ui_U*}0ln@~8+l2hj?%P>Ay;ng=QO6k)cKP+v4tb&yG^-2AGHJ2i?m+Iv zlm#GK_ZILv+kzyd#7G0A3_QALtIn|5^~v?8>UbRtW)>dk+J)5FG%a;2aMmK-zKaeQ zDN{4%V~?Li{`sTZBx+EPPDL!T<`^ffSoWJ8>{(RpA%&N~je^8mxE4B|5?r|h+2@Ae zUOfi0n|AG0p(po2*nVAAvah6Wm1Yl1{+F_@W~RgC!!wsyF{%m==Is-_cph2AXNr*4 z%I=a=#VuhQDW+f~NBbb^3=5e#`NHm@;nB58Fd910rFfZI3LSS)3qr%Kn^!cC5=~%N zXc_A}@19&+m4_{Iwj6W03ISJF%%M(qNdTqArJ2<70Vq;-orD#C#e=H7PwUsLYVL>7 z&ot1`;}T%lUL7+!6xlLTq|79;qu0tj`J^^7HJyM8yg$p!Y!~j7PK2p&RkVO$sX_xrnbCh#aQdm2cblHGCde@=$SI@^9Z13;Ys=)!1>163%s?&RwGtk{ zm6n#3sFZikt3%pQv2kwiaFT}B8!Z(E?VburT5FnH!MslArt1A;Qt#aSGz}?f54;>}#WuG3n=57W2vSq0x@hTDvfOR7C;+6TN=h}j(&bM!P`87E z4Q1Zq+T^?b!rNl<_TBE`im@c6q^GRjvCfeJ`V{vVI0PkWqhy5#R6t#_0U)e9 zp=mwR61P;4l&HSKTw#zIQw^T!A{Lcl<2geMC^lr3oZa>;m|9cZ0@6{g>E$+3kaYs}ou7JP)K08oS)ZeMdMvS*=VUavToOExQyrmX6y>bV5nxCp2G;vP zuo(rBq0k9?NFwcqx>y&C7`>4|^d%ARa;rjGe$-a+&5U_nQ z)N~^=Ve@A0p;8F&T&smW3)IDl;kB_eZ$Vz_cEd-9pY)U$xRC^ekTk~o%VU=~w`2BT zDM3mFXhKe+^GXVM64s;NveRu88>8MY?GuLGp>{>9I!c?rTFe=K5MTT5fqMiV; zVt9O%k~B2Z%mka=ous)oCKH#f2q`F4xkQ zrvbNPbO!o4f16p_IBe3jzAexKTe@uy6(xi%Qmc2;>O+qq1fxnqLSiPHGS{P?zj`SA zLb`vSx|JL`qX~mBVX{?L;j1L;MFmw;Q_vAn8;jxv2rvg@A=Rlxi(Fw$>7~h4*CP(YxN!a*oq?M)uaon|Bp#>QIMBL3M4Q zEz-fnzT0Y)IJ6@Jj*%%Q%5uj;dVke!p62YE*F0sgY?;&kqvzSNnhIP-iiT>scSXc0 z=nX_~A)Hh=3nWOvEpV)4K;k<~mUgfAj_5iytS42Naavd*A(amCYH?098%ar92_M`_ zl;IVH_uJEVkX~C{)bBof}(pS{OT+?N`3w&Kd|9a@07S{-?pm7xhxSv3}Bc@36vV7r@k@9r~o1>HQi z89+*iShsPf8bb9YH%XTgn3oa;AYniTC7$5ST_oy{sfima!&8f5*+)7^h?I9o3~(n`S6A;c`UQl{NQt5Td&jl$B0 zf>abdiMo)GQFDwKSkcGTMp(5~Y(MaWllm!Be?IG-8=6 zF+q>z>Dr#Y2L?Kb&ex6fu|fsG9?`F|+?4KE7bq!K!ZsX19eq_ep>3p;Eg@-8(x65J z9iWaqb5_^*TJ?W8*8U(F12<+2RqJZ83`uF~C$5=gy3_*`vpqt(hYH5dK`MUD+T4aS zYew>>o9+Tz4Z6`0p$SOVkVz_S)FB`f;w?F&@6dF`M18Skme-q`c-t)mB@JpyTM-2w zAOJ>^M2u1l5x2uNa~QrchVLB`vK;j_HG?dRCLE^6Q#N?%P9fdH(=! zY`p68Ff6P#{q|L5blc%6)CyY(aVRQUw1vinCA~-hkV#O58TyY;JsZoNXTYekr5eSD zSFUvF_A5;FlvAvQs2>o66Hl9VhAPT~VJw6)1GP#Q_qf%tv_g{C?0gP5$yU2POG9Y= zo8?YC>p^F|DO<_X(>ele)VC654MzB8SD9aSTqTuL8`OGY-ZmqMllYr-rU%3tKcsXR@@UF82t5th-ahjdI4L_KVb3 z;u~6)uJ=;O8dhcXt!^Im3)Hct3RqTwpe08uKAi0Ba?2dX)eWH!Ti&|L)B*z3+6gTs zT1Lc)(lscj8CL;D^)+tMkt+U)P=(&M47d9_G1}X#2EQBfKuRFtws>$p%tU?_E$>40 z6H2U&ja0*nQ_&=-p=D3E9mjLJ>wQW16W|XC^9BNtRR>|%eVFscv59VD6I)q&F7@+Q zQrSDCxdQ^G!tmO8>1nZSLK;?%y-VjD<^qV7&IT^@a$`|bYM!`JacAB&N z(`MZ%ahIJyLeiZ{8oU~k99jWN2=Et|A8x)h{^&H;WsaQ!Tl28+O^I83`?gEh-yJ z07FQ+SwSUk6^+K3bGgcC*3zaRqlW;lk_P~Kb{t3;(Ek8>kAoA#Z&%N%tDh38rG~YV zNS-x&2f4W`*aNw});=I!{{T*$$<~lmoCrN0e#}QftOU+es&Mx6goD0!?ccNU` zCs<{u8Mcb22&@KiMm|~}Fhr|WBU)KJ!0l)vCGYP#ouGzt#pPYo!tAT_1!@gxO7uVg zg(f^DB*-Nf3ddLL54uv&t^Pz7ZrP_nH<#zaKO!npKL z)^DingN)@&sh`W{JR>%FgAR)kh1RBOSdQ10nz#YIlm^j*Zrg1Rya#WW)BaVTJkYXf zR!+Yq3P37pVq;Ngotu8eC;VNL*Y3~zUCy$_FwN=w({BBm{4T)SLx4ihQ-G2-C{^YB zw^BMc6j`sKxaC$_hc=`@RN;mPq{Lo0+DM|SqL32hRh!;uz)^pETyq$+ZP4FN$dII| zM&i&PxuvPbz?1wWYHtB1Qy9P|v%^O3Z|cc)u-(c=)h9ysz%nHc3E3p8h7??L=c|uZ z*><{<1NNk3T%L597;;MleUKc08HI%$(YYs zzt0az@oG#-a@X>A#AP)SPl^?%bb6@dO12eIGm_>|5n}{fXaI8~w=*WX%rBJnz#+C+ zLdO!f3M6P&Ab_n!L}7p&MM8V$d6co1hU}HC*PL1i+1;QMI?zBVCjgMFc$z(4x#62B z_1_p6bCXAk16df1sYw!K4z0A0czeL@2i_Xob1^qL?)kN#e=sAIBf3v*nJvskcF$X^7w;!BqbMrJkN3*I|B|vkg{Pd3ug4z7_%gi=qsFoReDodWxc& zyCKrzU@3EF~CgDmZBcIaT{X9Gd+Bcv4ohw)r)@`8O4L0db>V~`TzGKd zPUbdv)}UDn-)gnZ$BP5uV|x+AQwBEkvW4hOfOd2P$E5WU!YIi4Wb2j>(M<7((sct0 ze94frg$(!>aKM$qe=x!7c9~2J#?e<&%BfRFC?Ll?NY~m}5q9rqmpik3&S7Y+F0!df z=?4WNT`5{*D0v;AR7t;koW}cQ?pe73N5q9~(y$C4EvZl&QdJOOf`{sh)5dc2Vb=N~ zmT`x~@G8Mim~uvKqy{+gOf$~&F#JXX{^eH;iRINmefoNok|z5gpQt^^-y0s$GSuH& z5TvMRc?Ko5feURzsGTQ)21W!|&X#kOKat$IWpt948!?YoAwcoqXJUa09u*3{4A-3L zzZH*9nL{}B8#dzjdsD{rxQ-`FoUqy$a5|GV{8tXlIA%MDLX%-nBR(O9)yC#jj%jGz zN+FG7<^8>`YuJu(^`2Ljt1z^5mu-9tE;bd2WIP*K1+_|Hz?e>zrBGE_29|Q&@Ulh2 z*GaN{v8ChzgStc|VIYqZgau$hBT>^nEo^$nmwI`VdbgP}k4Uov=De$gVl}k5PB$$V z$+ja)46PhBzbn0rD>{wprLGiLPOmgjj3w!m zEOZ!jW$7TThN)SklBS+e=*SSJ#t(;mvSfSXo-LGa+v#bbf?fg6<-+8R3Jw$~glHut zC@EH0mO3AkbMy5( zFk(5o7tT409BeYSf;wQhbv6luVU+OJ!wUf&G;+HnXd#76F-B~*5zk=VmuCBqb$NN5 z=}V6#DNdJr;-M-kTGfK2lNyzXJ9=nW+BWxC?^CQJEo`*I2nk9GLUjGajUbRDs|e^S zR25Z3IB3|rd!a!#_5d|MM><9sP+rK4V`OyoM>{JV)V(543c7z(crnT}eIn`3DyE+h z%iS`{Fyb_<9b~4dtd49{!7`8Rz%^zfgNIsRD?$Xibm2sJ=<%pwge3ax9A@pV~E7a z8l|{jmX-H>W*wT zG0%?E_a&_A$uHRiCFV9II%USr9p2H1CQ&$Wsn>imOBNVImL(&)8cGskQMMzAA8^8F zQfI^}-@2jFE{JtY)=x?L?U%D29ZS?4hdq1~(v9slCxgjHP_Iq8DA`2xa=)1Yb_=k` zm-{xw%$Yf!LzCZH-L$0JIMSAqvXPZ^T3=&T%ifZJRe{v95s93CYw!AOw zVT3O^F1Vnc>7@`!07|?uCWSk$w$quiUHd>G9j=mL~j$AW%u$I=9 z3`r9>3=dY=5H_56&?$*i76rEhB9U+!%o_I>KHK&`(ZPF5k1lyM4!mnrnZ!Yff)5OM z5O!?$3N_d!CoVmgsj=jhzp zvo6B$W>&4-2^x|K#NecORFl;*Nd6;MU-(M(yz~#(E?K3hs93P9*pgsXM{^ZJS_4zI zro_ik5RGmDumge|rtsT5hY5kJN~elXhH&cugFt-0gFQzY#BSSnclrMBy`W0iA@uE- zA9$0}f@F0LiZH&ha&`yl>(v%}=$BEj+N?{bcx2;;#yJv`IBRM(yZ5 z*$2AAw*oodQTc1VX)xkvNjnNviAfws3E>@7pRQlnbN-RVjTk# zm7*Z+PSI7foBA(Dgw-UOUoqi1gAANro~jDb6wHL!EZBUj=fNtCUN!^+?<*esOKq8{ z!3$|Kq?(Km`-TrODDk;Y%)v^gAwfM>$euddk|y zpn+O!POw6h)U?n?Ch6WustJ&VRlbTooo&I6T$isD07yuYGIeQB5@Qb`H5%_O^4;Z@ z#d=WM)!|BY6|WtHKnVx05GixkZl&}euh3%{ho*+E!}2Fhr8rhrp{bE)TFU25n5JQ_ zaktHr-nB27O2r?%iW#(&++n*1G_;a6kWQ>srUnzkQN)4NI93yG@Lp=SFK!&~T}svp z!SI#DPLsDlIzc#0s0>9`ub{lsiDi#gkC*f8>m3ecs*?@GVVVyzS<-N0rg*o5v^Q(6 zrEh<9@?pC|9AFf1*hdbUhj(`2>s-zL^9^c(6fsc#0uS^^5&Bi}^vfVe(fqY9N#r|| zEwhM)Ooz^TMsp+xsw{yOPwtQiT}Am3-b&O|cI~X6ux%_hhS4P>0oAwRvt>JHxam$H z*o`LDkw=ufuc%<7dz)C6Q>BN*9e6@jj8K)V1~eSDP^HE&XT$EkeH#Qw{JpFdiDIjE zH#e%61|7IF8bIFZGHw)Ix0k&+f}vegV(25V(G36 z&`LbXh}B?_rSj$#B&w8Du^=kgr^?2G%uBqAc9p+K#E>@JnR3;lEx>e@0T7-E+kpP~ z@#qs+ue}${WY-FI)wH7F{X@KisbdXGUf%*p8U_Jsjsl7AN4D2=;+raC_2P>c#i}I6 za`bXJlMtzR8+A@0QM>G|JsH0C{ZJZ1BC)sRVa#e?=)cB_MFb_>V^! z#)4KV4_p3SWQ7ynwn>$#K+2Y)c%7*mIsg@Uo{Td1>K8_H_ED~+6|hj%Q(`L-0p*gH z5~DF;=2{Zse6<+MGy{!yj74tih1OiUWlpNYg*{nHPFq6VHia%OTkek zG`I6=8Pr}MI4|hbeWV46v9~c3eRqW1Ef#jgAF^;Ltbn23CjtmK6t_5@Dlj%wl6jO410P?MM5nV+>ZD35hE!%)`k1t-z2(0)L2b zOz=?t1%H}&QAhkqzYor%dSlI)&rve22x>5lPUjVdI8)0mmt!OX<#!b~l>o8(ahnrj zUDDnH{TS|PfpTGP6aBSrFDmMEU|fd&X7tJVI+^b1fTPU!VDZRqS5JB zulaALI8`PYo@T72!Y8X*%rd5*bHhZ>7+I0_ku^GrMcJ0>0~Y`=)@{AE?-q38p@N3O ztZ*ZN!`Fp-F1k&)0dfS$JO@ni82VMSW0=JaUSE$hLrx%y@=S&qR4>1zO)JDUN`*-~ zN4ORDT&XJXW|wrU8%iHnaJDUQH6Velj+SmMX+by| zC3;RHja0W=a~)1{>UBj5NGfB)m2m22uvTS5=1R=KkXvyeo1Yy>IFV@hD?v1XH>vmvFj;u z0Sj-y@dhBrUh%2hEh*R*tu+r4thN$Fj#ZS9K?WmlSm^T`LEv!MXrTp5{jvn8Vdepy zJrXvg^x?48>}9OGmOXjpSv@r7X`dwZ>m%N)3&rY0K3*jx3MY?cL_qGQn0w&^GWl$^ zF>X^TnORx6%-AhFVPY}mapN0( zdPdrU9BkRF>%uWtK>ql35x3h!12;iSiDnvAm-5nCf4gUa3Es{y2ZGF&}KGiqBA%?As ziwI67L<)q`vg8h^^*c=nxz`q;sfMws7iBFhaz_E)R5Vc8LK2|+qyT+}=Y`j<_xA;7 zWXGVuN1&k-uMXs=fEalSw!cO_KZ^wEPE5cvQh>PqYvWbn4#s#QPnz=NU@nMU#0dIq zdD5N0%T112%Va{FCBy!4kv@@G0g~D(-pQnY5gL!0%={vS55rrey%6=6*6y_Dyz-() zgAD&W`4Mlz+sw+#C?-iy4cvc=lUkX7L(O2lnYkO>AP%#tBn zMkjfbjb*QDxA35+Qj!J@oD8NVAt(5fA_&w3NUHSp>F9F`>E0%tYw6M@c1X=cNNQ<7 znwp+^kR*+aOlo6QH0b+YH$otqfFK$1VUnY)ShgJJ z^t4qe_DZ<-pl~jZH>o20Yb)dYyFk0gKG$tt!4lZv^XG2zb>dyfJq0Z z@Wb9Jcg)!t-LP9E6+luBz-MUn*mwmBr|g@Uswk?Zq{LBaOmb|UWkx<*MeaB#Y($FJ z2gk7emVfOAz@UG@M2U_g45`jxc;X4fM5=F_>FD!ae7SB;M@tM>}-!K#=x@(<5su&q^P&i z?d3A{=zRYGiape+#Nq2q%&fSSbdcPB`yUNXpHGJ*^)FbYMKvmtT8KVYrwk-Xb0mJy zRsHoo8WDSY4Y&zmX2tCa`&BXL#B;)sj{(NCy!>fB9G^~odW$>s_Mgbfy-c2Jx*&my z(PA6?%KSY*_fQ6JIuYX=F#X;hU9J(`@QF`EaZi{y^@G(!cT5rX;0_+YFW*G-(SB~A zY;!i%VkSqY$LcAmY7iol)bJ<}NGw*)l6%8w?k(fNuHcaAeMfAk*aTDdiYp6ON{6^% zS$fBV;#m``a_3B?5@G<9dW(iwj@<<4$^a55ZLM*rHac=b&6+H%JlL5KvBLv`zs4I6 zNToVT7FM2&MHDL9>VBs6LY;8~FpjRSnub|Q2a{wMl2&1RZbj4L0Ombhr}>@WMj#ag zlg0)l`cPHEE}k29gr7`Lvt=6`XAs1zI%|#e-#20=Y+EaQvSCv?pxs4ON6XYCpXC}b zpra{1>9zC+lE`^o((Rm7t*8k<-Ye}O?IVHcG%_oe)`e|MLFzjXUqPZ9m{y+-#;R$i zXAZInS=FrTGW(MS0>aO`LToh`)0qDNnOlb3QRy@5#(>ZQiS_l^XjjS^V*$yiTkiIPHpidNwx#?R{bJ(% zarF3|CF)b8dC#XzFqc+v(^lcs;bVfW)a$w;L{IHfjy!pdEyauG+6ew6;eZ6eKs-uF z*})`Kg_hkLrh=FE0#czk%3x~$061e?66Ge35XvC!6J!av4Eo zz5F%rrzXsqrX!5>uPu7T>4p&%PCJojrNr7? zJc4GWj!^POVzRV?DMr>(K?u@cnUlMB1>~;X#?o7LKf{QT(X)@P6b5x=qca6N2ON4R z-Sq1`FNwBc05p zrp~NjxPEQJ>gh6uX2hgQT85fRfhH}1PSZlF@_vx~-4@`X?nqIzn+{<*89S}KHhHz? zHtpP?IIwk1x|WdQmS%hhOOSDZql{4daL4nOtRxKi2lb-is9$HP_S zUDOP>iHz^nn!GjZDQf4X!=4A3)8-|brdgzvxI2+7tL_hGo;**!Ig)eD>qF2K3g3A6 zi3??G*uzFxO1a#8>0Mf=UkZSsiE^ep6 zf0ln%@OqqE&uWt*M!r+-B%d8Y_UX**?2Qc^(N{VnxMA03WF``J`Ogtp(Q_zIo*vpe z84sbEOQN_#c}9pZhw=7|NS^ z{iKAr?YSyYQBq2lr7USAk8qS@1`6RG}U7m z79EUZ(9|s!A5mEy3rev{@u^0h$twb(hQa^@504-gH!|+_*$+CTA!`$-N{ACMB{F6p z{jrYN#-_&isg^-$X;C9-Oh>TeRehoRlr#)beXtPEc1uj^_l0s*ol9@PRg#x~feG}!J=jekn^>UXz#fR4BN$^T4oIVQkPR~b8P|mxckpnae z>>qWMfP{iaym_;gpR)6|GYsAG>4#laEKv4*Ktv$_3t{!V_%! zZ6$|Xhutg0xEm6e5`t5RQ7Afz5FptWZ1f9*Wh{HB6;z#26%*mvB8rC(Sn-xVbu_R; z9MMvn?U?O}lF}<}S6!=g1TlBn^Hzu<7hl}LbR>k!gGs=6yeZ+RYMBBD5Yw5WvKyP! zmuwyG7-_=~Enk=}=$2Yk4)CA@EUReK;o_ZBdew|$)wtuXGl)}GM@;g;6I0c-L5+~x z%kv!rNpYwoTs6g%Xd;}PB#8k-3B*K>p0Aj%qkhdTnzyiMw1R-7B~Vfkv<-eGLIpF_I1Nu$g_2SPPi+7NJ#t(+RHUFRljB-i@S#cW zlCJr%lm)B@8hH%i&zf_1a~$Q(O1H{HGocDryTzn1fE3!lXb>bi!h%$Q zONpFlMC*2Wd`A$>nfD>gm_{+y%qRIq0%nP+B*1bu8ls*&LLo^cw9GMSqA*KH0utpJ z5CU(d+o`m#LUac;H~~RoSdb7@t97NAaS2;*ptiJyHnWd-m<#U4RvAMUmteZqQulpv z1UN49M~PWwUE)ySHmFc>50bH@DJoGT1?c&%o_e3hD=0(K({y{Ga3vS|9b>3^ygdM8 z7tJ)3Y|k+pk)&M-DhMS>l-sTMkQ5Y_z>?DS0Jd93q6NgZ6mCfmA$`zNlD_02)gT29 zoZ};9D}^gG&(v4rY#43hfLC@B=m7%-1S=2$*a?59%+kW5Vux%V^0(~Qy8 z9;EbAq44^A*MebPL8iiI#NdjGrw7Do)}I@qrNbaHc{tL|<``zt;6hoLY8buen{=&6 zEw`%?;$#gjf`ZZ-AD9VHF8Ba-FSf&LPzhEdFv@IBa>iX{nWQaN&%Ku^OZ>0D=HXn>)_+A~F@N7PoR*h>YaVXk4 zYFC=S%Z^-A514t9RPGT}pu1W{W^wx$#^t`{A{OBt(iEiw3&ky$9Yb2wfS{DQ8eAz- zf|MYcuETvD%CZOl06yxL+b+9k`-(^hfK&ryPx(PhPB@h?R)1*O{KLR^dQ+x3wRGBl{=G9(6ZzwBlsA~P3kJ+Iytxg3G?y>^g4UkHM-`!9l zt83LGKDoaK!p2i}>`H+Odg;;#hSYIN03`}h*(l*dljAfv=UjbM=NwXjW1VvrTfu4M zjUoLC($<$?Z&YPfcJgCN|b z4bAVp`>_Y>1H(&lP%f1cPS8xpne?uP?~{R@O^tv+^ujRm=%mGEMBeGwcNY#wuFxdyA4jnOAA%6Kjo^#h;%M!a)v}v`HHD7ysF=f5RjiC0} zcvumBIdq>4^!i87+s7IXGW4G+78`l2jxkP=Neo4h1vmGF+Qf}MD}7J1fmL7*G7mhO znDRx-pi$2BHSi+x(Kt$oFdQ;Xt2=ENreL6ms8|uCVq=Ysks1F0!VQS!U2RTU zxRjr`X&4nusUVFh3Q@q32?a-DMyRR7d~d%cV9^mN@7^D1{^Mx!hASZ>#G&^PI!F~| z{dUdu*}tb=va?kmn(*RTvoB%(YZ}!J6cw@}M(80}o9qK=wnzqm8{EgqdFK{Zr7VRw z6rxSRolAXb3sFK)PlOTqkcSCQrqirC6OLP}mm@E{-DVX4w`X$Xe#pX<(n(M{%7@%X z?DZh+!(dSL*CS<2$?7jObmyqpAmBEMF9!c;?Ph-45$miZ@p@xU$Ku?=0Q! z7XEQ^CAJdsoI|cHrRht0l9Ce=>A@gl(pC5mL_Hf)^>ryS_Cv^!VO05(F36xRFPMX2 zxV8;p7Rv>i5r`0mL#oU~V)oRdfR2{v(dg9=`mmj(e-!k)wH*P(u!u5dKT}F*4OM2x& zGD>k#z=}i5*Uq8(sOly;(9cTAjMid!zBf;gC1TgZN-!0w!q$TtqQz>c(Xje@YPVMr z#S_UZ5wS{0;egHiC$*KiGF)1LQ-QY@Q!XI0W0+OYzC_+bwg&{Ci*}99RJvPf#cneWf;~9E< z1+eCx6{r}tZp)@yOD+;CCvk*S;Po)FKbm~Xh|~y@%NgNIHrC6~rjQ6x)`A<-tArO7 z<0Va8p@Q0(DAavDFY~9;?zFV{xbHNpN9FSS%{~;|cW6nvZtb;&CqU53 z)hkq$icECR7t46BsJ@M7Oo#H+#=oQ(pPv|)4nnU>OIDD{P_jZ{6IoHokTi{L*A^fI zoLFT#d=ijBI_=T|`?u1gsZ5liMga+0RQicYOQF|VQcm-`cbLhuTWh^a(VVrU!^T67 zG*pxjy?QZHVFV#F5M&ye=;IXWS5LCvM{@R2!tk6g6Y4~nt21L2Zt+hnSfvFuRSg9- z6I8=5khNDgr7IzA!DAqkb9<}vaza9cwy83v@KQs`Y#nSnq!6U)LW8M!UD}6stvVC- zk8gjQy_!96n(LsBWa zZ5nTeFv3Q9i4-m7M?etj1W#=g?bHDqiEmR85*unHAgdHBPz6p02F!c3It&2foA8y* zxmx?(;K~DLQ>!y335Wr(XTU)+FePc7qIQwrGS$tOeM9vPs1-!me?n>DfJIG27i-~k z!b0Kd?HLHyCMRhLI!EmYG?Xc_k){bBYHi|6ZB8BXk*gI-+ftv@H5QVh;v0&rn-`fq zj=6>J0+gv!vmy61#5Ll?Y+6!*#eEbL>PmR&vyKZO)GkoT>^{xI3^fASU*6Nh#QX;` zZsjFNXn%Xxvz|OFHJDzOZh!AG@BURZQZacV5IU;wP~bDT3}iw#Fy2m@cv{1^6f%=D z?%4;1A35u+Y0Vx5Mw%(5k?Q={E4h`1g+Q>evnH0ev>T4cixdD%bM5Qsj% z76sFnmEJh56fKD2Bs#gBSUVGIEN*S7we*d1w11X1R0au55)f1;yqzUWONo+F2yM3l zgzHmUQ?44gbN*jTDO3XfW)cBci9wbyARveXiCS^#;&QryhTu|l`>PabM^A`LH$^bn zVra!8BvJ}mAY=x5vUlwo?01!~_B>2X+8RnG8-b*VO}GJN3@DHb%NoS4OKMZ)WnZyD zQqbN!We+->qb*joAPn`;LGKAr?;gX#*2zD_l%Ri0fCs%Ebr%NCIJZ!GeT-Deht|^O z+&ZqhYI=%jsYH2hs!Hl9sv>wKf0(MKjp-mn+Y3&JTyA4|TRpNCBq_fGW+Wu&PNW5> zcmpnlDSDKa$q7hxa=l4ZBzM{lSi2-y-LwOVHjcK0sVh^OuTUCsC{S8cp|=#5-BPtU zmXx5A0|jqcJx6pCp_Aua;<)7|WyEvFWx=zh4i}2$$S0YMu~emI4PQm(D=gH)MF6tL z3rlCz-FOza%G|nrE)>B^wQE}~9Vo+PwMwK>OxoO=b6gi}l0b79{956K}C*|DFg>;_|$XHGz79Z3eqEcc5 z8K|gvDygzwTJscCPl;Bj6?8Rwf>X&W{)%Xy!Bs$^wzhd4%V9bYQV)PBDG6G2IHaKp zakZ7ERHo2Et=0$n=9+6UykY#ocWxlA%EfK>2}nv8ncl(BhFUVy%|@qCg#OXBr->>h z9fIcCd7+D|RM;!ON-zvB7t5VG$+)W~F+q!BFs{s7&9Myx5V>mDswz}QfCUbq01jF& z9WJ0jUZ8}msr017WyHp|REReUxbUJo-5{mNQm8|9my{Eiso*mgoo4GZzG`iqw`E3c z^zd5LkS*5JCt9Sar9{b6`gg*53x&_sJTKF{^)G_eWh~f&7^<99Ra7n!L}c^nuzxxj z0>~u&9`O?*tFT_peB3&OAVY!@@EW!EngSat?>{V6DG;R+=lMB8L4F95L%r8IrO3-dU1LK|^Ra4{6Z5jSE>R(c;tI1t_Fy+7#ZLYw9rGrFu2YGBoBYtOqbqLn53; zLdVUjO_7L`LYsgoPjx@M*0JF`DR`)Vbe&`%r}KpW0C#jlVGyGQUu~I*Fu&TV(M3Dv z(0a>ySsGUI=AgiMMj{U7zmkNRZl=3MEHJt~Yc3OXE54u+~{ zq@a9H%czc>v3US5Xlfk1a_O;vS;NLRMIa){cMLOd!l7sltss>a%G(Mpt3nijTx_VR zrIJEbfs_&|cHTbD7~fkr?wbd^Qr6pwN2~siCl2p-3%q-~jTclkM z>Mu{QY_Fg2%ri4%nTlLn48XHyFAY9ghBzofSL2wDBJ}SiNySA=Nli?%qQfu|$d?Sv z(bEN1N$y);c0f`Pr&QWffREZ8X+x@Wy)G3r6!~x#)DoFcNJc(n8^fAp*N(qvJ$n+HSDOD~pD+O3mg|F_kfdLi)$zgdm*ES`>kQ7Fv0t(cIgJsQbDF_XCKsvOj z5rVX71y!0EcWKXM$Zf6ROF$_pQYGil#Y-;WH3StAjHCc+qO(p-$MW?} zMh}g{B|TLvo^n9490Xrm8fbz&}U;w^A*$rY#5KJoaUF;Wil+J0q_wvMEzNGZe+ zXYJ|p^umIj}t5C5gyabYYYQjlbjAd7A z2u0g}%7-;1C0*JSy$yr{uI}oHTx4oW`{&AGw$>8r9Pc$Pp7!NMAzB*^ zue?iz;^BEow{u)R&hcjZ&AT>Rv5_*jP@8twctV0!QtI@y+e#@xF$L9>2>}{NfJsI4 ztEdzoiRMMjnTw^kSMrQwr1_fy#4@D})&4~hq4SA+KA@RaF(pY3($+dOuVq^RwkR)b z8n$J2&LOsfl7zLX!~ok)EVbOJODrKpzVQw!;d-54b`qiztw|GS*+Tmcx?!95JJz!+ zTZZo3OM2b!bijEY60I%xQic+sgvyMPX1a^i9zgX;p0N&|V>xoGFHj~rbEi^HEj*FI zNmqr_>}m`t=8QtAS5F*idDTqCwyOYc72RAe{lRf{qxPyVsP};yrB5qM8kDrRt+j+U zhZ6IOeJDs?h(X%7Lho^HQFzmr^A|3rV^wUn^0DjCZ;aWcYUnWcpJ8C_qN$XDYgqbR1NM9 zUOE+|EV;41^AxQl4YjMDXRZ@flsEFh3Jv^MTaA21p3~#ZowRRA>->5AE1@~%$#HOS z8#eJ6&sRnsw8e!!`k)X1SdBCw0DFUe;P)N4V(@`L`v)~F9-oIu$A=MHB>oLK-!GcX zb0B5RCYlW8hW`M@mkz~Yf&|3s;G&EzW)JhzxD<2~!{#jR2xiCBy?bPwp-&!S>9$s%KH#{ePGZS)xXnftB|Qc)h2l{|Q-|S6 zh}C(OW~&USAOS0(@}mR`z0{h~mn;yoZvmu-n^Kg5miw0*K`pEg+m$uCZhSJJJ zBUoNO?!RRBS&1y(+$PP|(`|gV67XBL@3N(#>w?RAS`Az_36v#Yv{?lBV8Zp|)QsKG z9*N?eM(Q?B#_)XeoFU7Y9c>kB!&iXMS(l@RM9dM-hp~XvhT8(eBNf;fjm>fxZpBZ< zqlwTJEhvQo+lgT*Le$x5Z6QvgQi$$eLuqlsr&Q~T(yOwZmfw4GHtg)~n0C(9S2qY- zVNKnkyTvRUMJ3^{yCYMD#DJ|tY)lG$zCIhLc&(B8YDAnkm9th#~MP~ zY&Nw|buCJPRo;1**kxB&St=d0zR3^dkiPX73QeM)Ne*goCfupOT-FYyHL#e98+|oZ zU^y?P{W|HcRiu%rt8zYQuBEEPYCo7sgU>}%D8_K=NGlRJB3wo<(7oBDiB`l0I)Pig zc%JbtXi;h5I+U*MdS5O$+FesNtf}_W+Fa4!EF`69PyD7TWqYY z^QsA0ZOtfBr}lTk;`-I#zsu&2qQDv&!i*5r&5_qVFk@Q6bgir5BQ^c zO7&BhGwnxJI=h<>Qm~1b;q>{MnlwZ~NLHESt%4?XqK#$^9B(5ZH)pzhI6up7ZP;;X zWnt13pr$X=x>PH2>9XI_xBAStk0(rYGr7~gD%Ij|XSUvK=q&^yIisFF{4 zD+RTvB)m!rRHv-4qWO*d6#AhTTfg5jUx$9lHtHc3@mi}U%T8~+kiao%-%GlB*8llA_yRZ zA_&9?AcYN}f+_6BFaFYHPvyf*x`j41VxJIeeOJZj4uF%$12x zlozahPprf0Dy{SI;IU&EX2nWKYaK;RP9Q8KmtpdYx7bx2h;$OYN-Ain^3vC-YeErl z+K}dyxo}jc7KN-W)g(F_X&>bYQ=}d@Z)Wc!cJnk^T(+C9<#|#ZN8oy`~KH^OmZms68UA;8wMEPy{vD1mR%|Z2`9>2&(Zd_3%)r0t z6GX4DC}(D{7f#LEEs?0au&|4Dkb=tLc8V;r(J5@URKjIiK~pMg#^k! z2fvo)U^p&W)C9_3Yx5Tlg(*or+RyBpSx%xzNEn!pCU*6kgV5Gsn6F+ugkci1eDy#P!sFg2-Anc=UAk$-mQ?!GomWhf6cmz&5*G5jER_~+l?iQs za+D$)Y)w3zvv%$jms`oRHLLuE;1ocGBzFxUjYJOR61Nku3{@0tdS&VlJY@cm;u+Jc z+1C%xbv099c$RRV52>bVN?b1;qZnLtFyUbqN%2ZWQE0E^BAxPGuB3%`DK7WVJ>Df< z(~50ww&tY&N2#km8zSLUjXzlK|&?qidMvD7MS39J5MA!&XUgD-JFD zR}1CUKP4!(bdxLo>Y_BF6XF#|_^$M$sQom_{XfeY$@0(g9H_X41A{FtBOOLJB{W54 zr=K5X1{7wAflnxv4Y^fR5pkAMEzsh-g*7C&3R*2GU?qC>I;K>uYgc>_m6btDWhoHZ zCpxqIP=w3x9D@%FHyZJR#((ys#q(g#b9b@^AxyMWg0}P z1AU!Xlc^@&?wrPL=-soJtGsE|Fs%+YRG5<6sZ(wwl}G_-QBD954%xiId+4c?r z8p@5*5QjzG(`XDS0YSwe2UN6Llr6SF9jm&B{e5fd_rCGy<-5|ZJR{C&X zZIoJv(RF0{t)5PysRu&ADOw!ch&oiZ;sFGhgR(=;GCaF^k*(&?@ES-`2$(RWf~4aF z9a>KeYL>lGbwe|CTQuSsmmhMo);W|yjzVt)vpgqtfEtzyal28eBbiCMIYT)+C~2XB zL`fLO0IWTe!*5MQ+tjjBP@Dh&0X+kO>J?p8b5uoH^HVdViq{>Q!(CO6b^wxY4ZHW| zO`#yB1V^*m)zKSk1hXJWGgn>sPfh7chc;KAQxQz`b$CW1l(6ojVC2Tk^$<-`KhZ*f zLrl)U;aiibc2>N-7phih3YrPPBros60)hyW0F(&=V^OXwcHWDzn6;(5h1)5o5b3lH zhjl4GvTaLv=t>HJQpy2dkVYVoY~QCikKuEPQ*@G}5t>-mj;9i*uBh_q0z8PuNFt|# zOSbS`15GN}l0vcMmuReoL7hoZ`--J2f-!`y4C>XUN)xadIM*;)OMy1R^kxbE>HNh_ zsg)fhlF+n9CrKDMT!AEzlcx$N^%c|pjOOo9nWLp00<5Q_z~p(WaENh96=|xgspq;- zypRbcYKqB5(AujO8*G~MJUcGlhVtff3rjo^bc7|o_rgzfu&pF*D^!$@fF>sj=&xb+ zZ|0XwF8x|mg{(K<9}z&slsHr19ukzOH-@dG&_C4dKM={8`aYBO7c0_qj}sLC0L)g0 zs1?$!HWwxSVo7q=H4>O<%!CCL@}u5DNI_x@&2fBhmXrjyZbEf|a=)42;U|5t%R|LW~$uokOINf$2%W9snFD`1MoLXGJ>aDrTyxSE9z2DXHo4dIk|O zf^`N}XhHI2M*tIb+z)01->$fWEYZx2 zRyi7!8jn4qQp&9ELJOaDf#)3G-Q4SSZyvSESFiTUNGWYfTC~iN)T$CdC1E&u#ZCA3 zc`o&&D=|-Yw5Cebq7a=>2B!f|ICw#bnZj|pPf;@A+1Jx=NV?^Qe8e#}2}4C8sF5C{ zejgdbHK%POmV+WLq1V%6J%V^NmdzFSWa%1SrxfuSG*E$qLK_VXkjPMXFHxnW=&W22{{Iz0N0IMUG* z%tFx(j1UkGtJ}j{2Jq8_M8@24=hCEj=n#F=@Sk_BWHP}l;&&|Mlc#|o3+?{^TK)VF zDggpH{nV@|EmBWURwHb6`;8gCnss-lxbI6VJudp6!|JiFomSPpBZt&bG(#85c%!1D zV%RgyXx%48RIQ_sh-#28y%h1qGEZHd_KSVlwfE-jJZM}8nI;hGM$BO7aX-MY35iO9 zNy8L-PVBDRv=)P?A*+-KLx+gl3yfnN6^@d4f~1tp9S;0B`cWc(JgCjRX2issi>Hy4 zuzxIzs)c04F*%ugG2KotaJz+==N5hSW0>9$GP^dJ1WJqQF03p2)V5N9Jl3xvSW%Jv zFkD?7S*^-ZI}*}$7zb%mw8ybqeTqoBmFV{aS&mrr<&~vw$oRfs%~*>@4{}sua7IAw z_D8pn8~*@N`{Mo|nr$N=w%x6huxizhT~BO%He_vobaCZ@6Dmyg?L?1lF-6s`i^R;7 z{RipgpWgTBvB?i@LYKxZVe$GnSohQx_dGGYi0EN~?fsGbXi5J7LhrjE#)o!K_fe0R zhCUwJ;hX(F`fK$`fzxB%Cau7FEuScF7Au0{wY6~NoJyQrt|5h1&+}8^^^uD#^iwm( zHj>jwuXs6^otgbk7DBDJpHr9;)yqu@!~Jd6&@m?+D?&gp0>C~ah+Uy}0dhbX5UZE;rNjt<+_Vb(d;**) z3EQDch%enwr%cB%eJajW8e|Yk8#0Y)65ITMND?4$&g!az9ejk7bioO&wY{{RfH z#Oj;T{Y6(ydg)6xV(GO=sjH-y~>xjbq;X?pfX#xVAbU8bOsQDOv%=Cr;9tB_Ti z>L2_lAJaw=f!F^4n(URB@vLLWkWw}(^mJ4rSrn{qQ{_uNL&T15%77OF+msvf0LZ%& zdd}sy?ru_2g#~Fs45*~c5>6A0@!3#XJ2K21P)m-qgyE>CQj`-rQz0WAfWeKhVt_m! z{uG1MnDAOU9CxL()$^q^QB_KrqOut3Bvc6`iwDcNjU-@7$9CEd+nZm5TaLwS-*rwK zn}MlBl!72hn8%~{QSt1BDkV+45+sz%C?sRkfhVs6(^DV*6knL^m*Tsie+XvE_Py8syIZ@M! zj4PwqbTw)S60T;h+ArVqYXZHz4d0qQgk`J1zW)IG&*AQ>tFo0Wc&%XaH<+yT1pwCuKsa|R7*)wO)|?I^yw{=c(GHvO{_+`aCy3Y zliKcu`fr$h)ew~=p+P!S6d=hM`9&UN{ho}Dp;fNlzNr=-V zk+hQ7$#J&ppcl9v1eQI%9z4uOmj?};`~^xEZ3h7=iP$i}V<2#nP6Mlr4BZyRo#?R~ zyvh-wmKvCYHS`|qf`5138u$}oZpVOZ^_Wr}+aRR;N1h&_RI|BPgdxTihJ__*lQ=8F zsRNFo*Ya^qHAz;LiU04eddv?%pE`=pyN#Zes=zTqv zE!wXQpvJm{!PNiA^mBsIN=CBlW$M;`x(VLj?vVQbOB4WeM9V zcD!|QxFW!k-yRI}RIcfUu6XGQTw?@bKHiR;YnT0szOB{H@Aq}%5~VG^5~hyP{xeDu z^AUB7WGv^6M^hgVNf z8%=aeHO!jJ8B_15Aqf*CfH2{X(s)w8*DqPJkEgDY)_NZ3WmI)}mbfeDOu-)3wL$$X zd4CVGhEzjgUg}FdmN8%$9EWDryq!OnN@UEqqr?n9%>r=#k?IC{o4tA4`P$U{lqo~@ zDgKDslA-)XWB6mhgZ(84tY1Y~rY(l`GP4TIlG4S2XAQI%g&RghMmoWgt#7r)l)zs5sb%r+i>Uh){m3AR@w%F9%nE^Z4p2ERzz?IfCA+;KC91jk5 zbW&3o4T@mvN4chsDE7*-0M=355AoQI-UJVBqk)g&qvYT``TZz5tIahS7n4CusZ=Ie zR(VPfE;#=Hc4uX<*vtSW06T%ujvurpkT0f)rf#Umc2weYwKGLgfmb_9JE1w@2SjG^jKv)swOr>Cj0mg7Xv>Q{eUR?L-P}G@J zssITa1ax5l2sR^n#jC2O$+^0EY$FlFcQlYuElfh9hM{4N8bVe; zz{Z!=tN|yO-;s2M3^FRq5Y-fXmj&7OHggqr3MD1 zw529cQUEF%l_?->k%b5U0E_qRDf>7Eab(B+(JoYg>T^8O)*LMj}GsiuW% zqKNrLm`S^`mMip1En5Cr#Vxqf;U9JoV`!X7JO>@MG-o&J&Fva-)H+;aQdUxeuu@3U z6htL6#FK_2ja%R01?p0xs(z1U$T^OuZGTE?1=?|9aQdQIP|I?v63l@~_E>S$TY`mb z@SQ?B71xIutToR7i$HY0*dpgxLeLf<>Hv6v904)IY#&Ot40UL0BxI&UoK-Y!5N6OT zuJ1PY_ii=&&m=aqr6M@iEauFUx2Av`Q!iEEn8UnsD5k0xR*|#}E?Jp@xKZI?+G@*p-L5QlJ{78BY7gqXNE@aBI3bnLsCXu5}w}`0@ND2T)wa>(YE#Ht;zG%&b z>XfBGAV4P#K+YX;G3=>_FJQdMZ;Z(K)hzlC>F!v~dG0I&uQf2zWt_QN=S>wu1d^~u zz?xcjCwGuR9%BpNL1TR+P4CZ6UeH~pqPLJ>q)v$+ap+k%BprtuD6+QJtt*cSzgT1lQdc)ifnwCuK6_gE6w(E_U4#25o{_f=?8 zF0Tkq(%VW}brZK*fyCo5I%JvKLww^mCBEUQCt{QVkMT#kO;(u1@e1nlvC>Hk0uV4( zM`i?*aGH|e;HVKH$DBJS^Y_yZH zyNg2J_R?X!<=tdoj`g&Z6v-N3cSbx)Ol@gr2NHhGslfPU%%d|+>VGM6W@Aa1Dvg4F zrk$xj#4tGRuMfl%@a^iSr*5HDV%ct*r80e8M5$d3JV(o;^FZ@vhBYOYFvjwrx0c=o zPLJ-c_XVWcUxbU6z|f+9y2siz5d_8wCuqRpC>5Dyj#w{BiO_Z{U{vjnvHU~Unz{?> z3p-|9N)C|q6A{DbNTa8MilGu%r<_8qBF6BK(Mh>fZX;{0gN1Nh8Clc?{?Q>qWRPHl z@W70HxNxKUE7iJtw+O-jID&p#J!xUrzM^4yPb*_palk>t=-e~I0a6ne&Z0*g%sYglo3{O3Dw(ao36nY1|;3}#5Ta{|@?9&7|d}gD`+8x}e_s_jF zfVI}(-0OStXv|#=B06d<>eQR*l!6^kLR3l`l&_2*rT}UcUisL>g^|&%%epIrmJSx*kZR&?u)!XeTu(Gwi>sw7v7B)E3`n3q8J#{Sj zXlgX6mON^x%9N(p4(Vle_Y{KZ8(Fov1d9+)4jaaiEis1^F-EeBq%rj00-&Y9_o~#w zDrIfKL~;m~qm>w3qG&-@CfC$qFexg4Orpe%w~XVR*l?NQD8 zLA+{>KcbI zM}_0{nVSrjhp4%2CQQqRG;ySoh^-4_QKAp`s1gNwCX5Qzue#C^7c*|8xusg7NjkV= zI!y4#!MCEZ-QoPLVTFYZNE7@gXh%>Z?3@nC*+-M568`|Pui>c*_O(IFOSk$=1sj+8TZAZ{*4gNlqjd+NLedvzpBt{FYwB zDIb50UdaQihq9ua+0V#XvtRUqT^S<^f{wbQ9G7GhP*F=U3QdJgQ+Y6e zMaqq&xEk1t4K2v-*yz;f^izkK@Q;b8@wE{rqvu$#EV(9W%y>pip(Uins-UJDnTsq% z#`5HAxS%&W`z^w}voATN%XZ2C09;s4p*Z^lnh<5o9KrV3AI6|PHlJ`ceEIUQbl;{q zzcuCOhAA*w8a%OuEMsw&s}TvjFYgA4o<87}vC#9Xw=X8j-D*$pr$Ri)(w=&&Fz?^) zP*yyLSMZK{s2lX{=|ir)7r=72t$vha>6U5Yml3GOGAuJF9Sa)L6C-_x9rvfW1r2>)RfHss!P+IPHM9S2117{{WC!Dj4Wj^i#J<2Wm0%6sz@x)7r029Z)?y z!m6qtFX9xDRbjq)UGS{2tdECJAQqNdV!?N)1cEnQ-cyQGcWye+jQwE(us+5!8M zJaildX^U;{O27uqj?Th~tVW;UI$NZOkNUKSzIa zwU4s);9|wFK?>P2KOb6!v&as3dIb6OdQqbEC!VveCzo@7O(d3Ca*c9Q*P0bw(!+|Z zghf|HBe3~-M$#oKqW~{+ZUc9n<7^YB?#CXk7sqWJUuTk3vqYQnt zRI|Q0p7HL#RW??E>T256qhggjaRNb3(I)_A zW;oC@GG)cyC^V9F7=w(Fw20~9Lv9U>;n*cgVVRsR5nW0_lA3gqDPngX>&7)KFJi0> zy_fC-UDBK~oN>U8aI25mcvs;(LBNV1^Jh{rmS&p@>b(+AON&>>B^G6*nmx4mgs3)( z+Id2#Q(X{KENARgMqNn~9!S<%n%Q$v{{TCzY^$yT4h#vvj+{2nUq?u-k-q`nuJs!+ zeXOb*aAY|pk@eIF+i5;4fTvACMY#j->F{&@0viF6UsJgJUyvpQZvH|jwv&ilJ z^enPbBMed?13gn7p6P?IRqp2c__qpp2)s8!qx@bZ+f!r3Ni=pS0nF9tm-D^i=K5-G zJV)&uI%!=sNT9>#y8%Q zw5btAM-fdKPPY;HS*a`G`FZH7>J?-21C5)Ekx96CNg2JoFJs$@?=1fSFpNIoh&_EC zwA;;vZ0MjH)(57Hz3R);{y)*IMWdswu2WZnViGRnhT`xm8XC0!01cR!0^EDe6$z719pEI_U@9f#I{yrnEDv>F#>yByrPYlrM$m9IaO_7nrFfx=525 z37r`LJHS5lM_Z``Xmk`=+Ak-zYVn~8AKgb7QGz3kaPpBvsg@Ejf}gvtcKOE9L!VN! zRR>Z!Ws2cQS!#?iNJ23UBn$dOAprfgYZ7iQq+0g3CA`k%7uM)%^JKlp+Isd zvU+EVzc}>|46K_ES*j@EkX6i%!EI9ON|iH}8)IUNv0B@2Yxln)ZQX5mPpREAp)#U2 zCs7Cl^iIHfXg8Oyy;@46Rz9?BWDPa_Hnx=36B`tm7BCIbCF#<2W8DPyU@vxO1H zuvzyK0Ni7$r0zhTmSt$(KI3YgcLT!w-!1-Bw19Os`U9;i&jmOBG876(>IaP#q12(m z*x0EecpM~t6ghfd^#z?hFZ!{`onh(L8~om*6P;))@bs1U)zgqgTrsBQ4J_2x3a&od zrrmjsTf=4&pyEsvlD(2AWF9bP40+I&$>Ph9kO^`V)(FN&Ty)paQ`7fSuq?@!C^NoL ztXk|h6N-}&ps5Glo|>jHEHaII7|ob?HNh7LhWT>!B1fGI-vZ%2kw`AFS9JTQ`Ibz9 ziedEhd3!ih&pkZis6!mHOc+(uI!ONX&vHPGbr&oLeo59j+gW156xzIAAfzmh5Zfsx z366|9XcW6us1h-Q1Vr*Gt33pDCjj*C)=b;z$2n$SCK+av8Oo5h~Ah_B+sLrv;4(XK}IdzJBFginW8t!$WeHG(cTBw{Fcz_42I}T^pjC`XO-X}5)+79@D!5e!*JTF!`17q>lG1E4JmUWVWHJ~} zLDm2x&QuL^I_YP^2lR)!jo;zLm8tPgjL_h?^sZ>}3j9W?_g%oHp{J5z8Ywo~T@Huc z)cbGAJF`S8!*$mF((B5J=u9AbNKuZTIuGVf7F#MCV~1IfXrr&|3k1v2ze@UJFpXx* z`EG`&La~7yVybj9I8c4Z03WLN;$8B68ttv(AgO&&G&hHqle1+TEQx@p2OKBtOlrU1}{C%-Z zQk-Hb8q?Ip1Tn@clELG;Mq^dD`#>tj-Lhae!1gXMYHp>gYMX_lLE;{Zi)pF7dBH;yl93;f3ogx9%%p1&>e8XP_G>)luSZ{gc0o_!Q3c0fpayyHTLvJZ+1r35!q7smp zB&kLc03=D0AOa_4b@M6BncTdV>o#&BmbHm00IDGz2^y9_Fbr*q*(W+;)H#d#%hxQY zM~LE?PYSAsr_~bWx{bJw8@_qDnYj zj8VZzgd2h)mZ7Dbk1dpg+nZyT+AYTdLyp065{A+akO=*nQjxM$qBi15i8+?eLH(Y{ z)=zj;p{20ui;ko^;Bms@fYzm~gTSo~1T;KJRG;3sWB5iLiu%vZwDlCRwJjc8%Jea8 z!{cU*$qWo4iWUq4q<-Mj!Qk|#n3gtWb07U#s$QX~*T4$H~= z9a5HpXnVNqF8!;JB&qwX-D6jH0iNlUKy;D@F@e*zBN{mMxx+8zYKjW1GQS2mod-lS zMi8+}j7Lu?cdvhzG||&iv~_dVQpmGGOxG@ipD?hw1S}Sc+tvZ@yRr+5K{B@zQVJPH zqNdacZEAHZLXM~KN)ZmVm%ErHVQ721b3U|tQduiZ28O+ATY$8NoJm8E3=*gs0!#&l z7lq?ka$z}_rIobx`H6B4ACh`~iDK(fgtcWEfu_dss)fX4cofkB^nw{SlE4_Pb>^PB zZK={z4y2(9P%NcQgt(VhRPvp-P=NKR9phm^NOhzK5r}#B+IziX{R%@L%v`?AT4zPT zZOuV8w#Y1`Ecf0Q%ZZQyA#(d}fY`F+9DO=9V|d zDsw#os=DIXgp3yink&gJ<-NxCBL;H+0MELlra)43km6VlHq@<3OQ`Ntui6( zZ&{k?-Gd3;>v$>)QUcs{a0htlmmFRk3a3c^6vAczt(<9aTq`v76Vskh#Z~~79YM}m zp6{BW1>vEtT6l!YU}+Gq%L^>(>fmisJ)AkNp+A?6zVWpQ!6b9K`HP1 z*2p19Z741Ub8X9&*jeYd4eFHT)-6Vda8s=nt4Y=pXT3PIQly+nIF$jp6EIZcKA-xV z)ci`WnQF5KQL&22phl*TbadDjCs4A*3P1`XI}5aO`F8Iejm!B1$uHZC3b0n62r?RR zM25pdNq_knRB1_J#Q)`;oSs^OY##YJ#jR!y66L7!}1#zf4jl>bD;HKRnCyvg8>FoG*RuNylsPoQ08smoJ zFjHC?b_Cm^ZBoB#2Fl2U+Hke2@dq7R8AVX+-6E~a&pE_BQB4C)p!jZ@+4hF0P^b1O1p zxO6hn($qnQOCV!QHAJwMjpAj9`MWo=9l>wG-d|v+7;!Ctl9j0G?%DvIMF+vD=CIJH z@u?+RRjD`-6Us6NvyITOX|myPH+6IiE~zdp3V9+s#Gwm?1p=|7R*<0t&;ja0*LD+- z`hO2dsIi=4y1xdP(9+c5wY1dL^?7p-o6o@T{B7x@YHA6oDmO|EIFfr2yu?koX2w|U z!hm&34aSg_Ex@vbsXfXT*l|q5VI^RA$Z^GDpoA)=UDNEv%lnmPMV3;RQ{E{Kp=)Kk z*HfbD>tMA99z&>v9`{RAIzqsj1bPS4-njbvpvJRaf6g?$IO&}oa5&vd%~3qH6;*6m znUUmrtVW_|*t5+e>{80^Gz-PgyK9sv=+N0v3D!YUjD_g%re1M6#3(eCXw($FDInCH zyqVTr*;jJSy`ryk1-JVK!cdg9hQt5}0k#lj*pX`O4~Og&Wfi`Txb^){QSn6*)j@a#?T%6dr4tuob_yyvKq2_{)3dzWUpZOjJM zHsq0KWX*^=HmJ&!d`nutq_rGWu98ob3eJqDajbGXGi1XgrA>D#S^L!3PLO~=@T3UP zl!y=sk|wUdp+2fQ7uL-0l52tw=lAOu%b1TkhFy*$5x<{heAe__>zfQS}mqqQgx}q614$=d(XJprtR9@ zvE7S+{$Xi$-i8K+B?>@!ZmmS=eOf}+R|$}=?3skTbgw(~{{Ssxo|)&(*qro~y)eMB z%G^#ewfkxDPd-|TOgf?1MwAj%ouhg=MHVgY>PiA$O3Ve4m3TlmI4iw%)T9kf7WE$Q zQtg(Ip7XvZy-SG+GwiPJ^{o6`wv{U|xM8-8wJT#vP~*r0QGG4r;Zj1Ba2_py#wj)y zJr?zXdYoF4rx3;QoR3!n3B<9>^8%u>NGTzcZmXtKb`W4|RDbd}w6yj2?2rg*^B&ASH z0wV)I)G6q3UsBz9z%dHiWi#}ao+C3<(lkbTdI}d*jp^u&chcKqSlAsNKrDDvhtfxR zsU}PU7L^4+X8@#ILWwAV0vRCqRQXVGPQlqaS8tMJ&Y=p!I8o9P;7~%{coLwuwRP%J zmYyj^P~WN5jy&U+-r)ZL#y2NS2I~+;9HZW{=uNydvF(1@L3Wd&p0r0i&s}9ne@iz* zqWbUtR5VHP;S*L!@&r&Dugn8BRV4LRrIkSEn6zYKB9WRxl^WhROGuJU>iQ#GA z-frmVg8JNpc>e%+)*8KRND`D_RFF&|dlFEkC<*ZtINqE!rOimt2x(KjmTnMF?ekHq zN{9zbA_{_n1_NS}r5+F>j%IZJRfhH3tH_c^4HW$p!k(T1^2;TSB^XHDM@D1wRjylT zjjguwTGogV@LPI1*+^P@mdFJmSm+plL~7_ecvX=4HuTqr^s5A*^>yld2$vCtq6&;t zDCPRfYQi%sQo5yTM^Q`};F1(?G8T0@sg;M80WnT(dX|y_fR#_&6i~2-5|5Zg;_R_QIQxV=b9Qk11BDZ#6DP1~qBdYfwA%~uatJ{u;@ zPKBips_BP{R4!7m;?U^Q!%0_!=>n@S)fZ1ae)@^4S_~tn_}w)&FC3J0H4K6o3h`I`rMY390?AWn`qrAs3<%^@0RL`hb9t}p|F(dD-(YW&XIL1q}W|n zQtCDfQ-)2PFbwI4Vd7djC6Y=7!Nd<)3P(I&qcZ!7?!`&D2-*+}-c_RgC{hwu3S1+= zR3k#+#LC(SNo{^GwFdO9MYnY5AfDEwJwET$U1Cwfyy33p1>j*R1H1r`3J2Pv5{0Q<%Cxzp30OyW zAQ`9|w0wozLf&zfjW4pLy3WEIeMvp&2{7DVwv{z21T^e8Ah@a-vtAe1eCyRb@sOpe zN&2zTxG{R%cQ94d)(YI)gVHn+$ASLA-% z>2#2VX#_Yt94H6;PxAIb>K0qc{-`o2q(PdY!_UjowJI1=dN+_!$xlu^x-_DiDH56^ zx!>KI$JtW0>Znt%qa~P$pcWOJ)Avtl{a~lT?G?r zT>(qiDk*Rd@h&;ybi9S7Pbg_ee3b+w1sb9p!6N+Q3XQJp$IKyxm6VO38(A-Y{m!@K zt86?tdUMC+P&R7#??~(Reic6ljyiD^mD^A&l~H?#4PseWT@HbX@wK>_^QuC6J(1FW z9aLwP-U~&At6)CgFFu+u7(ZG%jfLcTzL?V2&qaaalBHDmY!dB;MnUehs4T9*b#3zqUJU4qWw$2#aB6p(Q9(0;bS$(v==3j6nu? zRl)icF=9T4db5VdH9A#OQDL~WOC)q;Kgi=y$mk`M8CTtZu@DmcZIl7hj{(Ge%fT@z z1jzx1<5Me8dbq^KUY(YU7lw+x;f`u&iKdd024(`1&=4*F0_A*Io02BoFw?!_fJO=s zP+2Jep(-IJ-6&)YMP3%tkdLs9NhX9}Pi`#k+ggY18&cZ@g@tHKixK-z9z0GHzySau z{{RYX$=B?o>Kcx>q&O?%bhVMC7B?KE$3&D>atMmo))Z*yqMTkIJ%;7o?p>@3-R5bh z5Eh~nr0Ft3Qc&zL;#RUiLKc@aEoEp43X-(_z-ilMj#-#wMLDCvrKFb_BgE-(v8Z=V z$WzKj3+~1SJXm5jR_eVLMa}fsmSXEQB(+^J$E&ERF^qEyX`_b`6t$*mm~r5%^Aq6M zG*OC3YhYzolG}*CBPqB#975DkwWbzU^eriIg*;q9b?2`bwUWbbG#k>O+K{s02(C8d z4qau%wsO@3<_xyAv2N%|Q$6EaP^(Eg5qEZ_7u>gS5|m5>RPpQQ(l@KGQn`~1>W@w& zpwHPq6!|J#7EBJdISffKoB3`Mu}kH&vr%pUT^eK>K`uPRXK++Wb9^!j+U5J$x%KVP>`fj%3_Lkn_-X2a;yZGvk+Bo zM?#BTP8F7}XW2$>pv}GG3vo(P5|p})MPLOK z>6z4&k*P5-K_E>NxF{x~tav~sBHJCdFa(Ws2T}ANZTLM?fy9HyXvT}0L2by1#ts}o z;n5XyKZc(`s&fu}9;EY?T(~Drx@Gd%u3)YAcT^Q%^teJG{{SmJdx01QcH2TO%XmjQ zaV{lET6F+YRe>N$R*(;N=t7(*QX5i`q$OulpR-D+9ook9ro%2yOKgzs_Fxp%vuF4) zhb|O>v2vg9rA6GmAKxeFyJh$t9@zikmA~H zw#!40nZ3pRgE?+)#ma5VA=@)>(%w@`O_IN0x7DXokmG>1q%ZbmIzmAPfh^DJkJ5%S zlGpI=&zQ|lX{}6S2FnuFLtFC{l3=v8sZ&Xa?_^lzmYp0yDj)KMG|X54MHZx@+>{sb zS`*(i@A)`k4=rQ6ZP3btjfWmfDNt>L-l^3Py)h=(?k<0AbN#WjX*TFAzjP2$p}}(F zMGi9nl_f3^TtdHq5ZXW_(xa>$Xu_oGpG&c<#fjkuFw%84vX2U&z`Ux#NrBMFm{L>J zJS??N&ZNm45wM7dYv>0Ps30%AZAn`D;oxZ@#38nOq#+~rfyK1G?k(CEJ<6NbT3cn@ z2={Y#oK1#c(=EN+D=I?Xa^q8d<sO~8SL#QnOtF`G zJB8HMW;~PBJlU287fVkwGfOROn3XhUKQ>B8r734hcuNol<0D&W653fPI2nBoC?#$) zq&E4`wdog@S*DJQ1FD9KhK8;b zP?4>4&17|DNXYkxx_FM^=F+7&lHqCAyV7O#sbQBC+8lHi)vYeN=9XVu+FS0F5BEmu zI?wl)B+56M&3R3-6JeJu+3H4=q`7q3-F4Q~OsKMfDoF)P2f}d_vg#L8I!L%SdVf+m zmOLK6GUWHbvrbXOm1KH+)qq7DRCTe%hBuHY=35F;xs;G3ZN}kPxLcObEs|DVg|@Nd zDess{P{}D_Hp~qw*3)Hu@MBAgb5T$#4dodoVcuE)03~3$i+j;=X?W2fF2e0fQ;iiq zHJ1=^e85lypg_dw+td*gW0KSdx`F|^K8!%PELiLD>`!iFy@5I-<}v5n(_MAX-$+;_ z?2Vls=$;r;4hc|cs*J@*x!tbKSGJAddt7@vab?1F2>f~JicOSWC%qnWe-DJ#$3BO1 zh9CaI`NpRah)UT@AIZ4%59ZM+UzEhYUDss5y!)dd2$O2}FC~dni+REl9(gB7QkzKx zmO+_PNC|NYdD+(`4X7XhTy+WvO=0(GwhLDDT4*pXt*>p=A;Uf68o`tuD1`z_&ZEI7 zzz{e7AbDHUO<$;d$5oj6ADMGrF^oZt)6-&@O?_2GEk-X=kk?aGDZ>;~lS548%LIFk z&*=kLxfEr$j<^-vCA9@9(X3oHuv~P7wn1f-u%%n2K`LdSmefz&kdTua_D6r6x0A4z zb9-B6no|l>Pd0=&i*yyVv>yETkn@Qe98?JV3S=Y{tQ!jSc=+{BVqZ%6)~gAUt1nkm zQ>@s_1;bV!l$bQT?BC66wMY9S>_))*r0I9h>er>M62pZ*m{bPS;B^6Esnc-b2faA7 zui3PdI)*^pzr10jv;Cs6OMw?HsakD>yj9*N6BvG3oD`j>?pPxlIKG@R=3m5mNz^`- z6~Q)xmFt8|nAQioo3DJusY_s;d^a|;{$oW|b&0K31nb+j~F{gt)D zebICjsVFIN!6C&;P^b;M7M`f2kh+I!a}g5JCLbT zv0WEkZf(O1oz<;>w8mO%#8l#>w=65f<81(CtWelfZQy|7l$DyBy90D(*4dU>{{S+# zucQKyk^xyF2Bj}anU%towjfPWJ~Z_a%4PtrzT7pW2G&l#Zfwdm&!i7~mP zr=zLFL`x-oRbf6?^TKtbwX5&}STG>3bH*DsGKHRqR@3f_BUwD#K z(`a!{w#qI0qU$hT?^LWIZOGjb+93XMyes{bEyOh?EVRl-r6_@nK$sYkCUF9vGL}d6 z5tcetoc{pNM^)=;dfg6Qs>ZOKu|bKuCJhAv43AMA3OsdHuX3g~1}&#|`rvvuGcC(V zWT7g!N=}3&PbtPfE@Wz3den!)Qs;GT;1=xaeb<}twN}hCOrHAw*ZF2zgykmX3_Wz? zKpT}ife0>?skTH&SRryF`_f8%F8(O^c6FXUiu%T(q|DfDa-?lrQ5Tl$3g2S1p6T+^ zM=Vu6_hNgFNB6tB?nZ#^vOD$@0NbrLv(idxZ2i*-7OO1g2vS-al7NJa zTl5lvXyQ~`Y=$w|`Hn%;k_PE#p{Ed(xL$2xN^M6-aKefd9ZD49Q2wOqS`^}xge|!P zSg20hGds~{=zSr(hDbw+;5OorOq3Wnz#66r5n9k^tTuxS#R#d5)o#VN*>{3Mg)5=C z)SFww!zYdy?izlee3l!^xY_z#{ma>uRWts>j zMqw(fP>N};uJ7)ZU8QcIu-mU5TTCtX(|3b1d(9fPX@X8E@kHQA!~#zPT#D`L=JLwX zhphX-rSumR%0k|4l$mkX(!bf2B{Kof2_#kSW@-<^Mvo@-TO!9KwGS3$rJkBunuXRC z^BH$lNegbNU>ZOpi*l&cfC1#3fs(V{GJv9W0Lp+=qyRN|iH$R>?vkX0047M|re$+@ zlw5Zr_`F;O$f-;OcL78#R~iW=o(G0!3D@;!To$EMuOcvc6OFWr)uQ^_qMx zhFRolLJlX}GyGE+MP_$n z&#BDZw$Xi7lAh^zfhl~i0P!KO0GB?}zZQT838Vd+KM$O9)%Q(sj5(!en6LMb4wW>F-PtFb^=%>eu8)?u5Ay8Oyggps5u%8Ek41VIHV_8o_e z*U>9?NpYmxtdxl)t^&63An@rU8m~W89X852N2pXC8^LJlx?$A32vf(F=SrCd36H{v z8F0hrIr%vq6#oFD$VheU#egJm!>GHvX-Hppa)CDMC%~{UEH8lv0i{@tshXVHajhsb z1dT1Kbb}x3cx~y^v~3ec8`1Bq{LdveC(x>lzfp&03MjnXHx0y=R-?n=cRw>xTUN@e z{Id@K04S}y-d0F&yz)ZL)GnPq0^6Y}DoNQp4m$`*+IWcLH83*jZ;ponO27ohB|<-h z?3tveT6+Hg2cwL0F!g`a+C!Q#YC46k{<31MO&qwLN0%K{Q+Z`%u9(P8qkxD}LZ_Rx zZOlJ^ciGCW-n?ZcMFw>!k_y}qu8D~_Cjqi)F7Vvw%a)Rnr(sOM#E996;fCI^R_RxP zR_BjFRn+*NB`zz7;aIIkB{fvuTukQ{g=<}cB7}w&mwAm;Z39cTq`?0Gml-Bzf{=8$ z;_-|Rd5X4RJVS?1NvwX%LCkI3Z0+t71E8?1J#;EOhgDV<9fw!c=1NRTjouknM2*#)a-BD+-$U5V4LX->>Jg=7U!R4G-X zR#vT9W2LB=vLwT7khoF^kZ!rS)j;eAh`HxJ?%Rz(aM(of!`s(iQOuB)d3-15Rq2f3 zhc0I9PXmmE6t#5-gHkr{y4+Y^>Ok$G@bKnLFz@D>Lx=d1ne&gveCrcb&*W~MWMQRi zfr;>wBWBzP9RT|&$|+-pF)K3e({I4vxd8j5TT9#@9}XlSs}6r!7c{U0k^#axJ$gE) zZo^W6c>#F}v|{ah>86JF@26{fc-G7Y+AzjskVfBT9^tY&Vzb6KtCa*rv=TwR#lW(Y z^!DRt21vU!y9I!K{`wY3w*==NuwZ}L>ErKG!|K`NJ8Mv`VV1us~@6-Y_K z4#FoB_m{S8qjRoRYkHT1iNXVTC~XBLT0tEI7{HC9gKSF|^aGY%CC0j;n6o-7d+=r4 zme7U-f;Lp+RrJp~Hps#kKBNj^tMx6@Sq4LFj+hIoa_+CEC|{OWbcKBjb#GfPsPfUT1_aU}{eKhuvR5m|bf z(0uvR92So^%Tb5sJgte!)YMsz0k4M;!fIJpb5jbaNiftZ{i=D=Db;=Ej4r(AF7fWZ zVY)XTmCV>(yM$^=RzBe|sR|O6rg)`91A&5TqC2U+*>3u@T+5zIks8zXtqC&$X*iCF z9uvTrGzpTaAqYz;Yic(Er(xRv07bR-a0|3@DozJU#~**Q_jSc~*N!n!y;*KWhM`D4 z@VV`8fhPKRb3+^=w^D82<>JWIf>4pEYw6OSfyZP|MM68- zzLwj!4V0H(P%1-dj1#j`lwc)10*RBb0%oqCEB^q(boxvDw|*_u?88@4eX>nOfYC)x zSO7NcmZC8(vS=^;g)>|^M1RiEhrQ>;%0sD0Jh_ zlY+RwJTbt|Ajl%JX5Rg~#zV{yq^N311VNlOiIN7=Fzb*-Y=Hj&@Sa?Qj$u&Zxf87Q zIE;1lan<3HK3<7qsuR!;(v;O403Q==OAVjDq zP8b;gpIXF0+KcJM+i;SVLdSVJbgC7#ykZIK;S*Gc=;zTNQ@vt(gI4nG?1K zF;kZC?<*NCuzY~EEBl%fV5v$Q1`q(-sDlXvo{F{Jxc&(~oV`7CzZ&ajSGw7V;kkPQ zj_&D}Y2KoGhf*nMX(9R1=T%g&+KLDR-jT|pvvU_WN46Wi?7u~eHb50(wRfb3&^E1J z5rn|nHq;W{{oUWVmReydTDAbL0s@pzc5q0?VI@QWB-XhZGZlj_=bAd$osx~@Fcl;@ z**Ckm_EJU0hfC{wb38BEH&*IN9w?rSQ;dG@94jMoYk`+vwyE$Fpvj-SMEV%O>^RO8 zXYo3CP<*V!Z*AyFiOF9O(lIs%PkU(Xsi547oa2vriu^jdt?0Us5B_b7;0q=tg$X4{OjNZ%)FZ|p-f0%LAXPxnNqgSIl9pWQ zxVLiNCSZ;_aRE{NEMpFmO>%d&hEC^iEtY)Ogf2B;KvL1+I=YnFvEu+u6TH*cex3do zo{+Gftl^c^Sg)v#sbLRMh10_-OCD9h>UTudlP0@yN#qQ%M#pjyyn(jdm$!Doys-yF zE$1-Rv^I}E3L_J=jywSa_K&{5+DTJ{qS1rlPANAJVX|>8ra%TEM**95>M;a~t7TW-&wn#?&R#~mueffJ`|3&I<-%oZK zHxMtleOv{!s96AD6u>3N5g2{37P(^oiB!Xm|4|uV&4|@I24xYmvW~NJY>Pc6q@-#kWn8tm|QBWB6 zEh;5Kc@M4iVFc}{AxOQ!we;5f54@dtQ{(n3)zj1RtTfe;MM(QZp(c*;cS#$0yT0&2 z7H+`U6~BNdfyD@;13M2q{Adc#Se^?&YO66RV}hJq31(0NE0Bo8%dm00Xn}6T`?n^< z+S|lnQDe&ui6%N|oOM#G2g0deI`t9;!}85EN%KuM=atz*2t<$*@6PFVnR3lDPAu!f@7N zu+q~4KS^I*AlVunUQ=`WILQi#NQ4Yz;kOkIC;QRx^D&JMUAdpWr`;vCk-+2Kwolre zAiBOIr>QuBonY#oE!8}7oy12Cz%W{Mp}{a^n7nipXxCWx8wn?ouO#x=7m$-+Hh^ho zXq!~V)hNo9(oeu}1Ea2#UAnu4YE}tI0S(CTBy0rnQQEW9!YCK2ZR*4V16@mKHSr*Q z9k_ag#RhH_tR1+>p1v?Vum{d6#=R@h*Jpa#{F95;3OPTN(a(iaEWu-`slz5R)GEp@ zQgF5ksBSzDeq!$QsWv4S4UJIh`^6E8Qs9K)gruG)@S%QJZmht&Y~r-bXf3213ffev z4ltpBfsJgF(fP2i#v{{Y9+Ghk(T8FkLdr{rR?CVMGOTn?rY4r990xPfp(yAzk%E$S zBo1J3!d3ieOiF>7F)<_fNU2{T-kWTtw@a!^$x~$xAv{#9P+*AFs7j|{ z6UHc1$Nf}#BlJ<#jDh%1^eYFW#qcR{80oVnGf=5fJx(>M@$wA4qNTR8gy=HXggaDL4LW{@NZ{`g5MF((ps z3OzJb(_q;3P6LXScc+-q$tk-rQVY|vskgXBn?Uz%ZrqI5m^o{4-KffBk8Z>As3P*g z7fk8`3{T=HH^$9Oxr9y_^tpmi%WA8}p%GVoPXgZbDX`vmB&H(Qtrx@Efd4sporJTMs zC(gAt&K{t%cS8EpjpVGc{HnVMYROBzW*jA!Fw9uT9EQ&vcDCgm?PGD@GqU~HV|cRm z?j7$E;7E-wX-Ob$BVj!R?4q07vte?iqe&CQOi#j<5q=`Mriy{`{Wc?)(uG+;j9{k2 z-8QfXvK>h`xjx-^T%OA<-CuaLzpEU3-gfMcilE*{P@O3#f&J}Ip!`lckAhXlQ-b2S zL8y{Ok*XxX;VBzP0=$gOrblg}z%7oq+%3l(?1sYNX>l&V06=)+1|UYjC#TtsXm2~{ zG74v>Prii@_;(Jfe=OhqXTmM!`Cd=;VxRn;-MhDJw(lQpwBURFgmSt5=J!ngVOxI> zoh|;?Tu0oW^n;nN|I^iv)fYf8_^?Fv0nvG5OcxN5zG9gr4dk&?AoAN*l9;ZM%b`R1 zH`8l#7dKycRj>Jd^p_KWByAwUo`rO$kK8zlgtu!tb6@1{BrHftJY#|AS63aQh@y>@ zvt859o~UnCAfX$Ik_v*zY{P32+xYTay|M=cr{(Y2h^hIfI%!ut6?0N-k{By#m?^k+ zR|Ff_4|UXr*F$wS+inn~q$_HYe58EA!_e`iW@`C;5dI(-r>V@#lYJ%nvq-8cl`8P% z%@vjM)8aU#Fn}cn88J4embDt{wG#gTlt2L`@4FoLuXGwu`C~Hxh)M+LDmaXgSQPRscg)!}v2@+2}3mqj&O zcF1M(z3CNGxOng3X4C1qyv6SMQ|#)G#)KJTdIy%?x%?>L<86jw*r~)E2p9-~+(3?T zCb6qq-MF#ZPiE7#xKP;PLIsec&NLY2oHxz+Tv8&bO*@!{LfkQlLEI)=?6rl#8Ui%e zULQ7^VSPNuT_<{Bmf_D`UBaNmB$U%(err>Cg!ztQb-9277FLeH*c*^8bsRH7bkjEJ z?_86xOmo#o_dDX1xTJMhZpo&s!xCVt-_3cYc;tnDn&y2NBGimWW&>182RK)BjLR~ICEq@hXFX|;eUQB#_8H&V8Bb1UK%xMxxF zY)Om&cR+~0*G-19rCmX#Rf#h$8f~?!sZa><7KmuuCx~Jqj?rP* z_7xi}U(6`g#oCplXI71YdU+YC_?Lold6omEHm%q>FQhI0U^QSZcFkDX@!>I8}IM5H}@~{g8Mm5oCW~Pme zF|bi)jgI9P6}%1W?OKR3K|LTIpYvvyXN&yh-M(B%I*zl`rwzP5+ALnN{X)>@A6R*U zn-8S^Ym@NGcyfH$TL6nb9Yh2~(>98gFi*N_X-=`qqxVaKMZ7mc?)5-oln{X!V4v1% zA>Ri^X?VQ^r@J92BY{reG?GeGIF7iYq10Tg`3DH3rNgS@#b|Rhrxe362$N^eVKnS% zsiiCXlZivD@#tffSxEaNgr5DAT7RTx&|p3E3}x=|Bt#h+he3^?@PlEAvHU0O^I9T zxK_j_2l&gw+$N7_svqb0Pe!utR-uhjv`}K1{{RyNfT<+KX|Uma31Kwruo87kuWn>c z`e!F9u|a{UO28S!nMm3F5~8W$rllP9dXiF|sYzM#7$?_J_fk{T=cw#oAM}CK?u=8t z9W@mm6)gk(NR!hHD-`E z%d<@b&lkM5Sy0I9p(omx@4~E;FFB@m<7m~6xZYE{?b@UXN}!&d zAd*K>QH*x_P#gF-^q6LTsAJt~&bvhhUZsvHCnDOd>Z)cs5p{+#2{yIB?0MC_%U~rB zT%Di>)6^qUh(16h^;SFXTOHCKx;sb>r2hcDDEunVb4Fh2C#qhNVf}G>r^NE!Y^!SZ zsaa0^FA*$K2}Xd&8vqhm+TmYqz1Pw>&#&6vHq{~%J`=xu-Pu&%gTrQgtsGAq_k~)ZIa%2(_<~y`Q-XVbmSeuh$VyLR=|&rg|ho2K0es?U|hXrjfZt;FMJLardC zM~Wmdhw5aOM8yeGTggTuqRWBJwpNM0*n6uqMWyg z=kBLwp0HF-u+w4m(yUUQ72c%#@u4bi-cZ)VK-!RW;f4DphFf5N4l4B7@1JD>w|xTc z;oG8c#3%gizVD3+y;-b-FlO8~6rzd+qokHIBI@diC8H8I+G`R*++9a+4j*J}CH+BO zbRW-zx{?P7pI&0FXYiNw)6-tBb+a(#zPV)T49|yT3?@pd!(SPmnehx^qmGiAXvqlX zmK1l4Z3P*c?XQv3~s+TaxC?JeM812O3MmTH{vP9vHZ4=TimvpnF zSP%7Mq`7kq%J?ai)IBB{O0@8q2mz#JU$o=^Hy>vP4J9ZLkObq0Pfaf%fCom+pD3nm z*@!^(6I7A4OEZhu8y!vUs4u)O`0>sGG}#i;4)DW?E}@k+atGV8U*s>8s7IVLouT_8Ns)P-V| z4TtbOAkgHt4kHkDQvM88y~=g>LAfH{-uBnqYkN6;5lB?u8p}0$L0T$iB!!K&y^ntS z>1%i3S=Dz}DOXh_D3rjbToX(%L`fz>(i3}v%x*921X}!(SXlySnZX8`shFlSSR5aD zY1vBn*;!BKI4eT63fUM6ewLt`c4un|O7>puYip;Ehs1n%54%s~m)@jcvNd%bp8o)k zof5pACPizl_}qF@bTr@=Q4K`$;XO6#XWx-C~?xvj;{|rMwdM!>3%mBPsTc#gc+lU4wg-}CNoh5F5fl< z*{-a{!0B)|Tya)MVz0|C&){ejwFfd^%^04^jG2cIm}D z8KRBekE78cPpu}le9vMRm*%qNx z*@3zEat(E)U*e&GNfE;xy!242(a`b&uo{e{@k)ovYiqB-SJn0})ozdGZ%@5YbX?_@ zDr&K+5}+^4;q_H4_>DS7J=OV2*Deu7mN|3*M;7JTOKdPhV2v_Q9x)%S3~Vl3x`MDa z!Hgi!N1w`}el#6-T)Ec{kMz43&cD=rHlj%}Dx786=g1<=*_h5U^V2on`SKL zA-C6X&BKio3H++rDoKe-l$50^7)(wENQtPG#WPib{H?z^ZYaKG8{i>OqQlRNuzuULds1GW5C}Rf0m2K?S9{l>@-y4hN!&3yxq@ zKFJ>O^Qpd#y=-CKKOIHr7h3Y(X*o+f6pI1E+X!qzrwpm8h|(6R5<-su0Jy?r)NL)c z_u%f&FivT9w_oqj*--A&rAqMP3P}KLow)3SiK6v7qLl>e1RAtqy zwbU-0bxMCteM4$`c`_y~TSGi_Oz%$&%__@K@Rk6`qyWHJ3*T>Z$i~xm*vhV4T1V{` zpp~rcAsa9vL=GEH0Pvty_G@;gQI@#mu)@@|At&}>YXe%xNl*iB%wi#341QuISa zV{PX)=1HXww{M#bA{XCp0l4!onQyqE*MXnfk(4R`NZ%P?+ zG3DHY(~Pf|>12|8LI`21kS6tpJW@jx&mjZdUoD6i*5q5aGB&{{E6DP@WDH&I%7k!S ztx7)MZ6>`+SE&o=5!OT+J0FOG<$19jy0a_a=dl`VzcH z?xdA7h}KAgBUwyfYIG*{BfmLk+MULi8wtdrwJ4AAm4~(~8h7(IR#|4{!cte=wp3Gw zF(wWpqh!xOJ1b@$mU;!qJum9NO!AZUh6+483Cfiio*hz{vKXSTl`5W8j>BqH7L+@q z6QbWz=J;+mNuSIqw=P>f@_W*tkp)SQ0tTXz028Q?N@Rr2&POYGmw$fAdHW{2+hF?M zOQlF_QdXqfEkPi%=u$!y)&Lb4B$S|%&sE--a_30B6Xk5v04D(h4z7w6GILrVS<$*Hg{Px$4iVF^`?%K0ABP`G@_$VFPm21P>TNzJPfMJg@}3t_ zLx<8=nrb; z`UC39TqiG3V$)%mD_2us(9>X;_=f<%@MH}6f{4}68&<_WAv9|;%Oqwg+ErNO3eMa& zaf4)1^}q?zu%w-8?iz1O%ZLTS^4MCIKy671W?We^Vu&y9vpvU4uLL32LKgCt^}f5i zo09_3&h07;sSF`S1qfJMNo=V|BqUO6)5oV?l=Nq*-8!bo`7*O7XAH^I`phPHag0i1 zi@}%Z0#*p>DIT1|2$Y1~JWD8L{TXl^*u6JTTrCVZqLrn=s#N1jK-SbD#G7?!DJ5jO z0*X|X>$eF+Ecbgis`Eavzf<=u+}g2~A>gJNK(}4vx|=FXfqK`Z6+>$%Aozk#kuWpe zZX29EJ9Rx{sD#bbUbfQHB8fw}ik?Xwrj95nY{7Tx^z6(o50_(S1)}lC8A<}YOFiLE zqNyRLVOkQ-l?_iuq&S289mxtoNv2fN^6cX;l&UOpC8(Hy6tIvIr7g?}kG0SNh}Srz zn*J_1u9rDyT*np_S0*CZ-g#(n>E1=2N}4a>W?ss0;u1wmhf&lqrlrjo zr9pE|NlQas$>vhaw0`@B)d*VqGB-^Wq~Nsb5J*UEWyaHRUqEp!p%)2CG&qzO3Wh01 zh=q68eC+d!$1?n_EF~zG?r#*>Qr>X`TI?;+0mmG9fUPe#C-_oE3I|WF{;RUjO0ZhI z(T`#@@Z(s`O$BCSrLKr#xDm$ilQk|N_&yanqhco$RuvG-N@ApifO(`28sv$xIiub9 zAR)yiPbl|lY1dF+ZB7&fEt`<)mER*ygfre2z*2NAIQzQ$hW2*iS#1g|vWF3Dw$J76 zg{{C#jSH91R2clU7Mw%D%ZCJ|v=osV?s|{)ADOz#TO9>eMO8iyl0zcLRaEs=wNpgC zOcj`wQ)^Q^aauT2NNJ+|90~>5hZfpdZ@FZ6M$&euffBBa1_S0)PeZIMEq6^NC@3zF zMx-Diw$h`iNMW&p8&bSZDE`sq_}wJH2yaa}O>-})9E*p_h9mu8qMlUufk^3F=Ox{# z2i%DE(0JQk8``Xu0F%IDf#L=qtrBMWnHCpI+CwWy6UAdd_o!CIT{Nh#q4gu_^Ag7z zqB=|mrue>UltojB#?XBF*VoM}JaocpVEflV9uNTcww++ryz5FTm3R_W;Z@Rfz0%Tga;N< zJJAQZOL(P3F|j0tB3!_s!V;FnO}WK}o#tKQzSO5JwHP-FCF1b_q?Zy?ph{dw98yS% zqwMWpPO{BNfm{a)!I)b{&@XYc_V$Ibx3FcGwqPEvdD%2kzS)p2mVxLydU2pr5{{I` z6bz*#jJ$-20{Db2D-B~?9S5|F4;~L%Dw22@8z-*;#Ps^sCEeYL{bSqFQR0IQs)8!1 z)XSRry`04z*oD68Zp>5JwP0&EXA3k4$T-s zcLDE$E?V~lUq%CM`59bWnDm%~KAl{Aw$%5#xq?H&c$nHF*PXR05?hr3Qh_7`h6e*rxoQj>Gx}5M z{ue`A6mOflw^uZUo`G2)VH9ZdZc{ochBsMvMeG(L@ZuXnKxxe(NkIq1%!G#7Op^ul zf=Y-|k8)s?r@Tv)F1=fpIsNO3K_c5HLPQ5hDjJCif)Gg{Vu)W!k%7p}(t26UU0lr3 zbrT1`ad{~EiJIib=Ed;EFf>${L(|}No1&TucQZ+-FsbtHUPS=hi>#LL@vt=~ym>%| z#*&o?X)wc#Hl&s7B`r4Bc45$`8v(TAeUQ&=vioyp?ZZKNZJ=Q+y9(6hz+Kajq&Tn; zoDQ?&`%t1p04Ers^tngV=AcXir|F5ePbeuu3^IvCS&B?UeOehFw2v|xYmrfZE>E(p zeF}$}yFe*UvP)@X9R(z*D+(@aHyAimBl7_|6p#=t(oc9LTX%EUFEy9565sPD7d`8T zRhVWQAO=T;ZeiUz@3;}6_8A0VIF_l6p2CqiX9G_LPbP@x4@`t+!huK6SYKxZZ1 zS8bB=jq0v{m%7rFw_YVTN_>{iu*d|Vl1d#05_|xRWE{XV$D|5;BP>;BdTyIREiErl zYAa|L2f|t;sjPN6eio>Xa%v+$MVtUByEXfSh-Ueaomi#&>x&oK|t=wj8aU!v_{H}61R=?&cYx8%mt{%Bp`8wOvYJ`mY!GmjyJ`RHhr=@mG-EPh=mY+{aEBqT21V ztpNSbEDrA2ef|`rqrA}oc!N?|Z1|fc$^t#RJJ@XdrWJl2{EG~je(gWyDY*_hyir7Wn)QCY!49Wii)cv~R|Nh7PMw)V;Reo(&6;9S;ME8WS~f}(bUft0-kiR z$3nj-6;!N=K9YH4T>$||e(K)p$x9anQ-pst|wf3%;$YPR@}g z4?za2{{R=Ssz;dZck==&s@dAicMwP*d)B%3SnJ`%?6M4c^>Z6ORf~6b#!sg_^iv|% z%9TvdAabCY9sR%?PkeYA5vHEb87ZL~Jw8-Yi^x_dD>HIrMFeWmo{0zvB%ec;vWVR+QISD`H53)ZZ0;#p&*REY}W z?+lWAlFnr~d5DVG<0PqLB6&wp8pnVw<8&tNEfPT~K?&~^fS>}E{mmey-7&R97Rr)S zI^YZJ85f(wVz8Y>7a6k3yRB(XDM(L!s1}rPF`-)a5-_8qiN}m){{T`wZKk7Xrt^A3 zhQUuQJx(cA<|u-JV+$nTFEgal8xJuWJCYPQ+g!hO^LPVVkO7QU%nyapdWM4_Ruc)4^ zbx+hbWuv3SFkEXIe7%HLD*U}&baTk`^HzyNe8wJSQxuWM@9G(WO%6(DUFMP*CQPTp zrck0h3Q$}EfI$n=O2z~vf@df*JjXn?%WQ1&t97V6+gS(a~V~f)zHDv@}GGwZ$q5*d*EOfw= zaccp{;ho<@PbuAC6%{C!LYgDINJ&U=sZMuEPNXHWWCt7yT7sYf@~+C-a48vs$}KIX z8d@DvU3JgPEUmXmKub-!W(ta*FgW8?i65&Tv*CSB!#a~gilsdG37RSzRi|H(r-nt@ zEHKg!a75|ulXB#Mcilq)`&P(HWw3#zK!TBgAzNl3$>MhLCsZ2AJDVJ(cFVI`2}`hC zR;hJlVisK5q7EbYM355%im@({{w0;!;=csSdFu+NN}3<*3B%{Fs;a4>mk`WIVyT-J znb_BUk;wAdWp#|V=@F1_P)*kDw|1>3Nl%MP7M*DdQejFEQnIZ<3rd!?gt&mHAgn41 z%sVi*LvCDIIH+)27gE|=Lx^V0K~15AfEkbni3PN&KzLLXVOBYV;8~X?^>+Zt6Hze2 zvR6d0nv5b@;lrV;ohqqhH4Rx5vq=ePstc$IwoQWjH7sG9pxdZZkddfJ)Gd;J#}z6I zQ=v-M;=)0TqJ*|kmfZ;h8g4F`%<}iHg2#Dxp0JmKRPviiZE4UOQc#t`o6@3HsTz!G zzyJYcN<2Fa%f5?gYw-v$d_JcY#OoxksyK3iC-Xt(FlLFJmuiJYstxb<7UA+#lBKCo zAzmZ<6=_I#0;L4BwSW?kV&N|W0*h!ZD5T37tBZZ@>rxP>R+d^oZ5{FO_XY$71cN42 zSt;=Gs;~S)YI5YgVVfjiwJRfF(&IjRGs0v_j6)Zy#J*ZV3J7;W6o|5H_XD#kfwYcK zS$m6a)s(0ZLUj?uYScO928%)P^nFYgpGS(zPW; zI{ZZ-D3dcp!=zn8$NFENFwFUt5;*EGx|Wr9{h0{`B&K0-e7T}68ykx&d$u+_J#+#0 zc(B9~Af)Y{qr`E>O$bhDZWS-U82e!wQ#z(5#OOLD&g4f?piBCowPRb zEwaj1l&s5Y;Z>XJgVcpLS24$zEnyV-YXX+P60fDhX%;m`tgUO*S59J48JU8tX&hl= zr-@cLg|{;eZJJhq$i*ncm8z#P zt>~x1wmV#*1p&`I3YI;nIlq2`;?7DI?({=Lc@>}Ro%E-L?>RoO@uB?-^V|gXE{r) zfCbgDq56ELJ|prxKt_xOi8WvRq5-a9;v#uA62@M)NC&<<$R--GW{(} zP}Yo35v{9iIT2u?g^?EUOo1u`Z4m=-H8uxj`J$}Qyh@a$w*dFfsYNV=LVMJ;Aqq-T z;&q`6qXtXC2@8sM4}0@1#mmiwm4mO`T-{u)9pin=EjAt`txg3+s~ehJGZRLktHSB!FhbPQ zOq0n@0*@*vWoXr&C0&oGH@Q3=e;`w#OH+<_iwo4CbR>nHY8~5pQKY#G(h?FD61_T- z4Q57D*+xN=TOq4<)7~~h(CUVz2Leh`xhGPVkfIW@bqol^0ai27{{Y0tBIg_?I*dbh zU(GmS%(a*lm|Rf7MGbZ~kx&TE6EFHYK}!djCirFZUCw}RV8Pp~8>@AfF;a(mq?Bk# z3vn%i14>C@q$wy^S8~8~sZFS^T0)bGIqzdP7K%N|58FBUR9pv2mg1VVDt3P`pV}3; zy(!Y-JG7)@FbFLEzddhee6x-xLOKzeYDQI{z;L{|Q&|;7NnBbiJsskjT6vv~EkS7= zo-jcgC?Ma5Sx!=wsH?@K6zLzdZ&FaAP`4Ueu7G6fN&)WLRH+C_CS(o5+`Bs~Q=Dfk zAYD0d^}}tcD3%uNYD!j+1Bd}B2vPf>^;W+VPYl&==0-(Q#0S-vQUKb<$52nVwe8G| zN=j1^?AU(_6+6AU-YeA@oHp_E#;kwRm#(g*`gF?}{!z)z8&YGxBlBpp%@;s+5Zz)S? zafZ?o5a*6UK#f!P3;{?pk6tuct23rGSBoYmQ6XxX<$2yiA!!_+cXK`Oe-UGHJLohR zqRk0R4S)bT2Rk~rRDu1aVXzR80ziPAA_oZBOAMXVjNyUinjGI%Q1uc}0kqFEf<~dC zSHAQB9aw4&i0#7Lt0tapOvVZX5CGZJ8$5=}O7>}MeA2Dd5|poQl%^!?QQ%{UI31j7 z;vxJ~@N9cD<-Fyb^3+gbcvfeJFx1J18K|1ABB1_Wly{_*Bq?FJr`Tn4qW}rKPMzG- zsYNWP!T>rH(J4Sc4SvNy#FiWkw zc$7A$nRUMHEu~H9Z@YK}B@$J0k9g(;2uP7tzv^Su4r28a)tq;&S*|K-3|k(SDP@kH zogs}K5Fh~u*=?h7{{R^z_tTPgUu0NLl^s~9k`k08$(#_{QiO@X1f&GitCro_c7K*N zmD#OILm;3jYSgJDs}gtuc7H|!XqRF*q9*C102U!bs}QGfCc^&!nC=g2a!qNO!23D) z>@|(~ru;7Pa$-gjoBw+L_zdCknTZOFpV{2TOf7^&_Nt(W{5`&kb4{QB11ADk7+ks-B{D zu#uyQm4Sgs5?qES!Wz1@a6c&orD@Qx94(9%m8C`!tzji6!zh&$D^w>*mUoYKo!-31 zF3l}VWAct`UwB}YloTzrkF+g7h;Ye7VTij2IjA;c?k)lLOL9X`jI zS`#}_e2qP9;w#L#o-eY4Dx^eX&D#rw_!tsQC*$)@M$(RpL3a zCrrU4xLV>eMN3ln#W<&^si-lyVJ`8wl^1pQZk7j$E^?mig|t+nRI;w|$GmEF3PYtz zLy1{Z!AWqHe%nY(rD>2sJJH#$SDxAnY`8OMr2bwV?!wmEEtjbYM2IOMzz6Lrr=z|fSW#*#@PV9 ze7X)4!G&UQF|jHX$-i`p7(1XH)o){MY%OtrY2k~_5$udGfO`4Hpi`P_KD=?q%C-yq zDZ0mk^!uv#1eM`R!(C2QY#GWG_uTj$2_ZoM0j+@719$bOEM0E>0!s@+utcU>aVrB! zARJQ$a8}MZNtvsE&+?b8P;paa4?!Y&B>Bgk9N)#4)0b5;-&N{5?UPkzqQvSK5TdH3 zV9XascS%qI8^dF|OO2x5UG=g{Cz;DH7R$vYtD?8qT2_^|<8G{|0Hh@dSwfUraVS7Q zbqh%F1gN>$Cib-Df-O@4)>GX&hZBTsf|X3AV-6>#D6oDLncFec`qfMyH`LTgCV#^* zj2fPKl#)*YOe5rbohjV0X!sO6SEjr(?d=1 zeHoEv>AjA$g@Pv?Nd!c}*ml6fg>1{}u7aB`ei``>1rQuPlDY}+)kVW}#|S2DChC}2_yk13Ym#-m$m-L0*-w*9i=besV^ z0o9K{>GvI#%nsO%!m?YB%7CX}XiO-QXJT~YC)v}4*40=gPvK#M^^@mml6f#JOD1iK z9kdA~vm`rw$gD!rL$We^tb~okHtU({#k_%sN}CH)VI(LhE()h;k`@&kaR}CMz)f)p z_f&2Iu103Na>)KGaPsd6(gL&{3AffT9yb6;1Qe0jr2@{a3SQ2e;I2>qsni7pkLI`o}5VYMeuQzz2oEEcOG(^JvmRrC}! za0*D0IN2&`(s1EY*WJG4_avL^%=&DFBoV{|?Gs;3_V4~}v^orhB`ODjkPTKB;`!2_ zP1*OLQB?K9l4b!l|*dOKE9UyTVZ9 z0}0fyzu+zODtO={X^N9_R||nmENX1QBWX&f0)zZ28$l85qW$<_`d;cgdSAq|FRZaP zV9dDv1oUuFFjKPw!)79ap0;St>ZF#SG^-85JA3XVHn5(_SA_w)^#>hKfT+PCBLJO4 z1BNAgNK_I`niC^5de-fvDM^&B6s@3Z!U5SjV^X4IkUHv{@k`0re@?Q-S?PXSdWyUz zx^)O7pUtUawF7do7AY7fY9)X|J>J|2?;cv5mc_Q4amNdbB$pHvq0o^4czQ6YYklr} z%T$daI+g(m1Pla^IqBn8gXkNsIh!`s^?#??z9CnH(B&*M5rR5(^Na%v-57*}_UalP z+exdqtT zOQH37>mJ`7MK(K+Qp~8D#YWPtWd%He7fVw(Ku>!g9%PPM__?RzqlohnSOJ)V z!|F#tG1C%2p1d|z)Sid)LidQ8{UKICU(cru$?&}Y42wIA_< zKve$#oD9`FQ*M71eljQnAidCkS@d@7O>Rz92Tn$pTDEi<46&Y z-Htp4$lH$-8&3+K^9vN~E0V~-4ax$Mr?XIP=1Zt!=4)s%ACy^0$B8p z*J24bJ}!p;07nzS*mm=QrA1IRZ5<=y&d$29A4oZiBvbSQtRvK~%;UWiz-aJXQ!r(? zXx3_)n%eA2EFTZA!78MlCBm_4LphNul%F;wdU;}+7j@=W_Azgp-0uTTWRD@6g(YTO z)LL2_g{ikfK_n~qc%@KMM4IQP)Dg?mmbT^FT9#B&hY~_mi3H#_tpub9fE7RjpwH0Tzh za}J(K9Lm1M^X&V4Y@E&WrJy18kIORJ0uqMPJ~C8P;)>L8l}3<~04gA3HuG6nIbhFiRp(((b-or;uLa8QHr{f z4GvesFC4hVSs;Sy$w>u^RMf;Rb1u;PWXbzGNp0nauAu0)X-O`5s&H*14-)!(A!ox+ z?#Ae58|QJ{SfXR@TChR^{vvufhy03iSKw?*lnErI~K7TFMMA zYL%+QF*^Ap5KE6{8tBmlW+^m&;PTNa>0VPo6FL-^|OjJL7$sDojEfK!(~* z-3SL0uu9h}Ss3XMk=;JbyDzfr=G>Ol9Jq9T(bKen{3!zzq$r=_CQPWR5)xV@mtj!y z0(I=55Ck z>;~RH4^5QHfh3KQ)r9fex1e;Mh^^oM00&x}7PIi!>FVX}gUG4OQPl*tl}8eh0B!J3viTgn&W1?UmO6ETL2+kiTh-i=TbU^kUUb9p^_}}KP ztWx^z#Bf}H6Ra2=77Kz+m+1ve(Lo&~wCZMfV~v8AYPFYp{ib1JbQa8x$jd6oneK2p zmK-oX@S`(5QCUIRot3lMe|e!QUZra!VpJAHA0)(d2m*%>!ISX;>Y{bK3-pQBTxzQy z%XzR(Pk_ycO!L%Xn2MuG3^7znOrI-Pw8qgfDj#DYR^7Oxw9Uh3J+xKTxO@N0^^ww8f6ccd^W_{W*HfvvPbO{{REA zDJdK^MwNBJ+A1*IZ0T7|*kGU8JV?{fxHyaqYZ4ST6$G9pMgIW7@2-v3pFw#{R!)zK zGr7;s>#E)sEaJTL5A7=|YWyy|RoEP?{;UQr4r@}`(D2sfoKP8zuBL_fm zdiYoV^e4?!a=KUP^QD~&sm*o$GQ&z^gK@N6UU=WqMhx(PE-YB}O>Y$9U(KqeV~{nrQaLVE$ol zqINxDm)hkiRg%){iX~612wGNP_i7(-35ZBO6+t5dSy#Ar7S`-3^sOs-a27}K$NJa@ z6oi8ZVI-BokrY3QQ?#n)0c-oh*A@%d4-;eK_wzAYR-LpyzG$c&IB^^{d(JqS>Y6p! z9x5|7R-wkEH+G2y!V|UQB?_RW@ zCyXgLDskxsD#8B%3tq3s(N9}hZl4w178#nBd%eSfATo?;P_Xdq6taJ^C;*bp7IbN(!gb3M>Bri*KW9E|Plq z&KWxoq*`1rsPxrXmJ1R>Hl`su{K1cV5wLm4>Mi1Sg}J{c3k#*R;csf1P*IZ-+NawR zN2VsZi*II({{Sv&(~o-FmgMazxI`A!Kf)G(Bd%aoG-QlB6?|oIoKBUhD^O~~YMhXHVu`}XvE>oM{+PjTI=hein? zDCuRPL^NBUdzxoT36Y!$`~BaGEU33Y+AH{vf`Cs5;rpYutZ7nVE_v|NJysL0s^BL!w8P3 zq)%u7GS&^F)VQzWTDWTHPw=E+jKBk4@*>CzkB;Is@fr`x+%Z6tMVE^y3X$#Ov!mS} z@kxq`w_$QU8k1ifVZ|QB<%C9V-KQLlVIKkZ*24dE;q9{{Sm^g0wm`2Lwr#co3jZ z-VA9tCNU&Xvc=!b{{WTQt3um4)Y_&75T&L8Itax{f~nXIALwc8y)<JSp{UYmGsooq=6@rErpWmS)(IBcAi76-P~HJ+pbDbsY>{^k_Z^% z;8=i2Av4uO%lxgM1=~=UNFb&#S)6b`#5yBZow(B{O)`&9eLmoMgVdc)WR|x)R#ZbK z5+%Z06iRj>iHdc>MNdhIS1 z+}x5@um{^R1{zS2u&ZVswXyA2Q8Pwu$^A9!9(us4^4=+%X&{EH4y}a4Ej>zH$G##( zi&>3}8*a7F2s8Ie18*2J5=7}Rc8LJN+m70dt@6?}w4hTM!P)^E3`mj3u9sa=#VFy4 z@mQurfl;Lsmnj&s?(PehCPO$>BZUg+C{HqmOn~f(P)(Ne8?;RFX(W&ASWLm>WL}WKU0DRPY@2zTG+nT4%N0>rsv#<|=vLPoly|@G zwe-KU+sOgjQZWZ_KB9&xTy3RtR#R7~q!lM=0l!STUg3g=(1NXUgmxeit++;}iZRpd z_Dpm}(Zo`~uDaOE&=0Pxk?Ol3FQHFYwT&)4QjHD^kJZh*;!PMoEd@(V3X14Qx(T?b zjBR1Nyak=^nr+YKTJWJVq{bb}qA-v3qqqCtKt#i1eBO57<*spXVw1&D#D9J`jfx$0 zT3){W66XH^NF74{O^212D^-@37J#~>5zTcI(}y>bm^rgplL5 z_yZlOas-H1NdiIGxFli-sP^v3>ocXm1mYm@JV5H=I2~VCpB*`W98rd2)f8di zmX*UpHC!#^+7mM4*GrEIdWg$S14B<5!x&`IPL%Gar&t5mWrZ7i+?fo`s) zW{i|^V6kaUtc46@;CgxwU+<_pO51R@;D-`nNjpKGf!Yl^(&p^Dh}E}6vvwmD4hbKZ z78Qy~83PH$7BG_3$^j%%)=Bz0um_4xzVvKLY|Mb+0}z3vM;QHN&e~%21*P|`$te(0 zKaC@Y_{qee`KOIo7o#qf<{Ss3v*rBPO(hmRn)4E2wK2%-^QApFGRlRotW6AT%D@$q zaQ)T?nSt5bI|BGj)?U zeVY5=UIJmLJ>LIGyX;K_IR9YyEt_qV> z%0RA}J-5Y3@_u(K{ci=U#LPEgZ8XI%KWHDRIVEz;t+Uqstp(YnQgrz_>LN(X9M| zptsZZb;SJz_18CgbL#zdC1*-;ddV=#ktCa=q?wc@E-B?i#H4NtiIfsj;!SopFvlX! z06sL7rGIixIuD-CrF4$5NfOGkXB5#;Era1ufwmyW0Ih_2(2wg=(^Y?0C=C{00BLULIDzp8@t`Z#_6bMQ4^GtmKd7A2)kj5#V8R-OF|tYJqf{tf>9Kbf?_fyr z;Xd)$pgPh}2fZxM-* z23C@$Ptiv)J9H4DF*g8cH8&iNZ>&O*j?!j|a^h_5(3~X6_L&~&pn?fwr_T#7lsvHR z!6Zo9GVrMfewPYZUfs`d4fq+$kXdtXG*f!8voXivTXOyl`4*!K^nF#;Tw*c&)M z6UHWxfxW5eh@hk!fEQH}zTW^2oR->jx|uyE-Bw`ALb#lLr)Qu7twz3dpupu*p_J@X zsQ&<1-u<|!7^5hf1o0V`co}2&*~uHNuA@?ZkGqNxX`_V)m8Hn?;~V|!18)J`3x4Py zcN9%DcGEKXH1L^ku-x2OfGHo%Dt=QioHDjr zOF8jqW+bC5k8{&CdzS9VweUkTav0OjU|2)RaUfEwg;F|e9T4)IOn*V4UpNwNT4IP zmaHwRe7f@D#FX1R2WTljvsyS303a-EP}AaxIO0QX<}0&8R#3F3?NU^HZM(H#1GTgF zB=DUh3cP-f{xV*eI)yzJA1*BoH1({gwAh?)ht({EfYCd-YJ2wxK?-fI+uxF-d-CPD zBI&(R5~K|{9wsDu;noETn$8gE36Upf1MEC%-*DVt4aacmT+f0?l{6D5Z!sBM0=k&o zp=AyU?Q?$(IVOjZd!gotQcn?x+pxyNLL{gyGC0zrJWLh@9WAY|d!0?b9F!XrR-{)| zjz%{XY72bLJc%K>xhUb(kBy1p+bV+;kPITG)+nBqSR~aL8}|ec0e=gA&MtMZ`bt%> zh^CZ~p$3CYX9UW5-wv+m?^I!r8^d!B9a%?+(a9ae^b?JiV1IabRvnyNSdIg7`{8eN znK^R6GG1=wnJ=LLium1o~xy#Z=S?c;TnI&hN0je`$7?B?B zZV@OgMKyr;+h@5TI{Au6$AVqyx=q1v`biK@&7%&ieP|@c%}ej6t$R4wN-R;Z3?E8kJD2CP1|IRzA>$loB^i-mx$1(5fD+S#F+pV@YIkt zl?53{80jhiVLniIi61IwL|nazk^owG{nnzyVw8(V zCLdX{UDpR-aCAHgeyRgR9ONYj#j`PlyeGGsoCR6Y?t@6wWA+mx8%3?EK3 zLNdl5j%EDUQGn6XRLM<<#*)YK@XIPgQtBiTu|*&=DbvTdF&JgfS-e{*QIM5*K~!oI z1_NwSYb`k1v;as}I08T?7$gW3eZ4((i>!W@JwRkXQ5`qSn3VN2wGll<3Sm`W=}v7) zTS9FfiCav?b@zP0jMlb;78!oh7M7eK;H39!$E0lI!>%ZP&bCTa5~x-R03Ev{sziE< z-h(>jPKgZVgZjP3B7!Vir}#E2Ux(B@vAmE{R#Fd~hIkiomQ+AvP(9^h!8JTVb&x5W zpz&qEr1T)plZ-?}fici(PA)hbQzl|#q7PR@z@DBpQP|Jo3+WT6R9T-D!>aQh4=yn^ zp>vn<3aScU@3Zy~D#FCPDf&`eutAP{^{uKVP7ZAi{^t+1X>{5~HW~;=gE0%_)8c60Y z-!n+n6;Z_gTc}B54RUu76x{Ig&pbwOvR7=dvLxVA1~?@uP)Q_6!wx+Z0PbASbgZX9 zlOX9LW82599;!HgzVgm!!ZO|w>PI2e;uJZTCsfnQCmv%&wB>-3Mhm%DZ(__g>}CyM zc_QWPwDQAcE+IrKPNGN?_W_EAJAEjRzEVllP_(NBM^?!gc~wb%E#8`PUtFWf9=!S| z5L_2DVXsAx*Fj8oin6N}9F=6121HQw;ezT?=fjZRdzCFu1f=(lfP2IIaRW&p05qg* zF*xHih1(%=opGQfM2;Yw4kw1nt!}Gy8w$+*3dz_WE%OHp%GhQhKI(I@%~4R>;xYrK ziWcBn!uP(M$X)E+cQZ_zF0^f064Od?U;!mcfG|8xGET`fMQ3Kiz2crG5dcOL0<6!{ z)=tA}y3dsG>V~)Sl!M$!ScO`8BP4=k8a3D{0E4uRG$z>vp0);OX>N=I3~cB+0tdW} zwGLdWRy}?=Qs2}CJh_9cI24tzB~=0%=ctN6$YnJXB&_Lgv;wM)zRQqrrvf|P=xK=@ zOb)0&g#x#c)myfmB!dPB;AoKKE{9O{i`DGjo@2~#VAy?8j)CfCn1N3Y-#g1^btB7& zKD*t0fcG5Y{`w!x=1OZ)Q!7hhOZ!tJ&w(earm*|8P3Lzd%Z1=TTJ@j}P#XnACsL2_ zfN?4bPy$I9R>aNtZb+HetI%OxO58I30}d5V!x&iv)NKtiH9aMfeAxWBwy^g|Vxw@{ zw}o5Ww%hNL9Dv3G-C0KU~)BaF+ zl#q~^NX1HmLH_^}PfE|}$0&5_gD7W6vn>(J&_Pa4FeZ+U^2=8`M;ITac6V*j8w47y z%eMh}w(d8(_XzQad(@I)J4#G=Op&7;79x0#jIivlJ^c1=-Mi{x;;UxvHCrC|BfV0; zVB(Ax6xkjm0g9E3O;C0zN{fhm#FC+Q+|1$b8PuB-V}AGddyN4)-;Q^Xs_x!cxQ|Lx z;2DA(HB_Sj#VmKYzS7qOs0TxGK=p1O+*7~dJ zzGmsB8`50GnCh`C0}V!wmVve`A`pD&X_-+&N|8G;RFt~MbF?Vn4S8`+2mvvM1I39Y zM5}28nF4S!MkLm1Zl`D;%a*4CP^VlfTAd@shzWtg1b{UZfK&u1kSXt?Io6Xb^=B;S zOcJB{eO48UQM=BfUv`{MpD=EQ?1m;_+8=Q1-rNm7%9}|`n4p6_cyalTI|XIFQND=J zntH{=rA5}(l&2Ck6rDO|Wm=<3j?4+Ism^G`vX`lzjP)lt;x(AgSIHO_W3R2m-xQv{ znK67x>V+d3nu+5o^1@&)V3Fbrx7`Bgk-)OKwplHq&jMs=@60Jh)ddYsGL)#Ov{tKk zLNE@>m#qgH4YN1-9&2fCmfC*u;@P&_4I!1Ac0)zL5QHcYmG^-?;u7IAjKx+)E$SyA z^v|LhPo{Z~G)glTQOx+3ZQGOakDs1;%9|J#O3H};0GDBtQ@Hn~jjA2Df0Hav4ehdF zZkEf7C;&(Zal)yFl9CXWcSuqLSU7{M%5?%8MP)noM)x$jyk(TByPHO=;_;Bm651pv zge6_|!WJ+HP-!V3c%T787fbrP>G5#7Z(AK?$FPiFshEpZtqv7YS1gcafPBedsivid zIV&r%s4Iw`r_M!=b17i!eZbD;r9P0$XG3WUC{mV4f>KiHP+xkd!=Y=1wx(7fsHiBV z5w-Q6V(L|qSvKP~NC@woKu)`|G^K2J`ksxADB zE=lusal?qkQ;Xsh6!f1smGwfpv0nwFW~6j#kR*v}%|jvAW%b~0=HA}XYIOeHN>Y`n zXl)}>)~6ImLQ}3*qNs4K0uq#^2|`klMp3z$R`1G};l;HfggCc5vdewjXY(!q>Q)=@ zuec2BAH^6|SoI4yWBG?S8qCj#&4^-^W;I%xnGDac>$FI~7?A+5jX*%A!9d`JwJPa7 z;_(1tHbh_m8zZBlI;d%Vzs*=R`D;*?z&IrW6Nvl2$Dg@IRIVh{6w8>Me1@T6LkSlp z`O zgQL7)xKfoUhEVfsbx@xX2})#yf=C7hUCh{~U+K46EAiaNQ%w#DMbdb3ZW&QkUkx}I ztk`nXymQmnSNz31QOaFjM7&^&qL6RMz+|qL*Qo~(QVC9oS!pTML(hVkQD2F&P*gP` zklMSt4XCR%%MjCZ-zzsa&ZQ_S{{SaT#X(71O!sS2k`hvtLd?R9h@zdHI;)bf&rR8T zppA;qVz~YZfa2MH7_e+srxBwmjN&lXRM$^X(Z@|hQYbu_;iobgWNpq-LAbFl43(ug zrOJvFl%y$Z9yO^-B`PJh^rV18e|`&C)g+59))kuEW(f;zyNiY{3Y~2%IG@Y1w%chT zDpQW@QuP-d&=3=#Y9|Vq&Y4%v###v>LX_7#WF^B1K_(_3Xh*eff5I+!hcCMU0LjPG zXCL2(O+eZHavgC*9418VgFyBtkOPS+=_&ToygOb{2@K!@MxyDoAEfx$@Lbko7?a|h z2UpHx)5@V|??S7l$~Ed{00|ezUsKmioP$acpZWVfD0> z7=}5E=31w%nIx!|uD4`G6sCz!OHCM#Fj<+{yU0N*phVtamst$AB&lj!icut~Yf)C! z6)b>GDq4z^Nm0bWGu@{S=`h+HbqiBA&08nAl%XxON{KTCPB^kuq5wi*Av1|JsZ))$ zWlPG?INc)1o8vYhEzw9(r-88m4RkycqT4`;;RX**(~Sw2+G5l8sY4tjoJXe`Z=}X3 zrcLHB+v1RdjBGb*P=Blm?SA?WDOI|Gfzmj1aq{b;@!DFHB&hlm&K(rhUy0MJ%7GPz z$VGt`+6IioYCyg2J-XY9+hpPE$mhzQS7~a93O?U|>s?EYQ$aLt(+6WKySj_o-r$f6 zY8u+=ZhQweEy{#P008&Lrw)PBOb*dh58dYk`+a!S81dKyYYdJ6mNwhBR0Nx`APf7$ zuqM_Q@5Kh#%=8~#uVqm7kfF4kc0rNr&J^(+w3v+FD^PYUp-_e-0~lLw-bR~zG}l}4 z2}+w1IAiP49e(OHx9t%{VCp+Y+(dCa?W;5%xUyDb=w%;C^X62Q=l*Gj;+0jHWpp%> z)z#tDapBapFC?_nNldK*A(9yPDUp1|DY&l)?yOn7f4+4xbZIafl3;>6!h*1p4~aUo z6?lR{0)ZC2)t&G28*7jWZPpOm&8cCwopidfr4A)4I@GNTR45?mRKPTY&HlHs+T7EO zbq0qlP$pr=*T}@NENc_QajC0g0aenbIbI4jQi`7Iz{o%sQaErLwpx-yWx@$or&Oh@ zS;Q!kWont7Q#3}q_Okm{?G|26sp#wB@|~g&U{Q!?w{dcG3dZKb#P=W#co@4#btjLwPw7%-QM`+_bt*}S zJvhZ#zFPIm3?84O=zeL--_0=jV#8@F0^?HAM_mRMU9iudSgE9tO-3bTR)$!_k?iwS zvRs7jTTRN+rvmjPLbNIny*h#kK@dt3wS#s$?Us3U|o#K4+h-|bxoDD9a}~4 zp8o(zD@q7?Nea@mD@2_N0Fh1k+t-&=a~3aIn(%W=g5ph06#>PPYKq)tX(CT1I&{Qq zq;iq0V%Cl{A$13Jj|#=3LIN9;Awf$jaDtSCrV5I*=|~AlOlb)T5Rf3{oaZXBXSz`? zww0Cl8e3_O@k-RE3oU>aqO4A(k<>;NU(JukD%z$vRX3>?xh%yl;3zgL;!XU1o(MlI zNP4>F z;)L0x4yhvzxbug$fX;8r?i>_m2GfQgKAbwMgJQMPn4v{1#>5av9~%-bFMUs9H1ExZ z5+w7_yc}xC-%Emi?|#oNiS|Ymwae9M6o$T{LlK0=t14I&U~Y{VBkit*bUm(b!Z*@K z+qZ0dXRD^Ayn}!L04VIKSQrYzK^+m&MibGETZjBPK54}8Y%)5mKBAVd0>W`T9TN@2 zp`@pp3}L+NN;g)anxREYjqhn#$8+T}Er1F+Xv>N!Uwh*!B`H`+VN>1#2-T&+rD{r) zLbVj&m`L!-GM0;~ONdZ))?Pj86ynn314|G?$U?iM;0}ST09KV8NpjB~v%0B?Wn3qw znO?Fit$<(@6%_bQJr?Guq^GE3EmbTyomZJxwnz7yYsN{i1PcxsTT4W(phT#QN|mNg zsYoP*YEddyhy;>IGH6uo?on*>w=NF);qsSVabzV9xP-zKSVS~R6MzZ|pFC)WW_)?- zX`>Yzwv|~1!FDJc?K2zfwzs+OuZcVo+S-(;pKSD>k0PMm;@|U`9~#LR5z-@Xkm{sG zU2Y>3vriHmE0Arr_Xq3&;tKe8`nBQe8A^Z$=k4>TY2D{mtwBadSmp@AnG-bC8L66# zvlbF=j^u*M;f25A0DEo20c4Xpy0PkypOqmy*s&0!#z8nv(dsx-KDwpnX`zwtA!Q}K zipSsBHL%yWdv>_t^KFE|8zc8m<3MYi_q?4%$;Zle$5&NAsD#f-fX1xxF_p>tDgoPI zx7+~&*Vn-I;=rgUqh$scnuT%erzWI-l6p9m0;#YoaIL(ZEIa!Rz2T|t&4o{k_w(+p zr!)}&^Utk2;1Se8EjlB!ENYAcp#gRh0AuYIvkwgowc$O|LV@d^Jv_+vQ1dO#gE~y~ zb!^%C`)F;!Gp%aI@k-KC{KGX_Uq-{*?CuxjLIi_r-ndF6@LS$(PxC9H3p5*t00a#vIK? zna^mi=D>$mR1EZa>GB*njgv@u8nT|6I+qN)Y^7KdF4qfY?#p`ud)WAJL!c5zzn^Su zsA+lrpAbCr#-`=@@u=yRSxZ77k9PD;SR2P;KX?{41H(@n@jb(6Q7|S>!gg`=z)d-A zyw0@}vLlH0deglne5C~>3>GHZF2=wWxHq^A8BKw|vrF*`*%K#kgd z6ViG~u#)o{M>>wy7euxx7+#XO>0v{QHX=*%Db+{ z`nHM}O9E|T-UHeN_#_JnFrA$99B2}A(5y+v&!25LQ{gzKA4qCqe=~52i#WRlZtQLL z$RoF6J6m2QQ;2ZE!*7-xI)^5fv7h%?>cwS6W27H;Jv8T2iQ;vxMKOunaf(1g0F3r1 z4b9cB_OIW+jkuW>$wt}f9dWnJbaZ-A(zpHR1QqST;$v)x^5fI%St_3vhM8cP6E@(( zQdaJ_3i|38cD9!AzMPJw5G30UCP);RYC?u98b9m!#b+i^Y zX#uvRZSCA^p|>3FQ>aXBKfB+yixh2DU*n&HYdrt%<&=bR?M^_L!dTI^0&o!9`r*ED()YYWKXrre}A-Fj#tg62AHT}jG z`yo6Az98{AT3jbr4?Tm3>zWT715HVpBr5~#LFyjuEm39m9c%!v*#!cyZ4UbVJC06C#e2b)?- zR+k%XYYlgbTSaTurdJdyzsl`1r-lAn@8#}#MhRCEl@1bPSra=A7(4@}9)Pn)Q82!} z^ou&aQ^s(rs(eb8DyR}@yw<4P1c8c~WAc>lEaP#|HMHRZ^N+~3q?EjXk_ctSlW+cUhj?cBf-eL*}BF8R#m zT7yo!O0@>uLT&BmzjIn%Lu)HgTRIe!u%=Sl)LNAxG+lj~XW6B*c0e~_Y|BBdMb7o@ z0U$_G@fCf-U`XhSqn}^@0EsSa^)HXrt}7$097?`LBqR!WB4MILR0}Z-4ez#1RDee^ zD|a_h^|~(Z))wi)bc7`!69{djfQH*im_ibr2gD?jOgDX<*lw+{v$7imt!4_GF^Y<~ z{{VV15hHFjMEKopMm>zpiq$Lk+{v|oMT{RX7VUqdTZ?w)X0X_|Y#>LUNjo{&6@|I( za&HN8cI@;0YF19dXy(T$K6PqlhDlcO#v=0+u`0})m@5r!f3h{byA=;CkpevN#C(s& zu*-fk1tP`mB_Tm32_`miB1q~36NFaV-7m?XhV>syI!TP;j3&e>v6D}UveVI&d59N= z6z@GsuF$T*k#0iRZ5+sJJ8YpA%_&OOr4SdXOOpV|DHuRHQj(3MQJFQtAI&Mw^nrcb?fao z;_TIa7Kg%ZP~dC3O_3liPpu%H_es(NQv^?oQBqFF;px@P)z;rc-9E->YEul43&Ul@ zF+6(`5Vw{5z1D#mG z)Zb+cDOi*O+zG^>z{hMvNAVssqL%~1F$_l;>uxPZ=(lQoyA52XTB)OS@)s1Zk&nGu zh^ZzRKvbruU=da1as+m#yhw22BMz86Pgxr}2MlW>+F2S=K5>8?V08|iq|uzncoiO2 zp^lC?dnhb?bti+?lvX6;G#j{Zty;M4_1iV8U*ds-f1CVL z8cfw#DypK!WU0gA5-U!L7^HWB{&2kDWmW?+_yKgV|f&T!{yhDjrg{ZU%Nz*67ao}+(Q8)laM!8~DY;`23 zSQ>!Uj-lcQuM~h144t?Nr+-3uUp@2>)UT)xfYwk-GR^~uNR>4rLV_GhI>}aw2=`b# zl@w&NDf&}QQwvh#V6Y`m>qINO;dm48ea84HAy{;z#CtZMg=KE{G*rt^ z4XIHF9e|F3iHMvwbWu^Jc180ca?Dvl3w^~#po{n1e=g&b3WVT)N&PA|w{Vdl%*M%> z{ZFiIr+0WzNj9K>NZsJX{Ckiz;vflu%u)WJl254f**x&BNgGI_Cm_a!ZiDQfhME99 zw$}X7F^?XeKdn6_U?+!0(0!XDu4kr%ei+nVA!>D;ne1Orb-I9 z>Xj*=S3>ehA}W9#O^LA_>mK!6J%5$mTU%-G9c9MTsOe6nB&10Iz>_i2JS(3m)2TZ4 zYLn7qq9+-n(bd0RxhJIkRg%A;9U`HJ6k5q~d2#NcVUks1l{J%8HBwa4;L9|4W*bQq zjrtf0RFV`KW|I3CntO}%uanx_rCG!3yLbQ!T3Km?fdfvEb*^LXTJe(zNW!w~c)M-R zvvOLsSLNA_Av!@>OhlEaOrDhKju3GrtI_UT$30|zAbC2EtdtF&TRdi##Pe#_Rmn^9 zRFX?2em`ARS4>gq)(TNQOp+zG1kiRI&yDE6V{#11lBBDHmiqFgr{1ZSQ>b!s|dqpBy8D$!jBKA%+;QKE_4?r`iS&*){Ogu_6lOHQ$L%SS4ip0P z2iDK6A5nd6%N-W3!}70E@qFWoQejkd*`Fz4QiqzZRfBw$^i=fq&_cDcUaY47aihR6q_pE?vc1cMQ`58ifco;?+HKZHl(DVBXCW_(Yg z{c)Y4>Hco0r>k1{P|7e|O%uslw~ZHb($5u=peQV%Qa}#U4mI|bxkr2L0b&E}lB7t2 zu^6Iy_)Zg8(b^8^xt)aG+5lc{I#h{(w)W|rfk5JddPq?LQZKXD{{Z3bkv|b0nP3^y zC1doI82%3v{{SP*ke{5xYiOrFYtdB8Oj~>=Ptrpo-J@c_p$tI54aeVS`#pVj_l>W) zTEA$5A!t~`S~Wm8V5EcMz{n!8e|5L5-P5>GDI_cVqesHDs9~rjQH)@qa4-lsV^*G# zKLl@4og?)(l{&lDe9@PwFdU_eQey>hdisjG+Q+4lXO5N_+MYFuWpTCMR$Z%mD`+{F zImc}I8MRtjE;zL$q$5E_Bymx|b&)kM?;mK)=Jt-;TQugU0+TKP5|E%lB*`WwKoh`W zwyqoTEbD$q=traM{fl)Pcxh|%W)XRl`VI;r< zZY5g*HALU=pKi57mO9&%SStiF-* z4p{Y7(%91&!*C2uFuc*1>e-f#y9~sK=w`Zt@KsaP#spOeK|>{+I-REpyEn=#cd_TP zyQ2zmt!%m=skNZ^w1QxTB*`3f;6cWq9EUANaN@00bg4s976*tFm{(B*5K2gb0ok-E z@=kp8clfM&ZK{Q6l{k(KTeduB0jzLB%(5rH1K$2!R6nAW0*(8~3UgeeI_#?V z^C(e32TEQ~_a_0wAzv1bM1b^D7-?Xv zz^dc(8lC=X1{b&l1%0Y5eWu3!!9BS>=gdJ%i7_KezFyJ8XI*7h;$Ib|%T@mX0=vW> zrC^{sVB_-a}GS>NSprak8 zMREqM9ehPdHn4I$MXiTj_H44*Z=-RI@~jK@W5-E7>HGbgkqw1J9~ zsU&PW40K{TX)_skM|$-5RJ|%m7^i5EMmuqV(MP+}MFizX2U0WJgHeV z43k8W4bdsGw!Y9>E96IrCP&kk_bWuiwJ}w(Nzh1v& zRWW+M>!vf*Ov;{~`dZCXzN#urSLB<{HPvOdMTEf7-KSXJ{JR5YVX%9uPd3f4WcP>e zBLTBW{*mkckGG<+&wDe~-YfZap^-XWBOPahDd_`ignx^$8Yx{@>IN6l%m%xmJuJio z_^o(V&G?*K8aX6G?%oW}|n^EpYw-sC1OgO2Cz--23sPym>dOc_bad3>k zRjUdGLOa!nAfNc!XALRi8&1uUMH(3y6?XR*>~$mBK8^`SG=U2#0yuj}>E~@ksi}9m zF(Hk>?0huS+CKgnHjHM8?rsXOGdT76VbV7Aj*1hy1JEw4`kU(34bbk1;gaKdmmio# zPXdca8jWSCsgl-;o+P_Fod5@qIIw{+Jws{o=Vsaqw!+^!Qe>P={iy?Llz0fjHkEir zCaycxAEK^}dS{y>`a<;64l9`bL(sKrX4ck?u1A;m2H<;5x%PfowZbGrK1Rg+nn0cGT zsc6B}cVHL*rLzffQ2=SxfDkyE9NM*RZI;V!1u2(1#gVE~?W-$aPOFSC zdO(j8ZIC4cg4TbecA-DR#~dpecdIaE*OZG%QP{QgorNgs8x*cP1{l?BVLc*x2NHEY zidf{Re<~PiV3G)oDp4E>Obyd(q4WY~zcHeSN?6u_tvdi-B&kY1B`sS7C9xDXxLYl^-L#(ZL_t{w0pq7; z1A<4IsIFnXE9%u%LyR*o;u5J{?`m_kcK3N0t<+dt+rNHGj^_4A9yd@p4;ChP0XY1q zDwdZx1J6%5(>^tjI5h&*`VPm6I{o$k z)ztT{zMU#Er7cc7g-9_h3l*rHsVY#N&`hO|%T(NG#@9jxwrSq>h%EC^mjYFR7#@N; zN6)T~^Ng`ps}85^JbF5h$kAcw-&XN{jOIft@0y0vqs9O&7W=EbO8)Di?IeF?#lhEJ z3-f%bywwwcRt9=w5D&=h6i9`X;Y&>S(@YmPW$M1Fbc#VGH4~rabP$3~IvbU$fDK-Z z_8@@Joek2&6x(JWlW`W;SSiWw)OIM1s3(H>jtb$96d1Y9+O@ewv%Vhie$7PqRH3yK z!CX>5i(tlp%r3VWBqcP0W>P_qdX@x^1TzwC>Df^I~vI#}tCVqZ6^gjP4d?7_TAqGW7_twA5ohUnYh&(@}IKk-Qvt>Z&?^tl$$y-U4vz=lJ)tn@ARqB;=?7Lw* zud{msY;G=Y4ZHGHZ5nap9wX9@?C%4f6`Xia5yRGo6zR%ibr^OTLr?yU^{zy7Qarv~ zZ6?&X9{VZ)LaDuhJ;lclLL!ZOsUT6bsl(qPL@+F+POwKp3}zjK#ImsW86UbdmpfH- z2eGyGvgQJo{hKLEl_G}*ta{oj(^59V;%LAIL48RFcxc?6vRn{Fh_Mz7zNw{Y!k2j6 zPCZMPaXNW6Nr+lHYIxO1lA>8H`Y;dM3_bF63)@@hjgtgZ(Ku0iqRaS?QfdDHuhdKB zQQ?K?XkvwoXpqL_R7(Q7`Le|G?_<4=(S2=h3!8ATg4q5nPfwK~e%xHR9{!FA17}=u z#PrkcCNY`%dyZ1(+886PsAZaps}8Im=(x26%o=(LlSO)YR^I)~#_EzO41&dOAUGpu zSlSOr=c=~z9qM4t+z8qa0y*k9P*K;OhEY#Vfb}n>n4TwwVKLOm`C}BF!qj0E(FLif z!Lcx^3r`G%8DzDjkIR`0D@dVA99v*aP6rN{$8w^ihUv(9UiD06f}2d9kI`{{V}}tb5}g6LXBTEkOYE;R==4f z)X5q0Pxu?lz4r5?_Kl342}59%ASE%;0wjNoe(s5y&O4TokTyyW?9c!*e%&J#4y72? z(YCdL&A6PHu4rty z@+6wWLg{tFPw^eT^XO>AbkC{zi!5PyUTn*lT0IV6hG^x(<=Z2!91zmQ6bwMx+liE) zceRe1@&(T_)LygPtdXf&fg5EzC*M-W@8@phuO{K71xiXvPxJ_k4+A*Qry2+|O$INY zdX+j{{UPgEwt{^U>HCHXbIvy0j!75kV?|aSeXC~f(9PWGgSkf6u;G-rs zbe=sMY9`E7lqJweQADJWWh8;X@#sBtV0|Texy^k;>38{#&w{11R!Ip}m2v0`O7TTX z!NoOu=*%fe+YF3-=$OKO${tJkDvivw{RHX;HVFbezF2fp-Pg>Vyg|2Il^{x0w*kQU zZ0i_psQ&fGtsGOW2c&}mX=@}ZO@oj%)R?C1l%46^G7@9 zFv0{;-gfVLrdk7R7~2|*bJa)3)NU()MqtVKJsgy@*kwI60v16Uw2(v=5F<@5Wc{pf zZWP@n1W=agz!Ri!fLg)bb(9xGo<+>$`FDmLSz7n0GBZIX>PClY&4!1KY>n zLL|ozEIP0r*rmRAf;Xq9q>k%w&f55%*BW>Z{{UAWNt#p@6bRzcMFfU5`z@}TeLp}v zRGMs=q!jwphq+}Wo#bt?BG$KV!uRpwux7PS`5!Jxnlq&q4++Jh-hR5#o0n z0Dd;&gr`{puA5PTLRYFBKQv|>I*%n}n$*Lw3gJ{Bt7w*AmKOIWSVrdsSgR>vJ?9f)Dm zk}2zd{JySjQ?d@;th3=Pq+i(h{`oO3~q5b?`iJG`*tDzy*~l3Oi7*8V8Zu zJt{XxeMox9^mmDj!PES67Q*R-Z~AN^qxqE-%E!yyH5A*EZ*43XX=@%eZdui;(ZbV{ zFi&=U-W7U+DAkv)EEA~7PfC11`fU||9)^D%%yX>WOv}9n>rPt3FuGHAbtmjg^o9#ET`xO5GmLpn0610Go0n?;-R0h+EO$su+@i~ja z-B1*%gE&lmuyK>HZL4YY(fEq`QT3A~)ZG-v<&Q96vQ)KpUd5mk*rHQH;tHyTfHS19 zMpzQ@vDHFkBoT-pgBXJbCkfbk zX!xu<+2Y-6jVy29OYnY^H1yI_AH%aB@@hO+DYS87l0xFJaO%e0TSYAUe5Y!5Q6ygQvxXPcjtVoSTjpp=T3GKBv=b1VHEj_*Mm##`w))M> z!~`G-7=oi1PCn6y>#Ei0uS2~|boVxYUPeI0q{EcO9c3}4fIzg(s#YY^IwW#jBd)e@ zcwdr^TXw~Zf#9hIH6#gyjihz#G3P;nYjogJG!ZfZk@)QCsa~==AJu-Z;MEwt4^Aoa z?lmn;CWtL|9Sa&L5j@$R)lTx(OD5}iX>F_*wfG>5U zoH)>VJHL9Bg%ct%m5seZb^)`ESN2=<`PAH>(+MiGjvqk;HMR3Vl=V1;G&LK6FCmhQ zIhaJsLY82l5wEk6woPQ~Y!IL^QQAN~IE}c{B(Oj!F~sz7JjFTnTRC+fIArW59A1;> zf2%aq_(m&=)6SAc(9BF&b5<+uys<`}NGJ#(DP!8>_nlf0gdP$UK?Fj$nc@dV7}28C zw?HvEU?}w*1pFxJ`ZnpGUGg79XuAIZ(f5lp(_@tf5yf(~LZoc;(aQ1C%SAH_wMUSk zlq6_vsMCU6jl1l%zs;~itvM@GKtkZ33XrZOAbpXEh^YeBZJ7Wo`=Bb)aN1yLGl7nr z4IS>F`ku%+lhQtT>Yhr*=cb^xGfS@A`*7tjC6F5)~Npg@VTSTT|)I=mm1-*|ooa#*HbF6p zh@O!|89Ll}m8nXEB%D-CsKP+R^^+VTw)n|aiyj{mS4i=!gCxsZ@M3mIEa(^nX zj4`;~N6ZnlLamYud$)YByD(bOx&DBUz6)RnO=2fJn*j8dmqbi;>G zf)fCcCk!^}KM-P=b3=&%NE0zQfOSy7@)!crU8^MIHU4T_W z{zULp0JFxaBa$Pi1IwSw*ya}>#0&X%(c#~U1=!73@)fQ92((Js4(yt71%!IW(vf(?%c zciYC!X_;Ht+OJlw;T{kmCP7v>&H&GyN9O$7l`x<}q?|`i!}w6I=^myQ%~`iRjjJ9R zhvE_;Q=<8iC);`j3O)_?~aU zaKv;B0#G{D?14l_&=;oq ze_4LB>abMI6qqucz}50R)e5_zf~iDlF7z)iu|ly75Byff!12p9vR?AuIM5+F%G64+ z!cW=+5=amLjAIy+T>R}1Ja;WNwv7Y@T&Oaa9#Czj)T!~Q!W94sk)V=b2__BT!}xG# z+()L_t2bi3Mle1#n&QH-Dual{9imApKS|}N2^=Nl1jwaE(8M7I>JMvjoGD9*bR{5` z_<#njI+RWVPB2cW>ms@8=3wKNX8bc|8)oe`p(=S8IFBvvQl zfzX`O(tf{VSrZA&iJ53t3UeDiCXz33B*hK#Rznw^SS*Le~p+bfl)%18+#2Bz;Du94@ZfhAAYT13@EX&@*Tks(A z1I94v{4qY`Qw^5)D$I=r4#@`+IPBnf^-!II<24wKQc+Fi&rDHcrdPFsfHwsMY>YTk zJ)N(>gZ6>GkU=E#wC${mwe4E);jDoGNI1X|?1326dc1z7N|s#}Q_I+_No8g?u{vx7 ze(}EU!unaX+NLCNot)x&xK`KNGwc5VTs>IH9WZ!#)M=}+Xh@}qhFPP!l0dm6weB@i zMx{=s!-_?+PCUoVQ9`%z;57G#+tPj1tI9aFW)+UnW7wpQi5!azj8ky3sIn*k7cQiK zt>90O39gw!l3NgX`%d1d^c@sX=K85>m8_l#H({YB_Zz%Dw%~Ts@eNC0;C5`0JV)t4>&@WryhCizm4dBwcvN(fs_yc`i4rDR z3w@tCOXzli{{RKtTHFh~>UGHJ=@I3JPrI&Zr01PtXbj91HS^|{pju>_IOTZF*3rm7 z1(lORLAK&fgTQh^v`Pa(M8S#c9=_qml(D_t%79M;K4fh7)Ak=c)(hF)Buou_u5-fNO{es#-L6W_KcEQB-aF1}|KwJIza_GTar0pN4 zSI2D$xCTtevt3+tvd2^^)JGZ>BXbge%5PzN?Ee5J#CxQW4`INC&S2f3Boyhy{*mYR z0CC$C0e?J0zr+t*%{kHZdov-#k}ozvx_4dd6fg`!Srju`+gW!HXgBaiyzQlECOAxE z<&FY&g9d@_=Ix1`m_fZ-+9dX$wZ zClrLl0w-?4<+hk>I%!|T2;f1Ge5p%|^mi7*a^#hD@R-%wLS#@SRxc-(M0Nwqkz+vH z+TfGmHQ`fP%3N?qP{$2|asH4bk)%O^LJNHD1j1A#V-t^@P;ZCy!#4nLK#;#+_@rU! z%Pm0PbVUrYqZeT-sX9mYhML=yb*Fx0qxi~3!j1D;S z`>7M^gCJs9WOVsM2ZFI`BEyzioxm$X2oBOY0_H2~ro&5)+VEAn*TG6Iy8vr|F~^_) zc*fr_XgPbnp};?Bwn9iyj5uxE(?usA=>~Gba4}U;hfa??=?pKjMDyGtu~_bPBe*1w zWv$84jM~}L0YJc$)#uM$2bI1lf(wa|B;q6v1min@3gef0FP#jN)YReZQj$3*ASL#c z+U`LE-+0OQ)Qg`1;l;x;WpN7vV{Q|}&>jY;H^Gni;&CtpiIcO=Xga0o#%jfO!G_YB zvobuf#~dtVkvHvf!M@JzEHoil8(PPPip&{k;y{B0&J)5qe;g}EdmBhPmIQ5*2fv?f zLeE(XGUW_*dJIaRB6=zKHb?HP^?5;gnL(P-XI?iB{lBOGwVM&20Lc#lOhYi2sE zE*RWH1xrKaf$uc&KbL!GWQ@1Fy=A4r4Ouo2L4BuLvqXS+zYDArs~ zf{?i?!U&lra50XPj7}AYK6D>E;15Ylic(8XY9aZwmBJ)x1d=pS`GuE8uscIq`sgiw z2pYaEstRC`2nJ;Jj;R>=RD6!pa_qz?+uR||D$;b2d_YbeA~=a2wGF*5XUOuz`KBy7 zrg~6eNW@XOki7CT#)1*AyR@^gCi*NL}m6XdQt@3W>k~I`)p7dMPhY&-j^ z0J@YQpE_kam0_ZrXtp*0gTzX^F)=+S;1W1>iW@iDUSDp}xbKo08(f)0jiXk=N8$z| zlzHdV{{T_41e7u62onvCIG}Gmiz<1NN2NF}3M{2aE?D+AZKB*pi@2Feq>})M!>1TA z&?xIA?PD(9M*HgvguIb6r9i+E3ZhONCu!kJ97ocRRWPiFQ<>{9z+#?MSkS3Jk*ayE zR9K4yO*bY zF@Wkg$-`}LKkd6G-Et9_Tp_0xQk0=e0c5CvB6f^qnZN_lSn}7VZ0VYFjQLfdM8v7p zq-;O;;$WWoIw=kA`=;XNGqq$}oADEQseFVql1ZF>e75ZncH&0JtLELYGghgie_NsMSk#yu8w zBLT=?)`=liq-g% z(0eHQkKO#<@m4nX0ZyU>10_o)0u$1B$ig;}SbAmYD?arH4x2OOM>FBHkx5bJIfK1j4{H6TgCMWlkS_Sx4*bc zZn&TlfQV7Isr3X`e zE#jF2Jg!pBGsRCYWyXCvlXm6~PR@elu2+;uT=~M|)c7e8)eOmM>o;p#}%3SN256V$g7nY`3 ztqQ;ZNFwqt{#IxAfJ6jXT$=*i6Wm$fSRpRlGNdJ9P*jovg!G=A2;;`0UDo=O$+yz< z*w~eopYDDILxfJH1F$rh#d94r3gq8L{Y2_kNW`=5M5RisD-VXGdFf?QC}cn-b72_< z?BTQ`Yo8Vu0FXxBf@b!Ms+?^bc^ORq+LjaFWVl*Q-2UOw+~Zw(u33l zl4qa^B=rDlV9a;c(oQ03kR8rO!xP70CyAQ(Ejh!AK4d)h^db|1{ybG=}t zNMl8PG8^>en@^CvDuaV;XMm1_mu z&!j;K-1o3A<`%iGP*S_bi($dwn28vWt}_Nt5rtz`=zT=l?|sUxt=f49L3IUfsVGwk z`>qOz1G%3FSiq|Z#+x!9;q%nY{{YjBOR1Pv80$kp6A&b)k|^S73ZQ9ZZLXlHEO#xQ z#@m5W#_cUH@7P_-O_j9S@wtQzIH+QH112X(#)etP)J9voIf%Z4GP1FtDKl0SbwNBna9G18qk8uk{sezAAM#?7q-xw7yjPYH1&qaOp$kN`axp z%3C62<3mOr_+NDi`dNr)>8WIi=4wi4q?U$g;DTvfOFTw75oT7B$`TTuX66b3(48}p zW_K1xGD?47lfgq#0F=p2*hz%Q7^s0!72nkd<#S_}IbnDL9~R1UL4$CxJElR6A;rjm zr3nQp7#a-yKmHs!`>mOb<=nr5Vsw$gQBoBu@aaLTG^`f1LSJeV3$30q+v0O#4Z#}7 z>~D9C;?1s=D@iI*ASD1s(nuP-Kt$srr497$&E3rIn{v|P;roK>T4{h3O4v-Wuo7{vOmta(Y7g4VAWtUr` z;u*VBdYnmEDKa4@7Lgo5z@9Kjpg!ex>h|{+(Q|0+nyu2)j(3G52H#ejasVWiI|gIz zj6gIe)BX~DQ~v-n^}R-(jI&qfG8jaH!h%CiC2+d zn*o{-g34x6RSP3fNLHP&6@VQW#7zb+KB6ue&Hn(EBE{7tT?-QSw!?p$Pzp<0wMW`@ z75$(7q5}8cKr-dC!MGm0S{X`uTGeSpfj68zF8GthkOnk8dYb$%^N&KaT4jtfhCEJs5r$LZ3-k1l(?>0R){c7fBQz0Nmq=cDuMl|_jMsB^6nBaq4| zRC(&)%jPooARDOT*L#%v88S0&_ryX}S|G?uj-9ilsz5O~Bw>yfj&_~DZ#~9f(Q%t( zT0404i)$~ZPkP#x3#&Mi+CyszP*fZN15hL%^o#gr*LCj;lQve-(9$j)M_pSLBI1xu z6me3>V0JGIjVxqJ0|k@@Br_`%Iu!1f?Obn?-3+`NN&qEF23ECBl)wfC21x@An9$#Q zdveb*=TmQ#p{s-WcW#_hjwPao7;quNq!3|bm~0#rld3=yKo(K-3r&i3sk&qZDq)RB zLs%;%#b`ciSnFmGLuzE0xB>L?wVE(PIVuW*s~cx;u3NMO>r`HNht-A>m0(`2O zw{Lg0*$Q)(OD-*Kvgl|lz>xaF5ZPIe@_vALFw~1!Gq!Tm_V8e zyeA2$`P^cb3Rs?`UKt}-B3Wi0^UF5XNC6iNPJ+Gb$kn>f20OywQgvzxJa`#01{mQH z7~@{t{@HU}-s0}dH~hO#+AX9l3_0E@YIte|H~<-GG2barq>}_~p^HC$7(GA0Iun6s z3^yIY=f&}<>Rn){#%ZY|Nok{XGS$~QY=($!cMKQwmrw%k;@s1A6_sTzW@XtfY1EAd zQkCop#FdoCied>6Y8>5vs66L4&Fz@Ee#I8|k37N>9hVqO3sOt2h`>9iOKK#}q~Rn| zKhg)``_nF~bdMD3mTAox1vN!J8&O+M^wsH8xFM1lsf0|bVygvNyn}w|+6Lphues-X z*nQPLwnI2UKsuD9m16jH8;pl3=w0?JxVSj)>WMOD6>5<0qW3| zdTZ<#QZF0jnQPh2+APqeAxl=3EP(?^GEyc?9}Ec9wBig)o7dZ&&QFrFm{~h+r>+gE zLYz@exLwHsNebGZ%S^mZ8bN|hJ$kqFOVi$ybvl~{%el8IVbrtZ6!=7yHMqOQOp%y3 zdGMrhmK0;`$xsPoklSjfyj5p;EBOuDtqO~PL?{p9AQP%)0yYtjGBGhp`!emp{p)G= zvkR+rzijboO0_CmYHTM_x(hIp$UX>9i%>g8G%j^p@a5>%QuO_SXB;Op;G(w@TI$I@ zcNKVHp%l@VNh|7MiJNPc{Q%g7+C|-EByeMy?t8gqi&=_aQ-#3=u!O=v60IjunEOnC zWTXw1kNdCnHGP}rtXp4QS*G6P+$1HfOMQUC)RcG0{smn?Ed#I+VB%>X=A5E4r}S2?1v8Zi=^&hu&Mol(Y7? zq$sPxPPIt{CxDGcN?Op%PxgL}JZe$Oao^3L(Fv1RnNGbt1k>V=A$w|O{z`+sFN!hP#OWqq-(|LE_ zIc)lx?-^-*-*S|ao1#=kt!faKMj<{aDDe^FufB!-J9O*Qu3qX^8Jegm8oGkAs;%0Z zs;ZufbV6yNo8^;ylg!{GV#8xT`9lCMyE)wFGOWJaFlFNMosRGVkOrU$30@%~1cWIn z0Yu;;3`V`4_WggE=GN?H7ie+2w7#z4hE%7mmf0beR;kjZK0He!7L$x$&82U~0 z@zlP9W0}&kH=Iiyr@>*Vf;cdmxatjChLUPPvMU8zcCx)nsE$T$#csFZF757fd)D3C zmkU#CU=q_Ukg{NX>HtcTqooN*of1h@2%(Q@A5b^jv6(HrviU6wYj)o5m29`aF#3v% zmf^&hLrkOvE!99OP}q=YDD>acUY7L-)ZR1Ge8Zor&Id_Xheoo;fLB2ZQ_CLOsTM|e z*lFhd9BOxphC7o>+APTTaT&$kt)0jX2NqJbg{4YS5_BiSf|nXXieUteK;b!uzu!@J z88$+T+`i@3OX{`>xOIgux@FuSxmyXD4ddLPNLq?#2^AC8w?R5v((h2%cTXV4G2AZ> zuf>fOLcy17DynCuSa;G_NgUF~7D*+%Yf1!RP#F*tehW8;b==)M+ly9$TtX5Q%AHt2 z0bg}@@nvUHE*?0kq7o7a zAP=^c-mpCvbR#Kxa?3qO>FrK7C~L5qwyMOba2YBPVwNtLeH?PKG>Gz@lE|V)i2-E- zwa= zz5TsjV(_%MyGdn+-D$gY2N*5`7jC*nr6Gn9u|_;f3Oh8C!|4A2)9l9jkY8YEz)Y$w8PW7XF}y%}`R0i)^e z4TfU)USyvz$0d4V7)(ht6iUzXalFjGqmkfi`Dnn&p+wxP%#_Y@+^a87cLfd-43J6D zjDVxyDJKK~N|lV`SbcWuxpEfWk-qQJx6>ZnR0rHs22NE>z7YI$JhMc)MlB`t*Q z9pE~FA8e*|0k(WP&e#M|!CkNB*4?w&m*vH{Q)IT$aohc=N`V?u!9FQeY$-~BAw<6Z z6uGM)=U$U_51#)v6%&48$vc(s*bBz%c?O3f*B(RYZ7IYg_GS~rzCfN?G9Nb zF2n^XCx}$Sfbs)xN$RhlpQoI{<@~8_-eB-8xUgiYDq106$Ph}AI0zGkA1=D}Vw(Yg z;!hu+78$m3y@Ztx3c!K80suEY7aSeAm<2|WAY+dc!_vAC$diQ)9TVy%7u7D5;hEtobx{-pgy z=YGB99K9w#fMkm3sj!-wI)CT%$5Kw;!B#-N$XM zLxWpo1MW`3Rw4!}DiWwrh^f;p?{3%&4VMM52>?LBUvVVB@SI7KK-emusCvPi@Sdn) zy+_2WXs8Agj$zo0RJ8RDq95h;2{@#H1LdG3cNV$qNah#shV!dGTdg6GfrvsHZ39ZPzTVOd`1M1CAZOD;>Mb(;` zOxIr8m6~e2E*Ox90E8kW2_1pC-{N!(?q+0_GVQoHhdbElOT%1w1r>W~9{uJ20F*;l zF&GvUdQG_~Nj`1q!>W$A;g^X203hoP1`O`B{{S%)(=<_{uH~H>Jh?TvD8X5EW+z6r zoE2{&3bxdLg-KQ$cE%ps!lo|By+ZuQ%zMC~L-FG2!_(xRoONZFY`7LJjAiPnZUGS0 zL@Q|n8(1lpHv<0BEzCFH8)Z7m9O9Cs5fg|rICLjeS73gd^D%Fj-{tdzh(*E#;VCe$ zT`CjQD_cIK(9z~ToMW`YQ7qBYB~)eHk{Tm$N$^lEZf*!Ru;xAGPAb;vqYw&;Ob(x% z`i-({tr^>2n6Y&r;uEZ50K*VZ_q|+pO%PfcgCLeIc7>H)|+Zclh!sipzOApLN1#Tnq>Af&)Dr&Y$WyEnd0-lr4ks=P@ zu{H|EIeoe=-$PEg8cLKBTvytFPAWV+JV}8&ND}}p@6MmdGUsk>np4Y4PLw1`95pCy z(4V-(og-!v2#>A4uk|mi-lp?rZ0iOCCQHTX>SMzr%M!&cIKU{d=$4BQ!4jTzNh3-M zXwo7X6tN8KH#t1|(cH{}&vtT_EOPP`$`Fzk2q9#NDKV-4gX#lQ6&boakIRBw`urd`BYXq|Gy8abi^!YAL0} zB+Jv`(d?kARFXP&shVh5B(f|-0VA#&cJsfxv1XKHIs5mGccCwz$^w}{R)nR+B`Q{x zFKQB#FpzMGl{Z5q%&(N@VVAVqqS^|(%_S+?WTi$FJSPY<8#YNQ_4Ddit(|`A-5yTs zQ(aG_wBq(m8Cc;QjHJ*8gz(Mjk7>}`#OI-xi8&l*RmT(N;VCN5I6yV7|h9<7(E*2 zthec!yQ!TK^%Y5r^vg2!GcVEQ{5vz(;T1N)=_ad=s}P2^f<#KOMT)|S4AnI2B(Xvm zEK;P7yoY;j-3-IDtf3b9GtDTr?zJ{o2!BX0*l=ovrNRi*3MDYIhy)II4?nftjMb~_ z#+2ewvH_GU9~cHCiP zu}H^f$nfi?^rgdw-)19@J37797v`JGG8Fe2mw8)UGV8RBEq|k58}Z#3$FuRIUF>2u zVKKHu;le(AXlv;gsSdyN8njh(J33=oURh<_W5X-zBBzm?PkNXiE>HOYo9Sc18|}2MQJ5W|kYdZl@3ulp+q6#wwWLk<-vH0<6;~{tADIA4hRv)y|h= z`FjV=I08*ohYT+;Oe@T*8wP@v)|f^nkqat^a2opw7v?mpwe8)_G}^peQd}V?TSq{W zAgq&snAi*&h;Ms9%JU?a9cjXaz*e+)Ad!g&7#m50?5h6&>L05Q#3!pcGZN`vR&$PY z#&9~;NULz_=<6OAFv=Uts*B16f=GhvdxE^ki*4P@^49~_>@wQGFrm z*)@xaeT1}?kF`)R1Q2!&gdAY(>NE&+*D!jC=$>+3q4agL4pzn>Ng;-}3Z|{6pUQFX zM|4kmH}1gPb~YBj5AJQ4y+?HTLy0F8uS$gZ9wUdwg*l3>Gd9%S$9AM11Ou?)0F9Hx zY~d6wW^cq}@eYP6>;p1&XEw&Nq?ENZbyf2yWO(*T6tPIFb!0YWVW>AZ;bS|umJ*dB z-I-1)Qc#dbkr;!wVW1%0OtAz!+bF<-k^qfK#1LR?BX6%o5v+-eCRxvzeN?E65od|_ zE!Sk$RwDY1Y<{gR--DdNpUvB;B4+|RWjKl&UzxfxrPZPA5b#@4Yr`*#4ILkMNiQCEhc0__$ejPbIEyALY5HTRC5{)du1s*TmF)})ywD;-8a zBctvKB!7Hsk{z>JD|U11Jo&r>kd>T%=AvYOeA0;Piqy+Lwkv{Tc$ZD{O%TKJ3_r{; zGci{iCvVWOBGyOT0QMe9Xt@`5%&18%l_6YY5$+<0Gggys{lh{4cT3G<7#wiwBCUVW zzFvZ-5~r=iY5rv^ot9aQhBF(-5OHX`l`gwR)&PPIqkvqn>U@a9hnEVPtjR^Zji+hr zfjD%0sQmR7zN0PBVpu*00iLR~K{XvUIs(&FM8fez8qvm~4c<=5x{`K_%Ppsb#v>ZA zKgAOhg!9MQK-s}l48)&3X1U_8%y^AD-WbiI!|4lbY(A7oefZFkzIPsLoAygD3|v%= zBkh^<>pzDIX5F<(QqCu%U>ynhsN#H}Q7!eW>jAoFhku#An9k8=Nht#275-|oVU&}C zs*r{ER<3kou$!1rmLBn5Q$PSHiJ1U&k@6gUm~9Z=_U{SHNwl{ky-<~rwWOOxXVkr=^$vVix%-!O}bYt+-o5|gB>^h|@Qg!$z7!k5K3D_wPe`elLE!s)~RvTA( z6NaT~jas;vkWSbbP)f6gk7^Pwd`_3`t^7dX#VCV7f6Qu30!BP>6YIneb~7}&>5onG z*ID|5gY=iB7)l(RHnq-*6kNNTDySro1^BeAG$ma_%=A)p9{oYI z2`U{rKpaUYWNjyo%uG(sdEYX0r|=f^!BNv5n^w_d-lQ|lG7MuCgn7+IhfzsPf842H zYh00eoNgm+fGc%NQP7hLz^KLvPgKSvd-|wCw;0J;FFG~P*qw@bW9=tt4X2}{`{P9; zDLzEQeGpQ5g2JBq2ugg=_$0RL*;Se+Jo}Qu>wM@lSLJzvzf~te_ ztlrs+VQktIr5sEcji6~D$s`>|i8yRH3bK5%;l|DK)Dq&O#-Sz&#W?J201%Xj0!pz^ z1Ogd{)lMgpv3#qXI)j1Ggyvkug!E4wt*WHX1)mUqDXFCiP(d^Z%tV1%J=sYB zg|PPUNs(m|+iqSVC{qJUAnFDND=~)LQZbxO0XN%xJH@+gmb#}CazfovNlKDV0ko5d zB{(d=DZm3s-jH_sp*Qj2^FkgZ+jhdMnD`Hb|5Q8LH23IwrXTG{!4DKk{}d>gXp2eY>+`7v=+Hb zfq%Ae6SfSWcU=sbCp6|fD-MGSz`BEk$4?&+6auE7f_vXZc%4<=?%# z@7ry6dweay*X3W=-gsl98T==!qppcN#KdD?|JI-ky&~a@E)$AWQp<9vW2_uja+Y81q6_HOe2q`c@9$}*_%*faGymjPFRpjoV;Sh;sqnWAKK)`vin^}F`rH|8LZ@ZQ7 znsZ5}id<^53dCW=D4JRt$~j`5o}!vYf}#ncZPCjdibEub;_AZ09&Dg25MY7`AmRu+ zK^+H(t+wH5K|=yD1YkiGw2z@bTfI5_Ml#9tiR$drN7NeV3Q%G*AdWn0SYs;;^!=l! z#8y2jAwQz4O;iaviCf3IYRYxo+NuGK3NtM$f>fc7f^ZAk1Ows#nX19|v*hFyVn@u#kpsJ3j=~E06uar-C zKgqD{#z5V?={b{9=umhM7?}znW28s%3`Ah4ow5Kj{?XePJGFqA#79KnLE;BqBVny0v4_~_UpvhV#oKGdSdGrYz-V@pd)nM##nO^w z(BX%@HYt}soHB_gs1b=Gm>pvTA1DApK3f1uYX^Bx3hEZMBAg4nJ-_W|(y89(a3jqg#gL_;S8i!ZPMmfxc3b z5fo2*d1)MbnWo!f4z~u|WLq_j?i2?n6Gq5DNYXe`OB%zdvx6Kypd!zQZ<;rfB`pk$ zhzVo>d6BUIs;JnSh6Dq3DOD&b3KSN>o#`ks3|9-y6p~^%HfN@ammb4e{JG^=7_B}f zM9v6`wvd*RmF=~K;&J7<roCr$ zt2d3pME?K_$REU*#|?ymicb-Q(C3pn8I&8;mPN^wbrDx|ixQTjHf3CYM@%=(B1v%P zdxkVp%D}Wn%#XHU0|_rJJ6S*hO-5E>tq%=ZKkrGpX&eFgR8Q=2**xhX-E zf&jywHIkOr>1Ci#0q_*P{5!Dh3#@%&z$4l77@ZCyTa47Jp-~deXlcB;H8z#m0{j$> zIhebhYi|C8#I2%MWNhG)4-ikXj5jAm)4GV2AgRrtY~T;B%1nMGopnsp)QsO(l#$fq?#9Hk!h)cqKOrdje=B;LQVbP=fIu;H`?dFx=UL^WS>2Q=4h9DGeTTa5KQ1C z9CqX7IQwX;X9`L#oO*r0G6OPG$z3wNM$iMX08LQMx84O?Vq38mHavLz7LA;R_ohC4wj>j=cOa9tp5EM*w{?MU zV{vw&iBeiY>H|`v)QPE!bD0e=%sPYSMACkj_`sWdnK8eJcv>i4g1o8^pBHmae*p06-sdk>hVJS_~-#W}E0 ztv{7xYustT>XF_MIBFB*G4@~q^Q4yJQm14I>BnFm(_68?98@p4T!NJ@rn z=_9Dxy?|?7k8*9?-@tLrQC6Y*p%`L}QnMa$s>QTuK=U27`aRL0@Ekj`I+S{aC2;Vi z7gsW-37J+}oOm&fQkEzTQ%MZMQzqrxDiB8bHug3)*MPk0(YK!qP?C@!@dRVfzLGV5 zq!loe9X$sQj;aB0UV!ABy@-=bjb?<2{MDA6=4$4SMVJvZc6UDHs!hPPu5E4vOGqS= zSC2!AA37;;sEs}t>q=^k{bc?cy*bGEyL3k&(qVW`8H>^U*Gh3ra~zgetHxTT>ai@A z^mRwewMrK>?Hj2Q?a-DydHk)bpsgiAT6`p^pYw6ze75w>NB!fL>+aR3PY(zf^m2B2 zRS)2K!x+l-zt()Ul<4rI;=XPO_QXiDQRmU6$vbIBdJy+ci8|AK`$^AN)}1l zHpjCMaf3r9uH0m6XaGk@oO%vE{Ae-iBXsYrIGoeZKp8K7?lKtXCVuLSb0Rj|73%95$fC5n9N~n4T)A6U%!ly1k1KNIVzr?rZ#{hJX!X zN?~7i22QdY{rDQH>Tmkc*@k_2})fBvEfXn4hJ2B90*hsTg&=h^%>KTRb3jx zI`z??pE+X@p01XVVpMHQQm;uViPlKiwy40UAdqc-XZ?lRFPclO&XclYaKP*&dV*?7 zW#n9-Ewd?B!-&{m;6OV?4mGtkG{xAEB8BeE#44spCd?ZK&d+GH6 zLGt&C0lsMI_=Eco+PZqz05wGFt~P>qT7fsBcrU&!CLPAA>9q@hexrhj87B7sQP)5 zGqpulDGe1pYhzV3%Fq-k~JPrNRhVr|(}q$q@_97;?8C;Q!)VNDM6xDFtn76%+b;wP@V=~A4f zT}PJj_lDK(W7~b-FHi{CBeQDlIrm!Ri`e%Z-ckPm3)Y6*Bg9BQ-l%LO@tua2+oeba zD(LtAv^VDp>_a84W2nmy6N>B$7pAX*t|gHg2a3|erimg-5#w-ftOmZ>19(;3HnNz& z8J{RV{gi29;cTezC{Q5m=3*-GdMDN2OWhjjR#fSVXPhjh77;*(RWdsH!W0eW&#(_S zaBHXHJ}T~S*-R50QcB)qjW^=6hb^0L0e8O~6hy;p38(EcDfo1`Pj2pRmZMN;^FDYb&Eg`mn1k8}70H7d&00Ll~WCOIy z*3CAdXi9+xPLOy+lj7qhBaRr=$MsXx=SgsWf#hL700lwzlt>l6*H4lJk3tf zsium-qzJFQ!s}%u_B_i5UQ5m-V~N=q^x!z2fF_D_7Y(y3Ul5XGZoxb&T>k(?^>E}4 zuVidivo%)a+y@q}rowStTML{;R-&To3&SGC@m& zq!N|uNd>i~Ll8o+B*@aDlUQ50nd0rU18igVpso(dm;mq^kGu-n8wK>sk`o(jZcepz zVxnm(1uOz;xappjkfCXkM-U%8iNd&IE-qAQuQ_18$*q#5YkAOOBtA7@e$uU^Ozqjx zS$6fqlZpqB**;P6rH4X&81z%5-EYKtvy=Lxn<}yFL&{uP@!DEkO}ywymXtv(wCeE( zR`=O8C_J_xTEiT-bXv$z;uutiAf0ZusgL3yj8ryBCPAdgQj$uv9~RtI<%Ddhexf}w z;a;nAq&S~Zt7gHD3pFDOyd_nRD11%gq1r*tZ&St$S)C?{$SzW7+Hfd2-5;OClOKhWt9sjP_a5r z26z#(+evP!V)#xICS}i4I)9=YrHqP8D zy;2*N8I3`*>Qt2#6M|AaKuIG>HDex^eJFLes`(S=GgfrOug3FDhh%~N7nDduN}{QC(M0xqRq6`6V~RM zib`B76~*Wxsu8i4SSqUOqJNX7SrwJ!k}@JvHlp?+TDMQ~cINasBrK&UI!d&XK-QqG z8pwq}!%rMyqz%yDPvrM#xwSUvVOIvwB})mo1xW7$rG$VBDFCz_)dj+1!HEI=5&j+c zFR2WE}ra87OjPf`CjhRsJu&U zcJ65FOrS{%7(<)HQ6kntB zL~*q2Y6_HsFsMAq0b{f<0vy+OhFf6G(0f|kAT1C80b2mXnMc~A0!io<814sd8J1<4 zur6KKdBuT$20yhnrJ4jn=kzA zD@zoShN!9^rNg5$BE*$Z*j<%MtGOX`YZva$>?e6G?rts$+wNo_2s)x+M9A7eNKBo$ z?4c(9cKdyj->%-q`IeJ!Zrkc<)F`djilJ6vK*3sYmH2{zNJx!EAb+Q?N4**9e_C-I zp;?^pitILv6Q-d@!{Njq{TgHv%TpAyLK%e&{^OYj=8%>}38@Y4{z`MpwA(1?Ns^@r zC!!JrVyOcd9XMlCUjBC6=0ldW?X}uc>&`HQxU?%lLy_J-QU;*gB#@@S)Tor0#+Th> z^q0_Fo$8L0B4GL74~CZ(uCI!l6;!Ar%ZSFtMQ}`;l%5dp9$EaN z>2}SXXhBFxpAia;vBpUdClNeFTXg$qb1}*nadmi=DTUm$tAsSJ>?M?*>GaBqo=w4k zq>t`Xw1Gxn)o-JIfpov2m=1WO$0=#+1{qOakjYIp=xZKCD@dX>V$~AZh}rhUg$W~7 zJUibl$4>3r+uX3?l&9c06@hJhlLFuIs2>wL|vQ1S^B zybTkV1#Yg}NQ?l>#5o4wH+_>kn!HqpP*>fg5Kxq(WSEs}+aQfGu+shF?b_zgH+>fQ zfh^lQXxnXmRmB&3{V9J^_9bje!cb4`3IP+SP-EzG)3-u;x1VRrxTa^D62oxpO1gn3 zr@(6>RHvm;H9bTzNDFy$F)CtUWQ1SLux(OqHtDs!7piXHC?F)NP(V_NI0X}{NFx$s zgh-jGBeZ_ht}U)@Y^<+WY>S6qLfuWfk2&2ojZL}`0U=H*P~rrstQ4pe1LK~YdL2#b zkur`8jWdRe6RDbpJQlV<^TkjSiYkh>VHh<^Op7X7D0PK_YmOJ)<%zb;RhGBnKy)^e zPm51XKoimjSD;}XvfZ81IjY}TxD32P`?8exsdKw!DMaGasDigi{hH2_W{lsi-%A|{ z=-mz%S(UMzMuNF0aAO6qDygbkX=*^0nmE`ZKo&A(5UTNb}- zh*45hOvr!~Fc1|dRLKVcjKUqn?JF=BF4+y|dg4m7=BD@q#yOh5r@ zBm%M~jI4f{Jw0N+o3R|{nZAGLCdBD!ZZIj;Y9WH`vIxZ{`v_fM8E^?jkwg+zMZDN^~JTjD!Xm9H*o9! z0F!LGqT6N~T27V9R76}D@U9ae83`<}mNE@@TxY;2FsyQ}1frm*Qn-9+O43VJv?4em z%pnixX8Tjf#Xz?qn;p-$yv-harIS`x^dGUqQ{5j48M=Jmsf?-L=6ZN0VG?b6D*r| zIbA8^uo8RZlWXu}+MeZENa6q_U(NkC$apuW{4YA-*giWQZEa0*6k0@(TACRW z7J&_;Y0xO#2`aXffHnic&hYkYm)P#(H*KL|@}%ool?7ly@JtB+XpM(a#|nuzW3+qM zF726fC!V<`3y=5KSnsHDm1<((ROQ2~9#6I+?(%hlc9EFNw*~c$qQyL7v zHEs6Ok1lp;Rc4KqgGoT@7$G-%2NnPez1cS5*k>(Vzj)bmLO?+zr%52rh#-|76C(qL z!$uqZzPFi`($K>119tg&x+c*{(ckM)Y1Qf=sfa<8iBTz0DIiS)9-X>bk{7PkcvUuA z#u}Ph{4$uC;iHWo&O#bEVO1XaLPR7Ge6l>#d)_GB9olC&&D*xSLY!c%f|KC|CP~#e z;zWod1~^gP^zZ$}_FHNiQ=!+Kv~5XkVNXk;CDAwqDcn@lz(kEi5ldfKeJ1JjzMycd z9}3GElCCH*r>110o|*|&Bclx@W@$Gw%h-#Of(-yHPb6N@cV5>g%@oF7g4<*#Qc{^n zR7oJKQivi5lK>8y_U>=8@|E4%sW%HtPq@+$`-8n(Xk;x+q6r9aID63PCsSo2NvEGw z9TdoP{+ROSIZcsqY3ge*d|IwqDCMS4KV(Yr&rZ*{#R34WDA^Q`9g#sM#~?S)c5QOp zrqOJ)5aB5bQb&nIqI^dX0*okNk)%Y<6^z@Hycc;}_7}=(?r!bw-g(#FAD3Bf3oo{v zWm*_YwHB0?%EFQY6|}edU+8vAlhWpEsj0{{bhUV16NgM%vk;}JYDsD%S(-_d5M)Ug zY>~uO-4G~n2^Kiq4d1f8$?lxEX%0F2Pa41^X-vX)Xpgwa#sHJB+kZ3b+{W`Ty=|M7 zD#@EgrPN%Z4Ys#&Tgz-L6(!_imeLkm6Co-x03Szv5yEEmEsN1j(@Nxv`qBKoW5lx^ zEkv^{bcTA0X`@Rg%--{S&>=!zAVXV`pJ&-9YG| zD%fabmoosCKxw~7^zmj&N=VVEPP0cHfp3s@FHp?H)q)l??(nC5*-eIQ>vrHE9X<^n z5L6`TKi?k^kF?=ZPh~xzKf1X^%HCinxO)Ep!0pL(z>9SdmQ=7vPjCj7$UnC-K~NZk zo~M5e{JrVJr<7T(FgWpQs*JBoh({~qD-3bhOiEZ^lNFf zf=jAV8k;hdASm!AtjnhzG{7)lNBM#(e3d~8Qdi-0keIU?)lEp!EJdlQ>vw*UW-M%~A)ud~XQUb9Af|IczfMoPz%?;C}DvEaMnuG3=YU)6y_fUO=pZ2mY_RuOR2zcHl42Ve@BM1hP>b_9RH7`3z3oBCILR!bW?)2*Xfhqo!okmh+DgdY9esFJ>tFQ8UdrtC0 zk2H#9l&acouqA6bWb-3YvWzEq6`0+%=DQlV3Ang)m12>$3__>FI}`me{TVeec7>ap z+{)9v{D29zy;1&TRD|kMgcWT`a1;JYk&0W@#tjv$8Y~ir)qL~384W5V!?5>>1a%T) z64bqLGE@gD%N8W5aaDiOnqRSI)I&Dq56)4F*Z6w7Qe2BDIs znmARhQxzf&$Y}_-^94Thf{K3?8k=^Vd84`ZzFsx-zpA@8E zcEQ`9yu#N$vUxWa2~u-Q)txr$UC0iF>T%@A3SoM*vVam(E%=mBLP7rk!w)x5f166! zDe=s#rcAYnLs3+iEV154mB^=*fSzU`5Dl`6sE=Us$-T&XBePwrmuf*$LXwG`K++6s zBf=!9X(W|l1C0uMQQltjGD|MIX>S=-(?DG`w_F|K^%Mo_@m#9{(}Gfj5`u-C2p7>T z`Ihqk0II6oE)2z$yx5}4%@qwUTRv(_1fi!A)dUQ+H1}g%z}l+73urlx+p}(LbDMR9 ztHAn%l>!o+M5+MP05|~#c+i`B_o;U~qi(YDGz4Y8w0VM3wJ@}v=r#!;TjE}G56lFR zHi{L$5PqQK>@(CQ9zR>1a^(~?8J2>sN}8;sYD}?5O|j=xaPl=BJ0C5ngBF#^kP-nL z9rmeX-e$^K1nNQo1o23XBt|+$)f^1OVSx9uJ@iwT8Imop1IRb%xeH?0w8~F#0lLto zm8dkJ8}15~t_zx^;yZQgt2h#RKFP4pk6~0VK?XG>vQ}lctB#P%8;A{BpU}_q8@8#5 ze?rW!W98{8@1hds?pn2^$LzooaL||qCm2#^Pxr)i&Bj#kt%iBfL`}ke=cpw#WQXko2P_!Gd*Qjn@^Kqo}rpb zArY#ytLCwhKSF5S0EudlHv_?!XqLcd4{A&TlyM-y072;j0#dKy81WLbv(4jq+k533 zm)r=Kp};xWrrlxe8tsHu*C!YeHb5gk-O2w|pF z^5>`hKElI@Hxnmmd9xFUX(dV0R6)SvNm8L8sOlz8l5qe)$u8G7&FlMnFdn-|dj8GG zLQwV0r2$D&+6hoMC|FN&*a}LKI*_6wvigk0EAm&Yyb=kqj-dOP=4W)I!|!itouq>-d0M@m7)jSsIJUl6VI$%0Pu=eVJt zC{)qAVbrmHnk5ml!3v1WwhjOWp~&+DVm1wNW0Ae3pxoKot_BK{R4^q;3hyfF{K=BNG z07f`bcK&8=-CX9%ZCR4lr!RPx`?GEXB`Q;wE5%^|rAF7gGYLshI!Oih&^)-#9qLCg z(McauY652pxg<638cQVgR6FI64UvS!CID}1q-{(+)4Je7-I*gsYak^4&2s~w;i`X! zih&^c;43J5M9p2jHX6T}N^eq9-K&TWUb)GPVZN_0 z3V0~Ghf^ENnrM=in!RD6iBx>V)Ul9-q+mZwi6JZ{1Oz*{2;WO)n9kkQ5}8sILWHko z*)yw&l#{k3(_4*qbN!Ke*$KHw3d~v1+p&AgHP_Bch@H&fa}DU?Df9FXc!}ZeKc*-}y4-)ujnh3$#fixoG&xj<6yq z!DSwxbq_N7HO$FXf@XST!|U*R)@(x?N2;gupoNv?t6R-IO;I7?l@)>(jQgbx##_Gg zu5QDq1MNz{CL|ybqlxh=X;#d20l?5hd7Zj#SJt7sw;5|OvAI*9nNN0wIuHh}j;&9u z0)jOL!9gVjJ|f-tY=2rK>t-{9*JT{l1wv*V!9Zzo4BV!$Ow{65p_~a<$f$*G)6^>j zsstTbNaSnTBMq^cEhr-fNh;F=1rHGb2|OccF@_b9ouJ!XyPMeQwzzph;^~0X7o~y< z?aGC^Un@+M09NzbfOvRSBxxlts@Z!UztunBe)@b7XY%ar~5qMtWGB z?MP^&U5`xTZDWndcMy3U?qQ;@3Mf*{m5EAPYfLGb()myK!i?|YieH(P9A%(0@BBxF}=jR#G$#A%SUl0YP24|aCqkfAC`@e+39Anwah^|oeK zE!ApnGOKsc;@Mk<>$w}8D>fdvV&8M4!VX} z&}P$B6*AOC5&1}`ib5xvWnvnqNh98Fz{XEEyRDqVbzHYIfLPg&gvlxB(vtxvNF`IW zR9U=vVY9rxd-5eh+cLF%PAdIHv?cJ`QrKWF9C7S*x;$t?iggVHQE~h*vZWk-SH$wp z3y~=)p_dlSG%rmSbTfJTP&z{_(7QUpNTq_#mrA>mZp*BH*-E?2#dwfAm^^k6B*xvb z5u{9ywrY9b+ZAUyt%6OncWQCVwu@=Ha?!GtHK`2;Q{xOWkVsY~{{XQ?Mgy|2YK#L3hIhj;#B5fhH3+v7oM7?dXg`sKUG6DiX>0au-KR=Qf=ZiG$A0U8kX=a{SVZYq(cx6l zpZruZwo}0}ejk`$D&=*RFl;WemY$;?U?Tl8dDRMz(fsXXs&+giF^((9uee;~2Wpm} zxWOcXLWCq@M@hgEk$_5|%o0xkSK0l#a@+SCx3{;o4&}Da1lqd0r<18rqLNYve(;d; zNLGg6g(&#Q>s3lIzeM#}j}XH$e3XfeKnYB8N$A=cV~xfe6zu9hmDq^pn8>WE9^&bK zCT+D{?x_nt0mPU%Dk4q*>_{5E*)R-DO?{Lm!tuqmZ($8*4W%j$txkTg(^#BEimFiOKQ+Nw@B|4u^QfT z4u$N{q=OV;{{R+A@Qk@v9zQVYSH-ctyUappmWs{$pcl@98(V5;!}b|;d@ zYHg|e#)u(BNHP(MzU`{nDJNlp;Q|H}Bkb`C8Lj2JDYHUdwzhM+%E4L$eT@eQ9oq2M za%aallQ@qxIPO!;o{Hhc*1xCIVYqHJ1xEPjXObG_lG3v^G>hjx4^CKyhhr94%7Vvf zK62$ZJFrsWZ9US8N_BXNO2lj+r9_z`6iQQp!lH74ljgw;xtFC@`ML-xV2jrapea(? zfh)AP)KQ`WRHT24s1p1r`kjE)rZ1Kw%sCE5gytFss~Akl1vNLAC8wxO$r{V^9{0+P z#nLdy>fSc&w&dE}Jj%Qpn@YiOfJ_*I2}mP~u@V6!1G04OGT-@5Y|_@{t7v(v#=G3b zg1rb(3jDx=A=eZ;yL25zu_-7r5=vH5>h4*}{;iLc55=FU`9lfKBRAo>$0(Zl#s^p;hb|h0 zXMuwnS_j)VljN%xnPgzKOJug;?#|o(8@<16OsOv&Dg?H$bd8{_%BE*l(X?TNP`9&Z z-OaNc#ca6K=y|J03T)Um_TBOT9nwmPDGZ6!txE3?_dz}oW-7Ylka6EcF;q{~90CY1 z{A|_InR3$atMiw1n3YZ+BDJDj&Q_2`xs^hLaD*Ei#k-x>?wnI-Sn!6zfm(`JAQ2?$ zQ6*(zF{A-Fn#ZrrTxHkEvuf!nb&S}!hMTkfy8G0_w?*tw8)zuDhT;iMBm}krUi>Nj zN@Z+1I=nM7bwdiGqr>U(>@qsH%Lz{%B`dd|8KhU*)h$_eZ+h(l0FG>J!Vb+6=p zpV@+}N>u=`WUjtoRNk>-qrv)tPdpQ0rZYzlT#x0{(N>wLAgZnRM6orD=BN+>CO6y$ zpqnO~w9LiB2pUDig_GetHR%|U{6u@=fLWGRbayqk?n9|tY#}}{lA)o%wr$YaKW?Cs zr4-K8!sya|FFj?!aQs#*?Sb`fI?PsS^8I(rQeZ11NmolDSfh+6*-W&tGdjy9#GmB0 z+>^eKccWO=Qvl9DEy0wN)t4n>f z=m{t=2)951B`NVqnNTK#oJZ7_N2>HQLTmcI(PG$6EiCjAMT0{O;c8U*n3UAa+s#yh zM`fpJ0M}^>tZZFzac^I zD`zrV+qZ3vAuPB*ZFl*Uf#On%n@SY5lmJMLQUHI#qt#DNGPYC2vfgp(ek(zS)KcSk zbI(rM%UX;vvo zQG%EzIK@o+{{WZ0k>(+3UB$CE7S|TSdlJRw=g|LMr$W6Oib)`HA5CF!7 z55;rTzeh87QX3fQS5R|aB`lQ~O=kK>r$(u(hDAntmtDR{h9+;8Xpn4T70s>5gMNQ2 zo!_PFU>zOVO4P8Rl#wtH2uzJJJ{Z(gXQ8dcvU@YkZ|>MPFE;OXq(6QVg_i;Vam@{Y znMnmKhy@4%A^;?h{ZaLe&|FW^4h4f&^&2v#H;3Xi0+y1FN^d@rjFaaWBto&th=Al7 zUHqcugAG6?tIpWF$kAx>)VI=713|I^bPxukqym86!cHGTu|lZwOHWS)g2LC7N_Pt_wu0>~9=C8iZcBPxQj>(apsH~O zQ>#ufvS}i>KQg=B#?Y3Km(l@BB|+_J0u`&m5d*juedJ$8e zvHG(3WXR&Bl>E$Wt36dyG;H#?is?_~vWT4TW4BIAJH>FE@o0H~w52J>y%0))F{LtK z0TZxJpp<|`2sb}=T~+nX@{r;#YKg${JacB_sOM0F5HiFpD)m}HTndY>xWi8f)`t7aMeh;2TnnoYPminXLVWTb#25UmNX zpTc|899<;!8INSRC@}*DaHRQ2uyK4oFjj>xD^NW;oMKEpL9(Q3RtBjgubAZ`+~JrCAG*_N z-Jp@FL`cF$8ld~9W@2$SqZ! zY3`RXhAKuRZ4o%o-Ozk4qatTYJm6o!t7YM16ijxb?v}0}eH5ACx0-76n4&|(GYx5kl z>wf;t)W{K~!be^U^~A?rbT6_j++_RDVCgWIwOgus76?zjMQMM6)P@F~rxJ?6EiAig zRI|v!`kQ;s2fCnrk*NomM*3qIjWD6%FaY(yaXlx9uc734hJsEykYP!g;lu9e{*Mt= z&?ugR9jLNXu_k1BrBC5$hO}907riR01jmDdEPb_KZzj85wuRsV1Dkp!>b|P zxTe*$Do}ty*kkS=aq`=@W)z`Vk~8x0Ob&*@Uvm4V;ZUCc01J5VvS$)K*yF_1h}1++ zzYe&i?oGlno;#c{jJ=+5Q-WYMRrHYJc%RC(N6Nu0sT|d!nl=qPK^qq+8trX0;sT{4 z6(nOA4}5y?+0iuh+SbELQ)vrON{UiWkhKBf8ny`{B;YpHsP#YAmrp$$`j>u?dWFYx zHh!2@oLX&7Ke1W4g_@o)A?eCx@%%8OS7s3~c36ormD0um%D zN~8j!4y;L{qtecidIp;b%ozUwKs{jQuASs+`IutaTN%RN3dT((Q-3ucMr~n=_trKw_rNwbZmQ;-X0#YOWOZ@l;b_ z^4!@fDR9|pz(1p?jm`KE&36-idqhb_ZF_H)TB`+H+6B7qm>`9^OJI(k?1Ua5iWgUYn);O33)nNjh!RHl3E2 z7<@+%#WAx&@ieQ5V_5u>;yYrHtD1O)BqXqN16(%*J(2cby1TCW*Oc6g%a(rirPQc5 ztQ>o$idsgoGvN!{iKh3DdGjscA$N%lB!ZNs4TL15iH?(pPl^T#+9(h7`S@{V-l}9? znrBX@bwZaao~>2AE?vVg`~tfgu9wTjTLyNiD)iKp?ei*aAD+*%YY;a9#`{S6hp_DC z`OLLeufFR^Lf53WglSqzl2WCsRscbS@PV>~TdCQ`VZK(2y|z z)V0`?uQFQabuxYQwrcA#v0>G^+7^4((6f}gho9Tg6i3eCqtkeIg|O&CM6`tgo){*(JW;o58c^L+qSJ^Ynu~v)P6e9lf

e`K0xl^FAuDl1R05SMRg4G| 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 z z87le_a9!JPy>%kN?sdO?E!$HBh!wG15?CXIe8hk#R!f8|EpiA0xi(qlua)F5_tzlR>S3LI}8EE_^R- zM;`9U#;TPKQO2;vR!`7A$YH-F>9k9_L%~s%+KH6xAh6Ggg|W+|nWv zs~Ui%Q$}040FP@6gRQ{h;j>K&$hGZDQ}Vi&a-~?w z$oIT?Vu+2YnG09R2IW<`nU*z?g~YSVrp6#pIdnld6Qg=x9;-}FZ)Zl&z%Au_pZWrz#D6$d#l)OzFBGf<9jYzwzW(h3Ryr`RQOix!~ouuE=Wq(QTnaw z!E;VegQb}Yn+(7*#XKJ^B`zNrq=K&h0OcwwBitsQM{5Rphd0nHYsGu5*#gmYb3En8 zU$|1W!;9}0h}eR>QiP|18WYmG4Q~f-RyjHsWxA~;v@23Y)xb$wQbcLBV+1mgHZ4ik zW=cxDR8lDMYC3g_DtD)+rr5C}C6+Z?TWoRMs>Ut0#=s9@=56;{L?l4Ozz`(uK4*#A zc-K4JzDvq0Tbk5jRHf=sj0BQNz+eWzFcrosu_7OooeH|0pquaQM-G$x3+oi$Q-@9wyiF_b^$^QUMKN?a(kMOJgD!&TIa6HE*SyEZ~Z!d8eW~<%-4vty8i&lcfY`_@#SpkB<>po#3e!mn~eoVhU799 z+k2Ka+t_Jt{9#$0sv=%&f4V2}rOj@xZ1>q`bbPJd{{RBAN0KwZWmxcP{{SvM!NSu> zj6%1(pq2M+_L;A50DJPP&1}ZkoBse#pT>=oxjEvtSY3apIsOfKaxQz8LPh~rAq)V# zW;M2;olVqSUv2(6+;IZ)%Lewo-}+#F72~-1z^J3OHl4o#A`Ln-{?8DN24S29wfsqdQ4FjF8EL zD{n-On-QaZ3g3K&NlG7z#uwRsJahXKhkT!6zrmxF_H(=fKgeBInQQ+5nh$+u8DBNv z1X9C8LePsg!COa7D_=%tK6}P|Hr)2_W5lY@tXHwo$6{7?f16Z2nrH6g`9+U6ZO6so zPElq2!&rRpDhg?=FXv*Ica~HTEM)nTtfX6YtaQH{R`FOh2`>8(;rJq$UuF671eFS48tHGt5h~MhowUm7PLR6VGLlC@3Gw9x~dKMsTg^XL8(q#`T1}p1oj@xEvHG`{||*p=Ezb9c5L_`G*+5a6DeB zJ?~Ksdc{d{o}SB7gFU9NAfk0Z>c`#Z=FbklD**fFI@DnT77k`$T83_8V48O~pj z=ijusdetrw{m~C6yc}SZjVq2bGt)%7HFOsXingZ+%X#l7;#5z)1MWv-;6+P z-U7snckj%JvEIU@g}-TZg>gt|EP5S#JnI^-H#wxKNMicQXgd_Ai))Uwgb_YQC=;mk zyB$i9yCFaEHQDlMBmV$;R9wBmQB?kN zzzF{UkEogHfYjBIbfX*T6(3))ZmD(CIAv0eVY+*=`Jexl)69tn@FH6?u1cy1*G?S`YK>?vc80D>n_Np9`-6++*Ew)1z; zxlNX7Yxk~l#!%pA&Ug9 zC{{T9kQg$d+pr6Pp*|X(WP2OxhQ>C}Mjyn__;qB9Bw_isyn}CW{{S+fN$MY=JyYra zZN@U@YOF=e^y^nwAf=9tAc>!9vd1%g#YA#4`9wuxo?=`Zo<+OQ+C}xf!&XdL{?6cp z1*yVaCIL`ScP+OA5L{8#0)z}ISje)Rvox}~yZq>zWb0Bw3Q`6n5>^6~3~BJkjY%7J z)%U1QqIB!6Smqe`er^6;gyE69!%tC$PSTo(uz4=8_Cf#_=Sv&+;}-YVR;q;v)wg<={Aqm_dV=YWC(_!?3pG*G;y7(?7$=5&H6)4| z;}M2U&cfDP8{bRYUQKUr>K2VH+c*XoYfivHj1p-jo@r@pqp8VBz<`ntlOVw-Y-~L{ zYLk5`zf}SBySg^`knlT-GatY%sBwsmDs=AL2c^$pJ z_dz7NY6D0wJV$v8B}pejRuh77#K9_v!fAF%ePv*yZiiH$)HaNL4ptm@fqP807EX`yKU^e zcHY?vLRMDjQ6WVdh>S1=T8WMVs#5~>nbNGgk}Vn2w4OWd$S7z_=ppQHs;S%7`Ih=Ql`J+n!0MK$DVcVu#TV%K5DO8yx5D19WHiOZPOE$ag#gY=+Oc+QbX&R?$iH)R* zjuj@i@nq^wCzLC4y&g}aq^6v~J4ppJ=2Br{Fo{{Fy2e}p;caymxVhm`UCIWHY{IZU z9tRDx?4dF{MFm>Tu`oZRuWWIO+}AL5Zx8CmQOJFBj9#BLV3-~(%(`4pOctR6C%xtw zhi?IJd+`?S=7kO^rQxY5SsihuQT}pIx`EsCl%U(R>wm)H(K!8zha3L@c~GW2z0_st z$5t>L!HZOg6eVKhsDKAbH@b)!PoBgAu1Rlc*xDDQTo_g-WXeHn1(Kt^1FG z9z4T$94#F~_()L4i0H#<=&t0UA<$B-iUc1bBj;7gM@>E*Up^U9Ssp2jcXheEY*1d_ z?c2m2!@pz9pIU>d3mC|pI`Q+vr;iH5W&*9&rp(|-k0M9EquWZz<6wqcl`=C6M%Gjz zhVq8?vgu*t;Ct|xo*f-LaKe1}^l=n4Xvp)a6j*g`HHblk(D`Djx>)HWLn0>TmDN-< zu2mCr5KEI~8j=S#2u?f(Gr&Okb3z`h*#lwggDL>G?bN8?j9-Ol*cS?wkpXY5W$Cm2fuE2WzpV~ zs7N?)>h{R=^R9NOAc?D@^b6`+tRAlV)q{FS^;e0mf67?J1~yw2#}nqUoCzp!x|~Sj z7;ZZt`RIi?rv;&wSt;H<(X?8IUSf9r*(UC>kX~nO+oIa)-Lm3cU=$@p7zlB+!d(ke zpz2PrOr=5~}UZUm+ zoGhJ0>PAk$Y1eIwt_y}&;`Oa>@W%BN;P?XT%pv+s%U1sKy>K=&YDZ2kIr9ze+6SFx zztsj}pYmH?ASrSFGLsTGeTw!~9Ggf4jeGYW9d#G>e15Kd5re2tsQKg3)?=c%8b+*W z;d*iOW9r+k*b8-Up%@cGh2dC&QLZ~vjL=}T(buYp#1ysIl~pQBRT^2@AZB>ft1tnS zm?wNYN60rPOIgj+Ocz3kLZxJ+9Aya#I!?(WPXRPA$}%hL=#ga0j+E`t2_yX|C#rUE zqlK4!Bz`8HJH#f%AnH91PL`pJlT6)V!D*UXn-^nEj61joxgejXnD2Mnrr=%;4_q|z zM#QS!#ilv{Ehrf1jg=u<_Hn!lRI_IM{{VUx4D?J2H&Ev+^N@N|nQ%{AonXK^!&8Z2 z6*O6QEMSceH&IQBN`@+2X1_B>O&Fq&4sX(kpsAipllmDEVrPDG`?f9g+>PM1EpGje zo06bS$Yb)!Ncelcy71z9x#I_Cq4rda zxVTK%)g1b`YSIsn!1gballeZ$K)Lgb1MX zK~}0Rf}pZT+DIhqN>U^ZrvPx;P7^^drY}%kCG{oKnjWb1ijG(^pI?>`Z{zUPN zG1dSkrYChga=;Q;qknux=vW55mhWar_UUG!H=!<*-Mp*;L%N{2Fn~c;q$^Gur0t`7 zn@25yX=WFuWKIQAcAQBEX~K4l2%&oi&ADqk)#Dk91XiGf2*v7fndzSno-ZzXato0i zNQ}(`0t!tYpyE)CqEj+39we?7rAR4F7N9AlrK2h( z8nqQ|o`NP1R}Q*~o%)M}WqiGe<_u2`IEEWY5n4Pa2U%<7Gf0re)b#O^{^PiL4gUZ~ z7ZvmUb zZ}vIB_(|yE4j#C1q4wlo0v)y|VuOHn92K`11`PGZ3s}jGMAA`8rg-*8qYLH8mg7xc@bC0}iGs-`)ks7h4x42!TxvPc_C1t#R3500FNw|SdHxchgdIza^`Mj*@(I_H4lS#8=& zw=Oqnb7l;!2Ud|X2nq#WQgJ+J1);`0LHYjx@7Efl!Jw6_^*D|tLkcNX?8Y~FNw;9A zPk`i(>ls{r&9%5j#J1atIG(T)JjnvFZ5Mfv``k-l{{Rx!fH3kUUVv75TtlW}R0pg7 z03}u~B%N}tS*BJxw#ku<@9Yd=Qhk7Nl{0jI<^xiA19FW~!css;@(Vt+l;1bP@)S6R zRi=83>h&oV%A*qL1{+ULnK7QF;<=Qw80Lcvzc*8EWi+=`zV1LQECYP08HbBM0+TO?AF=A8XQ*{ zQ~3K5fCUDau71kZ6*5PbFr~q0=1sCk9wjYQjiYWn1b1vmeQ`b7G?H(b@~qpl**ejj1NZ-VWTv-6d_prXiVuQE0!=Gsb#F^ zndsXT!gAHm$0Wb_C{vfd zmfvl~jY(*1ND@XT9tH`r8t=eRB=%!&V$*l$-TH+q(qzqYy$uz%9}DBO-wkf`CwC3NlA^MrmBKC zWpe9q>Pjk-Ol$)J0b#AUWtcXX5*(E3Z0boQ2r&dnKg2NTrtCHA?!r~2&kBG_jERwe z7{SL3XiD_ymT=rB)Q%HDon?GJmj?@I%LPPUoad5{J=`|3OM9)W@FvfKstO#c8d@3jf;wCzkzt)71R z6n@|Goz9g;y?<(^H0{~5uVsJ#)7Mj{8A~ekV-l$9E>Ov9hEydnR;#Y9sF@;L?wN<_ z1&e)~8y@4>d5zZ@(7yeccrFR>qzq>P!-rK%Ht0>MDnek#6Fzmczof2*^cmOLH+XAeqvl1_==)iRkF6)Xe^!ag0Z#c(0`IShQ4`cc}5#C0;4| z7%6cGBwI&^R#0LR$ke#5A5h=|urPg=HY0V5Y%j%&!P{>V1f~q)lN0O4V*^8{S#LPE z(y}E`btW)S^T()+FsfMVU!)GJ`h3V4Z>pK{I&{PHOx4lB^33dDdPz2r=-_WjlI}K= zz11(bT$8ZOSKX-1qwqgb)b_zXT*v2{LI-(+v5aI%}S=eE$H`TxO#J%z1jDYcSkaiTtXH8kApp zWH#F*Zl3Irx9H|VRfmrXt{O|pDOiwxTO*)@h$9ec$XRJYX~2z#>66LBGjwo+^BDF8A+pofDggBq?`_1|_u9=3UKQlJ zij^tEgBXFeMghVGDoDd>(Tt{^&2nUK14iMIrPN@w@FRiM(s&b&z^~~VUg>vJv&W_G zq72WI)$8!8rdF@R%Q7UWtZaSX@-;ArHfg+Wv9Fd$ALZ0go27saWSQ2h6apHNE>u4!D zkYyxbe_g(Hk?2(7C|JSqyn6)4s553;uAdIZ@R{PSqpqfu$5jnnWIPj7%MccsNVSi; zEv|%u6kBOpN)#n35JA{e#2zE05scz70*sq+OsFje6fp#C2DX&+sp@m2e~Ujx>wPnN zor02ssu+DN)e<7AM^B5!gLm@`F(dbdO1HmP0v~jbIuW-)3g)>d2NxZZxz1`_f|By^zhPSl>Npnp+44C^;QwN;c^Z4D3CH8;%_$8n^wqDBs|%{K#h(kY^2HA)zoMhr8{Qi zxM69)NSqH2uy`Mx8$N+`iwNqsP9U0jaQa-w8oZU*T1XaCDmy}4K_N1%ZlFk{5=FrJ zWos>QP;~EU;u!_dU>te)RswJZOj6diH>$)`SeWUl_w=O7@6S$0|H= z6}HgCd53vBSwIIv@FM3<8YI#kaG*tre({Gv*s|$=;{(jr;};AMZWS<%(}#W$?~OOvuk(a;c2>QDq3|X zQZ|&3L61X-KO=!w_GQBI)yLYw3rPzf@wE{WM@BgG9;1bAdX%K9#53%fuP@X!MGhre zWW%dqi^`TKLS>d2Q4Z)T>D-OVec@%14TwA<&fhn;D{%h+5kI@mu^QEpW{%-Fgn*ws zBi}~ru2?=FhxDEdQjubkzaeE-#qrqbmukIDTD7r|s0Quw%d({x>^TyBmSO~((&@Lg zX3!8y2BjnjjcFb(gN)&{O=szE`E9FgD395o5CDKYKaBO&YkEq{63I(Xi{iw2*qgm; z#+EH2#^GU5ELQCb03~p?I3IrC@Ynt_Ii%hVtu$#xu#y8*J9c0H1$;`sH~;J zM0s*LVpUrhsH~0zdC-eBJsm%s@)- zTx=?{rZ&{jJc+fMiwi*#fCc^5sAoDGTxq8Z+kuZAo@Q%4ZA?^p;SA$D1 zr>Bysz0(@CzLGTJtyFP9);U}@{-565P01RY9}(>1=rqBge;BP3236EtF1i7&wI{GA zw+zutai;j+&qv&E8iJ{}Mkd|KI;g$7YxN!|CM(AZGJO%lo4L1)$XC?cLxy5INbO{P}I3rIDH&xPe(j{UCF1Z zXxys}6|_7IX9PG%J0?Aq2dzTs<)2SYlj~QH>6@QHG*~PZmCHLY4-d-5 z($&#aZ?@lbSO)KL?Hrx=PkGaCX5)7fP})>SNdRgi%zqCa9Tm(z)OP{JUnSci<8?q0 z6NFMXH*;lBZp}K|F99sxE3nldrGsJKV{{TrrBoSmR)AJJ5;5DmI z0gTd4`{S;Fix{8H8pmS|GUJy7yrk$VT!jonYf&yG5-k2TQ0sQnB{~(v!g8NGVqlRtb{w#!~6-TcF7qYYe5s z=x|DSXsJTe#z?1zF&se1SIlcDzUCyINjx>SN97w!NRSc&N0901{Ax^bVe_y0SkZU& zbI_Weyy4&HXC~lTe;UqNUK(sG6N4~O%To?1m6}mgi%_c5uz#9G0K)ctqyh!U3|9Ag zl2$c9#2jTaDxN2-bxj3tZ9{*xPpIhw=MxpEKUi@5w-z;;x?7NGF_p!`j;@T(X-Jx8QfiGB|rs5+4aZesjB zJz2?FN1Sp*H8nKYhC7SWAclqor-3kNQeu*SqDOh7B(U;HIx3E4_ULZ_eZR}RNK#~^ zsO&;QMxPg4kpzgC012tDCA}(1VZv0jV>lU3zyKaBJhoM|*LsNPo?oh=!zppp%(%`a zP_R&7nRX_`v5K3Zm8FXfh^;`ThA-2+?h-F3hgV?BdEHsvyJJqRN;?vt5{TO&BN&Wl zWO2k$&B?^Ufwv8l@Tv24uhj-8fl}t2ozsdOs?%an!H3D3F=0L-h(_|PaM6qh4GTRL zbxcL)VKqZXO%zOJxndLu?qznyp6!s@Tv(3rM5xSRq(DldPAVZFVhNokXTqQfjB$)$ z58|DjQMPKAJxzWQol3)fL1NjPp?*dok|e_MJZVgEM@3Hr>*rKYghfeC+u5pW32J2A zz=t54t&U*inccOex-IXVbd7ot(hi0~PRR{~l?2HuDpwtbfR~m8I$dlfGt-Hlfrb;e z0ToIeU&?s4H`dyolwq+$S%Tow;gdWx#73)88bY#1=M}n58?(nP{{VOpNwxWkouIvF z#$vYG2n@8giEXlwNI)8s$Hbu^&k_m7gcb>X<)sP)#48Yf>BAV|@T(!G^-rEB#qk{!TnBW41EPo50e$s-U>gQM!+7$fDqeW_cy<7Ex_x)Q5kzjO04cb)3y52rm}aO z5}iKUc>e%Cy+x?0Lisibnl=Qn#T;0$?I92!ACA5t@%H|qEM5C--p8fHe}h(5PVz=2 zH16G0>olYoGDaNBP+5K4R(T0vcYu7jECbl>K00f(SDFYcLSVknt5C=&(3O8!ucB|C@@PRna01h%v!Nk|Pqw9~Wcz#xVpHY!; zs*F}xgvk{>eRF{u5`t+NpxFu=k9d=FqTjy}vzC+)v`VB%17REvpbv!f@!?foezYu( z>LaAaJsT$uH2dksSt>m{WSk-d-CbW*Uf7DFNJLfdQ6p4>7zP^^fEOa`W9;PLmZd=j z#{dUNCOR?c$7qa29N8ZI9pL_sK64~{YbRN;Ojio%hCiC-NzF7Zi_{&dBYA5c;AGm1 zaG)i$>@_?Y**?{y!ETU{kQAbLBnk7wX`*b|q8N1`84UDo!)Ly$lkn&DYmj{`%>rPJM@r)m@l1MMWv*dZ#yYSFzL zdbjnV{>_+PVCY{$vE1W|;W*A@$MG!Liq}%$)D_ZHG_m3^h$cTdBTW!e%jEmBsN1+N zAZ+gL+cLO1LiNHMEtL0Y8ZZh<)@L1{Xuv875kT9$#zyNnE$=T|WHw6Ep|@Uicdex= zLxCVCKoE5oB!CnJ5N}SI!><01dacuM#9OPhDMgd|m;AtEkzvAVo}VseYS2}yg%wbpf!EQ`TpbF`VU3WLbB3 z?Z#G=gpDMvX$ep;l+X7-m4XaHlAaJv)n*Kji_vvAI&|I|ITnvJz}d?NkfVsdno=s$ z<5Z}|$_-UNl~NQ~8!@+jL!G1L2@BLB9ZaNQgRO`l!Tuz~leIxz6(fB#Z;JC=wArjH zRhxkrrBmEGWjjU%waR0FBC3DY6W8>5t1V|8% zL4Z_LqLicpM5#m$nh~;>;&17ezPa!$)1UENsZlH|{)d^eh9yktzV>ISrH*Q85U!~4 zlCCwqxs#SVz>O)^`V*-sPzwM`R3sVbAc8uo5X?7n?$!0%y=ib9ZE8ZmX~F`KV2w#i zl5rbBAdEqSK%cAbwPaseeFM+gOQzYv7tS3o#3-@My^O~R!#-uCrU_X-4X< zy;6b041B9yZl2^^`Ixd?*^Tg8=xbw^2vdDDi0L}ClSwO=0gl#CcO5R=ke}WQE9-Xd zd-iqAAKE5$f=N4Z#7H|a!jCO?OE+=7Uz4~BkpsC{AcAqk4kE1rY>`okdPJkbB&)5% zvp-fb5mSqbcBV7Y;20F8X|TEc=KUA*JYk-yNR79{O#nJt;SAS#t#iE9yPwQ7lv$-E zuvC&4aO!_(y}KJvfOV4+uS60N`P%Z>WLu87;&PzP3Tu3EhqB&oW+hp z1b{W_u-&dmJ5QJ9d!(HRI+1@49H%Z8+n3y@O6V>Ah$v{D<&T2~!wWPhUfSEzjmdT+uq`OB0&K*VY2o~37K z9~Qt_8f5oUM^hnURSCAXA3@_RW?5~kC4}ZE?#hD7U_n|$B#{$=1Tir_zGY_Gg(b!Y%&*E>H>5Re5TYv!PCd zhh1WirFn}H%9&3ahI}grY%+?s2&$;9#px0nnd7K>m|>@A+02GGrT4cBC_72LhXSu} zjhiYBr7t+B)KZ35DM=&+8H@=AIG%{chBjT3=2vZ@#~!h^LQai%;Zx@c9(JW8I#i5=l&+ z`Cx6p9h*T)Qf}RSX?GQ+rgR4sF_#o&dSk+rf)W!T3{6Sf*O)dhlj>^*Gu__KH=X|g%w~Coo9=KfUZjM{m_ibb4UBdn zDHRGnr*xt<{LE6E@l3949<1(t?rFJB;UUa&hVrDF!}!gH9z6fk+@46 zZ>&Gn+&}xqrGK6Ni_qDBu9Ou7F1}1v_Z}@`DS+3$miTH<5}n`+6WlyJ!au{Ur*O$0 zEBhdNHN3BQW}E5y2}{F=wtV?o5BYiKxr!8`Jlg`}0LZyE3$-<=Vf}FwhnzP;G4oeRbxY%$x#J z(I=z4K>TSy+?zhi1#vHn_@0C=wYlkn~ht#6ML zF8b#PWO}*yCcK@{%4fxxt~lwlS4Phh-8^*oFk}s=4vF zZ?61lH@84|nn>yKpYUn_0PLPk{{S=3oskxa9~Y|<`m*R1Di#rD2V`L0k}* z?_x-}Hac658_SiS?r8r2Ouz6c)4G{35-%=K{QI;${q;hu^@Y$ADA|W*Cw16MC-T6} zw@Yg)TTAQXS#?-UzaD0tiZvI4r;&%A|0E&xI@l`aptp1fdtF{A= zn-d{1)lkQMEur#@8~Zz-5p6iBcQ=P%XVkcS_C;LexexHKFg|Iu9?1AscJ-&zWt>z) zmT|)AxT~6)QDS=rBA-wPVd3G%JNvKr54B&7Ffx3RBuTy_qx_tE^qBTnDLrju2$DK@ zGQKsmF)XIO6|)Y!O-QkCKfBve-{{Y@!3c|j) z`h2h_%w)VwtV?SyEV0_=#QU^F3wwL(#?krFfm0`<5`908s;dly2?)F%Z!}~706_|X z-na6Vl_TlpOu(|LyqSVU+v21YrUyf>$Fbs|Zj8&V&fFV6;nR)UWGEn(u9Q0NTTj8N z!2Y$c>1r9H$mm~C&e-in<_dMY2!T?h4&EAe;&SEZ{COk&#D9fHS~qWCvwZcOz=`%X z0-%4l9v>W~(;>koq;HoStv1u`TrQ=Lg~wsaDT~KH*TCuwr{=0HS>5^Y*|{Be?jLw; zQ$(J(WRZ5qk*NucfJ~Upd$6^})2J3cJ}2tpv2SvM34i|pK_)&m#t~RXstGG|enq!N@x0xD zUvo;@Z~>$QY7_h)Xn-|pAgGvw!m@iT%kmrj)V{n$i%B-uER_!Z(y|m11i!0ZpAv#w z5S%3R5JmlM<|rP?lyG?1-GOSV_d5RW@0;zfe-25)+T~yK5Wn<@ALwfr)p3+e3l{$X z@@4bzbKgz1KDKkUXh`DAm@*Vwd$jc|RBA}ORek>eAE%o(cL_3X9RC1#kN3(jX8!;z zP6^8`)&4QLU$^$d*;o_SFH@J_rob>1-*5-=>DcYRVogQCBgd3e4wL@?6g}vq0si^3 zs+N~+SN7#L!^x|o{{X$ZIP9!n?SIuH8F(;UzX}Pphd>$zIp*ogHg>QKx8o~l_PHq%!33UGI>{>@qyE~y}@CjwLghCguQg-Gw&=Bzf#)0bNi`+e#|RtRxP zNIHLLl(wSUr}#|B<1z%?FV#n@2=L0>B7(ZEl9v_{$66@xl&3SKcVrInQ*Ya^*|-Ny z!04G%Ib(|R&>2P|w>%BFQSmV_CM6@vyy z1`|6rh%-@XI_K(2mY$t3#l)kIk8y#2mMi&W_$Yc(E>5KQ`+IWDWjTGilv1PuuegUI zeM6HSUg{F&m%HVktT}aOboo!(T(QsyhDw>t3ya`OIQrp=SP90$iJh z8d3rP@b9h94N~4*kM+b1f8(k?NAIH6@=f$v{hnQMvJ6{hIMo+{;(B#2+^g;%MAt8~ofxvRCCo&TQbU8Y(p@M zh73eSNe!U@t*#EbeJ9z%lWCK5wf>l&jW_+C?FA&1+FlPPTOP;)ndQwsuPb8-HEv=c z5&<4)I`=2^gTqcgrzr-1WPHs0so{|Jj;sS0i()GQC*mT zbz9pKok{o+^IeGcecZ9X%3Impf2AMbQl$2M+8cxWmDt0J=ue^jzrL`^k$qWLewt}> z47#y5#w8#Ew{1;PA0MlX9M>oq9_Rf`bm9CI;=3*F1$$9*w`b>2HsOHp{VFr`m(^83 zWAfO`oxxXjCu=eLH)BwJ;x+ypbNSv*oC=!R{{S1|<)>!~PJ1Nn0nr67bcwz|!({&e zb|=q=3gkKy>cV!BUXK(bXat-|br-eX@^`-*JH?YGJWc-qsh@TgQ`naMxwIU5Z_$sR z?KamV>Ce>6qzarmt>iabHEN%O0pCzNe%@32QIw5~On-=LW3WB zdY;%tv^ts2g#Q4Dh=|*5N5_mSee$$_u7AA$0Lg8pll0lW3dL%)9(PmegJ<{D^XP}v zE7R|ih8W{Fbz)ea)+AaDK;nPx{#FbH5_WL^01FB-Z|R449y(QVVw`xovjp_RRXQ&~ zy>)ZtJuND--HrUxNwB|Yh3rpZpyE^7K3p->uXp%ZQG#dEgvdrC^a<*vB>w=0PocazDI&ykEGZ%o9RC1Vp|Bv^ z-v(Q1P5%Hf!nF3Wybh33$%C`@3io(;RaM!R>~IbbH`b8BTpqpRnHWa z1sulh7BLjjt1r6AAx2=Vj6gbzUxUkD(08FwRc7pM{@}6KBMpX#KiJE4og{aqBw&Ba z5OL@roxZ{-4A0(xeK+A4b5>>CVy3l{-=n6J&0*oK(%1NcLH-j4S-jiJaDQoL;zvrE zSRUcC;YAMiVY+62%LtB#P<}H^T_NZPLOOkzb7mH5mmjJfrwj zdZx|zMLuK5JvYqQjvrTZPg4aAAD2G62Gb!7R5kUrkB7ICx^j%|^vbQzs8}PXpIQMc zb#hkBeqn#_Kj8DSq+lO~cd5+JfmP;A4xhX_Q}EK;yW-esL)U{tha zkg|}ah&)SamFG91N@aqelB5zRYD^I`1`LVmky`%CWZ^*_^5n#N^=ZO-I8iRk9WCj; zZ_ju}50bHen#7^RA*h-qjzD2bYJ`%qX+6aO5fqXKzyW>{W_MYhU1;OCjFh*bNd)P{ zsU#sH2{K6oA6hJ9BFRhW{Jp^|Lc)lJU=W~GPlO1=hfP}ttGsuw{{V2vPfHI2dG&ciFc%tgO-8g5F1dX#}WRiu-NC>o~~M8+5jMy=dQaV?!8 zP8})73F|*I)@i?|zK}YP)a*Yq)a4qA31Z6BvDVitwJtx=q?PvQ@w&=m%VXdw^>%by+ z*@w0;;pzK$Y&&*zY@o2obnSExL&t}oO>Ou1bBtpg{4z2XHX&5C_=ZEQ#&YY)5#GCD zo8~COusd7?U=-fk4`&QAtHfR1Da1&{co0Nu32+0m5=ypk+fxnT7nxybc#2Tjo|4%u zlhp~)P&$>4(_*zl3!`RAh+kv0gzsh}ac8jG8{X(NwYBazL7V1{-MU#pl{R5Rjv_?H z&Z+?Aw#9^M;H*bQT^@AHN$P9x`OUc)sG3~Elq*C+ zu+-W26L&#o4cl-x79Q%{UtVEN;ybcNFeNxg1GCHCYv|#%K{4s&!io1(uvoAjr`N#B z5}LBraR6Q`32a+NB>9`Kdugrv@@>i=Hx`LIN_;0_*)g+(M&63W&EQ~J<}LvcxL5$6 z;)&bFW@8L#l9m*fMvgTCJ3EC44al(E7~1Y`EPHqD!v(4YowyCZE{>X4ZI72e`f!lN zQ2=^|5rPp&U`Q%`(4OeJgZszovDb-&q~VU=Z%Xm)4T~!G53tVF^M2G4>$mpIrJxhtziy9qXORK7q2(^eOnNz>}l;3DsL-{+dDWt!n_K5*XNkY=#Fs}*4 zAP_+uF`!06o4LF9tzWVNmde7=6^PU}PnSpUr6;PdSeduftp;1jlz0{&lJY)DO4Yz} z))HrUDdet^UbeQXuC7UHYpd#tMkSs{w%E}lNaIj|E7{j&d2eNw%VRGKD|CfA>c}oQ zK!6DVCrHK;kOD>niKAWT-mBg4yH(}-^*F2`V2}m?0kQy{og|r2B!^y_Jv4Pc)mKm_ z>E}yUh8ZyYI(i_+HA$6dFgymXz8b8xU5L@kjlFgOnJOq!5^5SY`MPC>rk(xMCfPPJ z^8Wdq*!q~voo2x=+g&umR&NR*sVQERw6>I>97o+6f)<%NRFE;tEVB1_dlOP!aVbD} z>h2a&QoX5_6rDhh7>o`EH3}`+TQK?*>c%eySjhRa8tKk6IaQ}@=|@FA5Ysa%By(dJ zND@*j6ReX_m{(IHqTPl)??=*}d6crJtY2#ErxMgDmsFjkr&5;LP~eiZ6&wMaD=qhX z>T!iS5t&;Sfr(p6)Dwm$NdS>Jm?ZTY9&0}jKU$O(a^doH?-Pi`e4jp9>0+jo57I2u zby7^Q)WYJ;9I-pb=s{L%j&muzuI<&S0f&i7h)@hVVMD@Fs6haXLF?+SfGf0&i4CP@ z@t+U`OQ{AA5($t;5JZ826NMFA{{YjB`O?hSTakK;gw2i> z<#ZvVb-KEcK_c8PGJ^^P5MY7`Anbw+5PCs^4+@d3FB#06@9mbC5U3$ZP$69;5hD$l zd2JMlkjpXIRd(zZSyhGZJ@fIk?tQ)au?gAudQ;0fzVCmY-hGv}XW)N^`hV(gMq$VB zI!s2Zs(n3qD68efG3xq=si^B-LqS!9(aSo}(!nHqp$^sCwt88i7x~)HDEV+w)l|C;-s&Wj(L7{d?G47{YpCV}W!VN{qq}4@j`k7>d9*E1 zV4<}I;*xM!5)?oiL{uHA4#SwjXQ&Rc4l~edCOtk>$`$ZWj#OdvIEH7%DKPb$%^qcK ze37(t(9}9922zQ&UP3Kxg}V+QXDGbP0k=Y%SzsweJ@QFHC&pz)GzDUDz@3fS zAzD(Be%t~^(m2OZ^A(>sN>_1tYS~YO0!ogQ#6f8)3)}ogcoKLt%F;r#B#AnRB&4XGfd|WlLF!g$ zuF5zyc5P@Ya}>BlO*}N%MjDdV)r3E0hMk@vGm&zNS$B5trwNeH^Lykn?aOJB5{KMI zhPL=hp*SF&i&9AG!j#*f1mK-Bv=!{bVvaG_6vvh^ICK71rq0;*9bJS&jZ;k}UK5Ve z{GKfwG9#q%R$=j(ytyQZwUJ$mTv%M&p3HK^H!(!b~Tl z3bJ0(06_a=Nl%F~KG;?h20Xae&X22kZz^Suqh?H@k?|D8a11XKuce``NM?-BOqC8G za}`R*Q5$Rvb#zt+;EsI_Svt2HLyibql9HhyfM84!;W+V_j74-V(be5rp-TZW2BCq1 zcBVl;X~PY%NGzL%Ytg7?*efw^xf}L7b{wjnLdSe3{J(OWK2X~>`3ou}U^;Itx-v!lv26#5 zzq635N5!ag>L8PWh{yZm?yR}EVrQ=jfsAZET^uUr{{RW>c89GU1nQTfjLy#twN#ZD zmKf$h9yseEG<8B7A9u@_%a?H0d^##$~e-XjD*)2{eaN4P{K?W2!iooludzB!%>XfwbSu$YY z0R)l{x@g;a9mRbt;+fYZ)q32elMv~~3q4HOqykAivh=XAq>iZ<-;$imZ#5MA!`;2P z7q+37<|S~V6&NIVh*a#1cE-ptIMze7262$GTq%ZBQgxH1AqV)U4Tf=%F-rUoqM1AK z3+nDC>YE$NxJN;~Hf75H0Fe2txr0GTSBy?rntT@mr&aTDEM~DqmNg|HQ|8J*8qG{H zt5($Y%8n*gB$S|S2tXu)xZ16Q?okPeg

t@H&xf*h2{LpoFC^JV}DJ5F{c&0C3ol zRW)J#SIC_m%b3nv=~qK~Tahqa`<&?hTLZxHrG`kbtUiqzXld$d1Z_2LJ6X4M^S|%@ zjQ~N&J2KA`dRE{{l7y!n5~Uywgvk=Mbe@m^#j6gjg9d0-RA zhSA80R}tSGnHEs-Np$x{?aD{A@iOkN7;qF92}-8|r3nYBL?2`t4Yk}rE(9bfK?Ecm zL=grIj7La4b*m0x%2e1ywG=XIJrzulGbO^>Bep%N$_euZpq+KsnVj3*<7sez5C%5w z+mBJKDY>@%v#V=vl@JKo17_TIQes@OnW*sp0P8(91nq`1Bu`lqF^wAgtj0U+-RyH? z`EfYAWozzA)30bjB1qYU?ewb)S3*1Bg%n5yKo|$0k+as6`A4allO|&EW0_*KEp&eC z8RJJQZ8S$y6D_PqvfL!S${M~wZRGfNjU(bb-0yF~@IaqENbIC)W~%Koo& zZaQr!2Mk#a>bm6ga zhZ9`|%Xfn<%kEaw4>r47l=rNuuq6vPErkFzWA`8^Nc%@cJNoQ=UXwRqUZ8T`TFi9x z^Uw12HMoU3;P6en0p~;WatXGA%1bmLSP*Y}aOF8sg(1Z@66$1NR!Y-}5S$E-y|{`~ zpJr}cDVv*Coh!6nl`2C?4Xi*aDc}thel&&q$QG~9Z=PzIGkn&1>$6FJ2r|hf7EPq{KS8qf9qm@F8;9m zubcAqJN&;Zx08MQE$?}Ey}mq?znHiD%kqDhI{TebsSz`_c25mkCV*ed7yQ5T{{Wd9 zd+jr&bEl(D*yE>cb=UvY8#5oK?1z{-c~L$Yk!Y*)1vNC~FzD+dq=ven+2x1%jL9Ta z{$^rS^ zepahYla9n&GUS$?n9GN2wS+YkWYWnz0A4w5vO)SeEVe6<8@;@%$*vR>uJyGTQ96Kd zYzu{AlaC#kf-y8?&EI-Ezg#{eucUFSDfQKW^iS8np~@bzdVZ_^vC-jpo)*IyqJ+ta zVEA;E3UO7bry-|DqfdHh6oyg@3$MI#QvU!hVblw|8B$VVNE6}IC&Zn&ZNq_)BN~*l zEWt%Vmxuw)irFL_G2l+jYNmZ?C_CWlQ^D>Jf>a9&@rW=&Hi$ z$KeT_`iJTMr>l8)I?z3Nr(8yh4f4;-v_>+*28E9Q0GTq{D`~dH$TuKL&F@odC%}9r z4kC8Mj*-WwqN0a)WyX*c6bT|zf#{esu<+>Vs+6yuqX%m0dbRSaX_?}kHwPDtl#(FH zp(?P(SjEWJ~_`LZQR z6&UqYGA->KX=pbp>LVkV>6|H7?l_%90%0I+(wNl;tYD$gs+Vn={H?HP3`o?o)_&RQ z=#Gl1{CA?XShfpYj?keyQ0_*sQwjHN1+|cY-s3~9$YM9&CD&ra9g3&E!rh*7N(2Fok*SgZ&PIaY^u+OS_gA z7HL~98A?xs%c!0avxwMsQBca5yv&U~UzMvCWmD`H7P-FLok;q5E?u#}PR@O5L_wiX z2*ooVS;uH|c3FCyD;2`0imr~bhEkK$)WieBEOIYmJCZaa;M`nrBy_A4D1r_IC}2eX zJ2-=g;YKaErc@S#1Y!u_dG^-KJqhc-L%$hbgj9NL^#w~$hxKy|fv1rniZondBC|Fr zgrESd$hy^1A-dSh4wnKO&a&6?l?%I54j}%_kK+bqrHll`=`-U40WvCCZPxSl^sW-( zeV%c}2Z;U?RCU+Rgmr_`2dG*sM>Y8m1_v*hgJN|N6^6DaPcP+aIOq^l4mYj7$@1$qZ6$nWL6A0_NdK)vs&J2}mOjfPD`*)Td*3 zFPkceAi)zj^o}rSWx#7_C#SBKqCrbKQasQkgnP!;h_s2TN*{0wpf|a`yiTOeAE93g z4A%p#n*lkY5JZ@TN0uBZ-6|&Kj58_su5NB@HQldnCGMonFYh2tA#k&e($>#Q?@tRL zX;hVHnN)_?c8a81ZN1&(Xgl+86I4pcrQRWnVYuE9QVr3pu?CVdNOne28aaqIv|!wW zukqsKVOCm#$E6WU9O({6>n#>ZineSPN!@F(s+4ApqiDkzWr^*3F%4m|}Ald2g~h8l>g!?nT3jm1QxcQ3bdJ8U!=zwn!u31Teoo8T zt1k63q_)hRCh9Fj62cUfG?ToWip=Db4P__1sd8^-iS7vG#MPQE?hxZgQ)^H&vN(`^ zeMZAj_15L7S(7f?jaKS#DNtj(jC7tQ3L^uweWwvbyVl20GlosTs&g(+#Znr~)tIU2 zF!M}2#i@dXGDyUyG)gWELR@ zfWxd0pI5C1Il7i5!>Y4BC3@wF832u2^x=?5vb@V;OG*2nU)$Q;@|UL{T6syFcJT9` z*0*8wkJCxIG3i^T{Vc1D$5n-36b7kwg(9M*K5A{i0b(9P55#dJQk0IElRbF+=wcD1 z$3`B^J~Ku;8msv{4`?^@Syx}Yk?`Vxai@r&2N|m}dC7YNt&fM&K0lv_7pDqj&|`^J zikgoqOERN-z@HKAZ(!}k$yGHKHl6&cPndJNcqE&FcL%!K!BmTB$4csvMtZ+8QS@`5 z)%o`pWsW?zg4g1*l7D_E9(DWQZ`Z+dP}%`J1pMebbnbwqbPCYp9?QK#%Nd6Y>(5Wo zPIJKo_3anD1~)@g=Bm30mi7g`=V(b6R`+|bup#$5)S2V%Jv9xs(wjQCjC{vO;nzpo z)E8Yb8c$2Pgk{N7D@C8^n+>X^#UprRpmd}8sSQM7L5{6Z2$^hE)uT5(_yuzGGK7R` zSS}?cD8^2qAo*=QRJ-|7ZtfDNVJdAUX;QdhApRY7YCnL#p+1^*XYhx{a#vh1q{Ofe zt=8A#64KNv7LE`_B^=O;ZH`qD2?0^|{o$`N-Kz$Zmo&* z;W5`-!QTAI{L^@@U18FZW*BLL2lppXf~N=@2vXcqTu#M_NvhTAhD7xh=%dvZ6@|{y z*Y$Iw7=2Ij+PPzvLDY_xCY3mCOZTY8FbK8oTvIB@fsH669?Q>Uju#s`meN7O6W+8A z*x9WE0y-1NKqOFDw%-dyHt-Fl)kBGrugYF&!9sEFAN!K7vM^B~9ba1&Im^~Aef0V2 zPtc8gGv^$wmUC`(!K)e|?~T#XOF>UATArmpM6*+&+U=Ci)~iN z?rp~rgdIs!Kqg7>!BV10iBe2rL~Xd4`ujOu!#)kC{o1N2k>h1HCf5SYISuJ9 z0!|7^AcKLBV2{J9y0F#K5>ilgG~fzCfsj(6DNrK<4E*Z0KN60=dgJtk(M&JZZ>8ML zf??QJ9aRM`W5O|vrc)gR868_e5gz{lI@IT{9$L>>g=w44P)%DqnOW;N4%>x@ZLgHY7qlz4o!Rd80*L-MaZXOhsl z^9g0DQM5ZLyQl+g!Q@?-wQMf!k^5BzsbNXbuMkQ#1qcEP4kQDBGmKQLk}XQLy>)49 zsSKk+j1Yw_z=MG&6{b>^9fpFu#p+Ad)?&a@D&l#k4yeP~3W!$}iB?-&pE07=O9Sqg zK0UkgMrPK@vp=^V<|_|xzimV5*3r}hM4p&CIw`)Vs6BMdc-=O7>J1K6%owZ^K=D;q zy&X+Nohn31G!pV9TjbG-|>+D5zc<5m6j) z!lE{cY2{yaOgm6)Sv9Tlx@9oSuP38RNRS6iqF@M!*|Q8OQ<=rlgQ*kzQbZHg8xJD0 z(*7%6z94BcRwdNxSIn?etv(T3Nm+#aodgp~9})S=U*+%SJwhrVksTf|rC72tUL;=n zUffA>%asv;meLRTqev674hM$JDLKtwQbnNpEN<=h(~6O_ zaR<+6=;2k>GMlf(B{fY+)lsdQ!vsX;+%GF2dIQ5v-aB!MPQ-ZW=*y?LV=P~Fc06rCv=aWIgrIN$*!L~P+xaNPas z8w#B<93MARVf9NB$L2*?H?&gwtrM4k?v6k#!^ci3wR+ycMQtU(V2mVT#vy+kD24sv z%`QYO@_*9*0E1KTo~int!Xqn!=SX9X$aYkz77ROX*-xi?FOM$e)w=%VyEE25(bElQ zS(<*={t^EBPm9*?SH!!HqP5U%+$!a}4)#;>`r7&*9}X}st~9m|w3F z`8@vsi%k_hW%Xx>$QrY$^|Lasm$cMWDO49>8N6FYwmvr}+rb)lk!_3=@c#gGC)e+q zL~k#r`?9?xe5uL~uX?bD3xfxw>Ru?6RAX#(>m_fO5&K(01qz1uD{rSxY0dAraUlwJ z;DNAyVNo0)YxdJAcIhOjIA@8BeQ=@s)1H0xADA#7p02lT zNHoTkBK;xSZ6w?8V{*PchquFd9&*tZ=v#ok`z>PXlmbfiD^S#A6sJiC2sM#Cn0M&S zP1B1pZEtY+1Z`3qAv$D0P%6}uz@$brRBLlzUGV8)j|9(H%rMJGNbed=h;2e)M3UgX zq&nCShMIC!v)(sbK~A?40+a+j0Dw-I0D&4~%Z)|36mo<74Py4B~p-Zsurt1xOY@O|Sj05hE`S@1fY|wBE z(lA>3{3K!UthM>0)U>M5&z`aQqkHckF`up@=6rzgeVX} zc}8b!jx*OzcX#_j+&+r@X&;9{*4!b!ZwALPDmMptFbQA_yWAFJl}_W^z>qb+30TbS z?Qm@A=!KAGF*pv2Fw>f^_?`F1#)M2eJNmK1;1rmCd(F_K?Cy4ARp}XRsvU|gU<~Xu zB#YQw>Bav5+9V_p9D&4ZIL}TSD24smxW8C&>wfWgLe|n0p%{-6q~XJ(g)~*c>JqY! zJU151S&F6#IGDvtC1mdsAsQ@k$y8AlhMEC?XKoO$I<<8PK`AL1CP{?!z|)6ZP^#Y} z%-C?a+8j#Nij;s7we%G!Bo!WwM4C%UU)B6kisBiEAFkK{hs>*~EVcj}ZmBlX<4)sF z+*=&vC$wKTybEWMWNKuC50F5QmbqN|&kPH|QLer@*c){UWW!b)6eP?N$ zEztRNSScxPbr%rnCJ64oWT1okPDjl=jE$g^SQpzrfj3LzlAL+Jq)->rqSh1&6lwuNy{q^5I z;qhfA{yGnhwB=59V8Fw>6NU+ndgxfkW4q^lv8#i}7nQT86Y27&G0;A=R^F(kTP4o2 zO3cmd?xb7c^>HEIT)hT79)Jk<(c(J+-z$$1X@BQFagS{|#py4swX!iZlHG_5S&1jz zwat_IKQ1L!`ep5nqn}z6v-H)y&qluOGyNyew7{hz`Yh`WQfw4ps*4@niME=Q?lmWc z2Y+l(XIDPj5TB*Z<3Dq@-|C7#=za9!o`d?&AX3z5QH9j5;d>GWs;0|*IM@3lW#V!8 ze9qcX-_pK%tQB!)Bm4Dv$Jr<GuIs&*90`p}D3sY9DZM=bhVbJ>sQ>t?eD{^zoneRI}g})rJ$%v)xOP z^rHDbEBk2bW$$+h{VTToJ@eEOMkXK#m8j)!h1R%yVR--s1AzmTf_4ff5$ljjJLnz9G` zUmx`1lr%nxaW;)jPGg`u6&=hT;Z|) z++gE?mujHCuj=}e3 zKYo1Faf56=E}EXcjB;!X=2qs)WLVF>6ha2`sJ*XY#?JI+3j1u`{{Tql&t+WpE4geC z9M4jEgO+Lk07PP)Xnhvs3Y7vZR``;x+FkaG&{rfBj9# z`2PB@_6M_;#yPWx4i`4R4L-hAnSB}bcmie5l-Ms{|UvzK%LCuqx*>F7EzOCvgOUVkxbD;{F_3 zjN?6b6xch}C|CG(p}U=xqem6)Yx=#@(a zhPj5lfIAl89{$7MjVaycSn%2(UhI77goa1JanW4@;c|q_WY`;x3nD z43Sg;?&@@DZ*OTmxNg<9^DpjcBh77msS>xdvGcWu2G6u!Veb9(nVZtrN8UzQaO^^u^Iw&i?@A)zT>g zLoR^ZKuDL}Ht_F%4n6$8c$NPE8XxDQ@S@?qy^u6d`6b%F+}@8*5crCFkJD#E;?`Ua zx!ftb8Po%Rvtnv2NgcdT5vwZRJ(`*y=O^TvaXp~+MuR`g?p5Z~$J_g1PZXU1=pv_| zK3c4hjk|ogqi{yL+|TZkdt6(-x*i~NCf+T9*1ywn^i3;0sP<671+1mje~iNL{{T$+ zr^MntY(hT^{p~nUbT9HVU!()McFCvAkzbqvOQt+|2bu{wi*N#&g{tIzAs# zTa?HFyr0`=YwrD_KGPJiizRec81}YJD53)~lt-IdbSe?Yp z)%RZ}dV`;h79Xl?k6_7Dv;H?|K1ZGu;Fumrmn&kF@MWqRItXS-YAIH!Emcqzj6y{e z_H>N{Fe2efhS#tS-fo@smG!l{?zOn~q@`gChLS$xI9+=Bv+Th~$9;!DLcVIKNx!RW28^d9Y#yU-pMP>qK4Eg@L{^e4w}rK?09mEd!*z)A z^fuD^3;jH^y_sC7f5pfBPyR}tSJp0^8p@KN_g04vraFDpZ>wKzNJ&i&hRdi{bvZIyiW$hwC!*8BSh3ZU+G$@tu^xU60qyLku4e z49d(bX9Hsm2?2m5PMT;vr-sdTT$JJYwe9}^ji>xCZ6f~wq0!CKAvO&4OX@%S%5mdK z#jdY-gtB4SYP>*)AtrFP?#>LLTK4##X9Od&CV%E--}I;-IwN!IJ3U^@3r|(JeUOn; zDY4u}mE|o>hoFJI_4zq==m9rlHPK1$-`T`2c57}VDff?DBvT*sIlILWEUgEU-uV%a zTvXgE8pLosLRqltOeU6Ui5cZE;V699VWDPeNddpbsRQZe-0a@c-~_n+!hjGZV*%BL z2GjLxpCG8UXJ*-2wJe~#3f283!iJ@Pd}Nw>JwVJ8Q!dxT;@k;U7%V-T-C(DC7XJWO zQcrz2$~!L0fyLW{{^$qFlD+k9yz9j+TPN1xTMzqasISx<;RFIUsiwO<$^KOUE>sVA z`}zxMZ9X?Vxa_|xD*K=R08}5~(NX%Y-lLA2U64EvVgCT3tC{K^YN4eONhTgj5PjSx z64trYHsfoHSa!agcy?QsD-yep^-&-1v{vWUHupI`HUT_)w>};0R0+C)omwPBtEW{| zU>Rs>kraV&J@9uD4YWG_TvVRS@}wMl<2^2)l0_6N>VJHX`tuXS_Zxk#MRJp<8IVTb zHBy4>?y}L-DvRv|3nt~#`ZlJ*!rWNjX8B2v3%}~B$K6T4=x2A+g~KEMeaFpauqRTp zMGI}3v6o;Z$h7q2oe4`Ri%rX-hOs|T;=|d#PDGa0f8AI3(QBVlo9ONa?Xl%<*XvT7 zsad(|hnMz-JkGl zn{_ijNUTORR~$h$`H0lTPUX=Vyploi78=`LINxU(8QX6^?v8(jMQ(QYz3y$jjfVzW z8#+8R*HND{<$X*ZeqpUPi~N{)RFx#g!Bt}f`?j(60#6nVz{wdN8&ve-rw%jLx-A{I zZ)%VHv>X`D2xxWx0LIT8eCdKr`a8Bv_px9V=1+ms4Ns&uCb>3h&NY)DtHyB@MHdMLQ*BEP!_ATG%mBD$ z3KZB|i^k<;BOl8(x1js+qSf}vy$O(v%I6r8N+LvXg}6k$NmP7!igQ; zyxH*0aMSNbY>irKM$dZtS3wduw$7TZZEU+QT5D4}`g zVBwQZpvxp1s1IA_DK7$BlCC?+pEcbhx=g-ejk1@$B?yf~fm6p?@j$PblF zyR_2Kjby0LNm1j0+xx{rizs2Zghsm*q(NYP+DtpkQpEe)H#Ny!EX{uU4iprVu>0z0 z36UqH@@Om$0w|Ey=!|73y1T?KsdW z!QZ|U1mm$p4V!V;B>X80ov1MJUZ#SUk~PBxyvj<2l0TRt{#cs9n690^%XT*63nVTM zxgkgRhYqpV@Tc<_BxnP`HlZz?LBb zSPk66{qe~hx^*{w%=gVHDRy8bXdtYs5TfE6#iR^W2?r7dW*29Bz|m<|h;mC$B$ONh zONr2cFeIUF6RFG+g`^TdGDmC!(jH~%XIV045rAQhiQ##V5TZD(63mhWp{S=b;&6#B z19=d!D@q(^Qp@|@(ijdGpPXubHk!>;gQ6yr?sV2%hlcxvSWvXmhZGnJ70zHBW zKC(|;GKI^X=Sru@6Y>?JA5U^NW9U~|x|>OvA$V#qO4_WwBq*WeX(gyLy6zX+Ry0D^ zzk4^2FcY-PvbI>u@CzzZ)(QJVaFIMbN-{P`6bG_Fvw8I^f$s3eO1wuO@ndIATu-Hp zZnM)bq3)yly`}OSGH01%$oW+zI{`>Xn~Bva{ogIv62nWaf$-p?vfCFdRBj4zS%El6 z+Hn}f=}%09=SOymN>ZgO5=N23%O5#Dlo#|1((kJ5qtTp8)NXF*lzG~DF!Ni7!%dqS zlDuJIo-r&K90+P&oH-KBD;>KsH9eBz2P>B5{>+WjkwI5J=RhRM;V1o{9%ULxKQ|l+$LDe51 zb=5Xzxq8iB(CH0eg3T~8jD3c5~K++Ga!ONC#2EI^l5~D zFzRerb`w)y6#3gNVvs~=c7t19?g^!qDHq6=DA}Fl-T*|qTw9Tmam%a4scIyyRl^l1 zl6r)lqh(|kMiP_-kK;;-Jtkz~u)!uU<40rC-YK5&thrB|x|N1LVZ)_{LrGtPA33C} z!vj)(F{z+`(mW7CjTIn=a;le@N4>>{Hdf`MsEJA05MYcarw#^>S$W403W`Y^NRUiO z*~6#H>?5rl0D*g)u!x5|t!;a#6%zvQz=w^q|#NoBcFKf+jbrNdvh9}jG55nl9@pX<0&O7j*wEJf!P#g zm*k+NBt#u(AZ-1jBp)qEk2*>|Jzf5LFxhLA%TK4X9E5BmFS;R-xT<>8$+~^#`8%L0$w)m$MEp zhs5_``U5$dn4%@XXNlIwLtsyhxrv$mnXe9mA1KbLh5l$=76f&ziyLXcH~;~Z)a?K>b&@#HrQs{)jFi6>xFXISdQ0w)Lt zWNoTx^$(hTO65%7k9uP3o^Hl5kLor%iO@}k*W%Sxw2)#Hbq`5bEi_dUG;y=K5M4kn zEpkUb%W@`cA88qli%p>1Hrn+i2}+iN0)SKj(>U=p^HTEOWT}Oyz%W5FBy2Ee&(@ER zr>>~}5xDnAa7-`MS4`^gT=9gVr^KtNu{?HsKNnC*hPFCtI<#sklD_Qm0AgYmNVaZh z#wc&@N!l2{F7DOspXF9H2CiBmY^d-`+er=}?M|Q;lYuJ0(Dx^QCQ=pr$+xv(r?@GD z(o__1J2pqH1pfetUrv1;P+)yB>rbJ$r=!a`vkb(j@mea0>g8%|a|*60P@q>yB=ID) zb5lyH(l9%TTWX+r*=^49t+(v=rEIS4rvjT>2~t~ID@f5ApvqJn3Xm}ZCy5?%)uL3F zECRzyDg(TNxe@n96N!kzI_R)^P4yp$`dsS*^(in|Gd>qvhvIlHF@n|9&rb#=hhkK( zOH)fVMJp`P1GqZ8Y#Ch?gQq0j`P`d+(6YyJyP~9_-5xZMR+S+^VM9*kU^R* z$#biX-n(x4)P%ayr6ho0@GxW^uy7*-OK(x$w)%tWBO&13A&&vTvQ|gSb=7#K76X@Q zC5{%Zs*XB&tLtiOC#bBfsxU;6hn8X$K?tZA-Z$*`vJ9iLfo=KlcZGY31x3$(kp0@YL1G6)hI&rJ0sA zMN-UJjg?hEyAn;TH9j24LUbS~D-1C_2T447$Fie&nz70s!n4-=l$4mCRkHmSK%|x= z^5xFij|#wEG#_OR9w$_liQnw`I(s>a*|%?-qmrnh+`*No7$|05G7dl7!o~+|)Sr~@ zE^nR*wX}J`z=Wzju^%cnzM}Cwr_?_J9d;Xu=4vx5(bUvdVslrn z7llhwsWnC)g~uR@D-V+aCGaZ}#xNnb{z=($d-!sXA1?>=0Z~8#PP- zd|Fa9V}*Awu&vL(+}xP8el)GuONnl0yGcq!97qL3Y9L@RlQIEDmYx`@0NQ4iwkcuo z)b=9wUczsIMKG2^w3+`Qhrq*_>jw>#F?q@5sy?K+MEI`)Z) ztXAzKEx5mJkIOWtG_6HibofS+1j!po;CN$Kot{4zzd_kIGt%W6-k_!@gF}WbWj%fg zL0evt)-_~{H4KW8BO@5LOsv))X+Z|S;lKL}=C}D{4J$)e47l%wYVh}KP*O@%kZ}r= zhR&jE8Lc-vG`S0P7UoK{khLWy0z@lnhS^MQGy-HV#~aelX7w3eknvi_q{;P?RZk9e z#MXKQjyI)OiiTV!Dr$*klvUjYLpmXhhh+@6G8SXlox!(N;B`v9C^Cl1LvFfKLY7uQ z(ii+mfDafZXx8U(^9x%r?vW|eEhZGH)e;t^C-_JtX)t60c2VZQeQ$a;%z3Xb^p_^} zBQE3E#%hwUm_GWusr3Kb3H{4 zU!jc>zX5y>hY*ImM9x*BuBj$^5W#?x$ql<|oel00%5$_?S}NV_xi>C&ySLm+rA-6; zJ>HUqr6gby6?rXlY9|TS6H5hB#ELNDHl$TZTCv>*jr;Txbo16t+is-1kkAf#C~)0aCUV zL03%C?W0d-ZU(JU-YPZ-2?-oZzR}Pm_>L8-XX4%0kHgc{hH9tkPo`mv$)9GO6C1=o zl*fnRIGg}5`I%y#Uzs(?zz;jgK_Xww8-P6PCuTddn{J({v&$LQFR$XNmf6T1gcLGXbSZrD_Gvok)(rDIt zBkL`1r(agNKR-N+ONZ3er3G**RVAda2A*FqgV+)n9S9>{+FK#rVdju+yM_*Lhu&7S({>f^exKwlv0I1Xd4DG0jZA7!^7?rsXyU1zEM7yt zwsse38M~Kf`O5D@H zCu^1`QOn#Zt5y|e&ImK!Ekp%6qA@&36R<@?7QOCec%07WOMs5;q$NcyqV2p1$+#o0kN zcCEJZ!O{wUW|O7?(mw4VM-i|eI-2wKF6!yW8f>I2C1YBE#X?MJ)JU0(Wc5WjdVpT9 zV|4f@sr*MbVbqbqQA-tH^?M7Fq<<^K*<+Szr^O_ZrTJznsf+}%_iio1jkAChyfblmmaKPx1`l`=lxmbLgs&A6Mw}IZjk7|92SswWV|o7o ztyzyTsG1^wQb#~D5**y zgNlq#l62uvJu+nelw^$Mow`MqFf1yY5zBRuViYded~aMRaTP9+%T+9GF=%I3jdrz_ zNY?xWxqowaZqu)+Qgxw3m`Ph^34mi1!PqgHI?VFxdmFVSgrp@&L#TnUEEy7U!C^yb z;Z)Q3k95+LDEf!Taf~uWo{u%b4SF(r$SUIjDiI{Lnn2(d+E0B=`Ip;;dHKA&GGbaJ z05<7Sl*r-6I%^Sk>cjHaVezr#$;0@Q;Zza zB{N6~M32jTKS&LU9`L@J@!bCaC1U+ZeZ+#M&I(Z@NZL$~=#e6D>7t$5&Y!W@ZrYR* z=*1}j>Q=xY^o%gZhq%2Q&(+Sj<*t?dy#_$3%#<_B1No0t6je}1=J`?t3$|BLcUzL0 zk`HbcZvK9yw6Yvi`WF(Rrc!4Sw3LnpG3u!Uc=t#$rj%Pt8qj4+JjmKTlm%qm?}_9rUOd5-s->iw7mh&C%Ik8ca3SMw zf49-!#POWNE>2>Chd@v=F#!BV6xLUpy_31$TP;Xd22w~kW5aK*6>r(6@jt{m_vyY) zj&-Xo3fw}h2BXGk%F}{XNCIkkuNx!&^F()i3FI|(kvh_XP_)Bp1Wc6xHjfV-xR5%` zR%>Nlt&66X-TOqBP*7CdB_!}#lB_V|6Fow3r%VIZjb})@X@z6?HVO)Mz~+ckW}2#` zU-#(I?3PL#K1iObxWfm!i7KoLefA{S2-43Zad#?5i&-UMl%iCW&IQMCLtycOrF03# zr3}-2ZOxirY@oKCEt`d}N>sS7ilr5!5aL_;3w79)@KMKd*IjftF2FQnnuIs z2o|{_AQLSdrDS#h9i*KGf)UIgb9?MsQWg<>+LRk|0zhy{&`8yjg$XeXn z=Zk43#b`pxB&>ug0+j?$fq1Szgw7F0GyR!*S@NIe3;Bgd^%La3t{>JPA^!lEe4os3 z-}Za?f1|bUzh2ynzqOZ>{L4uE*1yX4GCSRRA~y8+r(|JBKayGZf02XS&ws1y zlWc{gCBG8WDmq|5;m5?1HW7+Uj72wU@XSeC1VM$NTSRdkUg@C*mGMmNlBw|=^!RY| zHZ0FiGc_aWsg0yxG9Bu7GD-u1ZO2ecjlnVTqbHHvufsH2a@>BSzYgxK;$EUXDDIyw z;;9Q}47EKwHXm6|g8u+8k|F&SN?iFh09;>dhD(7mZqD^RleqxlvmPV*CU%aEg(gTi zkfVm*4vj1JP6YJzAB_qgs{J{1{{Yq=OThhHdI*xE6w9=@^ccQy>G)(?s(RXJT4~!4 zrXJ-zWOG_sDHND$g88)C-A+h6n|#qKxv>WnkWsNnCuxJgiP`DI34Nlo}T&L?V7U<3kUHtwW7OpzE z3=wQ;Wtoww=p#|RSiM})L7~)dAl!0adp1%m^}q{PfjHqiC;cp+I>+Yn&@Rgt20UTkhtXk0)@=-@-uO$BRgC;>4iA1rp74*p@=l>`-i#x`Il z(_o>;uil>Pu?4|%ZC!mnGI1mF^(lmtEc2{T@06e_5o$_+?-YJ_4(_uX4MD1c!2Mmd7xQq*M(K_Gc|qN|d! zY`?f!PiYhm{s#TWCuJ1AfL0`6dPk>M#8fI;ERzTE_3NPrJy2lTy9lJklL4v2^E^PM zZ1i$NEgfL)wL&G@@J`44qS&i_pcLE^Yh*oc;)0fyG+>|*LeO}mor+KNb`h}625s%` zT6MzW!rM{Qfe^G#)JVZe;t7H#F%%tB zB_M(nAf)Ug&!?|wIEbSrZwo66OoA~4a6gAg*hOs_>D$y-K>q+4E{j(57p?K(xHna( zX#tiK7nc?+iFRy941sO6@9)&pDcp`c=)K#4i&^gPzq_v{=Fo&JeXD~D1O07ecteC? zsDKtHjEb4zAbdvr^@JPY;3_^2v^}j;(=; zYT8I70qLqNEi-v`Ag$I!JCgQmOIy92v6&#cN|Lo0TW1i39x0qcNyDqkCO<8^YUY?o zQ*cai9TWUR<3|If{al08USGuOFpM#`uW38kWK4L7hC=}B)s0Glw5~AMeTU);+ za-BVOCD~nz@Jd7waT7asQJuzRp9;zJ_(N1g=>oJdY&JWh{TnD^G*jJvB$e%>h!inc zgvA$}&xKQAO;*q&Iu?*1OQ2H98AEQq;xDTU0u8KAoIMZbJ(a;OXWAbF>@Wopb}6738WgpvO1#qX5S!+ z09WRXtKp5Qv6$#ZWOY$d*^Dz7j;=pPF4KEA23azm%TeC#Y_1|=7ZW4QZ95N`p+%1I z8!LazcV$hN3O?WnFb>Znj|uCdF`PYUQs!B(I$T#Qy;cW-{{W<|EVaP6tPIi`*d;_B zQ#HVJ`z)YePzWKpw>Jl%?CR;DGyBpUT7PGPaX8{k?b+8xr#gNhxpSs7$&@Pc+;tVP z(WK2a1}JBwsE)dwDiN6_i9b&jz+?Na2nB%Td6%}U=EI2)3Y461Af-horwlOa=%W?y zVoCnzk5Z&#>9&U)x$3u~Id|0;Ogev@a^-X7yjK&;74`E(#-^fJD_$9upo9fk)=4ad zREuqJ6q{T#mffo}X-?_V61AX-1pduhRfZe{j*vz(LTe4-L-!4|5J6Ia1fD1D*fvaK z!)#Xn0QiEN{u$1gqL=UTi?5wspiFDI=il5if6RHod-&znf0l zbeaOOil>yfmI?7vu`fN{vG>|h4ddDI%dw1Tw+jwYBVNGGC${{Y4NsspBegfl%38z#x~RdyMd;azt$ zQqAX7gag?GBop8d2Ny~KwGJi#_T%mp0l!y*I%PR$;|6W+hXDP|&24!7dR694jq6 zSA-{=Dyk$Ziskz)ij^RQw%Kxx!b3m+X8|%)uMQrk8cwUkC51ZqQ3;7SKtd%(ddLtf z=%ML5q4*D?{{Tt-Jm~%2BQ;SWc9L2-eatk_QyT>f#PNCb=lEa(2HxeBeuYi>2k41`Iyui781t5aLKqld)-$ zw9pm!pZW^_0BX*QMLtTdn=ExFBvcG{CFVMIxx;ZvVdgIF*FP^%2bVG%t06ZBw*pSJ z{L~~RP_&sr*k@!M45Z;WZ2?%sQv0B-(sbSTWyI+ydATJHGl^CQ6sc$N|N5N{bTI`{XVUhgL@~o|oV-v+YM(~m4Lq&_!Q#6p3))Y3} z$q+mv-P@68czfiKm1=0ofYX|RAb$#cNFa;=h?oS_vDyw?tk)@Rb_z?XPK$v6Yq_@w zDdCEWP_Tcc#wQB8Pg50`*Wtz2D!)}&3{sAS^+OP*{{T4@ajxTlV^S1?lQq)By`!w! zwAhNSjN4|hB%U2_UQ%sl^^q_~dX&VdU^OOV5hD$!36e<#y^n9FcvF(ysCQ)~*{yq1 zGE~ZsK-!t;AV5wcm#&{n8DsGZ^#1^W<(#vf+XBiMh9^yr$yo=vGvFW2Gbw?;tltqN6*@F>12XwxGf3kzL{$eyg)d0*qC1V1YqAlx6(?+}0k+`R zusn%(>vKPmTB7dBN^uE4wAKMBP5>xr3BVi-$>JbkLL8SVw9Fpvo+?hE;VB~(e?-VT zMkA(+UJv+Z`g6wA;xrhBKQKEsJ55ed0(M@>5Fn?A=YC>`^9MkWfEfPzmHz;+b^zk1 zJybsm6goZlQTl$zdRK+w{a0+oN15w|U(Zrf;t@v_7M?_=u@EsVUZz?}>c zlxGq$($2zN&J|TrZZ1jDNavWhO~SOOE66G~3^sys<3QW3+fyS`ZzufZbom(gQwC}L zFMU#aW6FI-%Xp1m3z~6Udj_FOL4>trN93TJ=BwwGrKh|`D8|yAo7yeQ=G(IC*Nirl z%2^A2U=pPmY!DJOfOO6!L`MnWF5TN3n{2-PwCjEA$!6WT8d3|6!BW&rgpnc=6+28u zBx;M%XR7=Y2wdGs(=2lk!m7kGQ?f@4{{ZOhyXn|R=K0IKFf8PDH!E#9B&Tq5Tjmh= za^MS2pi(g*LS&>#7;FR&X{ftCzP;U?#pbOUMbixs+6tuVD8WjUC>YhK2*80f59bM| z$yka-oHB+ZhrKvHY*jRsaE~)}*+F1I0j>bPplEzJ3VU;J?UHr(i0fNKd*h>x3Nr52 zY*-`thDa0#{A%s=aohVusCrCP>=&#Z6E7Tio&a$Mnnf}bQBes{ruzcM%Hdf1r%eDB zw;al>oXderty|oJWOs^n3mqa`aRLt9K{LcuoBqnXk(rGzS>`q>Kg83GTmXEP1_uG8 zbU~r|hpB#*YNaq@c^b3@2+|rXYN_K=7VqXpRo~vzcfDm700M8!lCa*5-en~>JG|L3 z8k@bio~R2^0uISko--6vYnbl7V6>JumFsX-if?QZ*olbNfHsakqJ$Z-4@LRUFF?5{ zz7ts!L*}&Ab5tyg=BS=BR)5ftm$6hVN4h{QaK+~HZc2($a+|h5)Kp}zRHhIlz6>RB zqCl7g4Y64wt<*+wX8!>4eB ?am!I-vee0nQkq;CPv+vSQq_!zVUiT`p3SE4Z>7a8bFI*L5TJys0F6z$ zoI-?RK#T$L6QuF3W1h-;aIuw?+&bD?aYapBTD%m!1SGbW)Ux5!LXwoHP>%@VOj#e& zN1%)=)kZ(j8myO=Gfq^&CB*ZF6_3G;dDPX|MO7}?a{I{@W!h>QfW;SZV4HNlrd`WX zy0@rwHoJANNKi;|I+CJsgR2}tnUsW(Od8%%XWC7*xPLK5V9`kYvV!fLPNzb~htmka zDY(_)9xZs3#1U^+o|`%s(7v}WP0HCv4~GY-qN&Gx`bv$dRfbp6-jfUYiiuuWC-3IW zqsxgDyoT1ib-XtDC5~lm`;7&%mTnf~2wI@1qeZid(o{6I{wgD2#t0x+M>`q5&Ud#b zy9Fvm*-}{VT|h_*X;FC7YgUyZZ`+^Q545N#5|Sh(G6zRGA48PssOs|FEp90yq|?hg zN;W%>G2&E;Zz*9>V1aM$joPs`>4xR@MU-3R7K+R)(Btc63v{~NEV!{IK+_R0FcL8! z5^E4Q%e4H>yyop0UGuHmA@!k@wDDR35~vzfN{OBzD5hsgA`MgTsv2x^Ua@sQ4aoS# zb`1ty#V|}C1i~<~=@gX}LMWKLq>_N|Hy8KZf_rlixBGK4TTAQJvu@LAW4cOGlt?Pj z3W?hU8N-RF@BNiGq32s=8I9a2P+|3^HVgnDVoZDL&YPqQ(JqwdPN!$c{L0$M#!Jf7 zbrZbMwS8O(Rg7Z@1dNkOg-{K!y~tX+g}4l(n8cmju*|MoVGK3`Vb@4R9V6^SkLjyu z;*p4~o4Vf|`qfIC>#4*K+pOWRpSy2C+kuL&49Q<#heR<}ud7(&kxMGpOk2w<<+k?S zsY~A7g^9N^YcJhgrbeqvawK3{LEE>55VgJ8!j7fh-5!~^bm77WY8|$4hJQFc$7{{VM){3>?BaZ1{J zRw@|r8KPaPJik6|yIGIAKzo~!dv*uH+*o&CDhK`}w*LT7Yy2IwiOk;hcpHb$`?J5{ z(4k2ke#M4rx#Csx2qJgfRD17o8&SH}()TtTzxHb_2mU0t{{T>H{2EMeuFeJb{{YpU z{{Rk^7%Z5LOa-N=l(bvf51ttcTwX)CouCgAE%b3~c@2wyZMC@aVXyEhlJn}sy6N+E z!~TlBUX?VsTjI+wl~y)&4H7vD1(rDbTqAS*JffCb41QEp<(mTeYY zR)k1Mj{;;8p@@ODBzaU8@)qU0$}3caf(cs8D5zpQTTVT6LUB3(b97j2cLJ?hM*je` zZp^K4NZWs5;2%JMAY;@&3WJJD+yIl0NhjiHQOjL9rp&o6EZDVkt!)z3M3IJHap~A@ zRlcAU0Dv{|;nOUo#D#GjAaJ2YzFdojgM^t9BcPActV_|hR>Qi7)12v+@h5uv6J7EY za#gUJNTZsCJmpyk+yhACKt|gOX~K8Z8gdbUpKVC_4U>0GI+8UfR*|b53Pk(Qr77|n zt|^l+xhkoO)rcdemtq10w9L@5+uOY^#{J12%c0h(+G`K*EE{Fjp-4=H5r`DEj-Hh+ z(JW(eSjEt7I*?d~7rT*u{{TSHb75-fKH4ufjGy37`ce2)$WYTqElh9bGXMZx+fhIv zLXYu$Z?9{cUz_h&8&9^a`9{B>pJ4nc-^!UuLn1;)xHdlj0553WWmEQv8WMCJu5{x? z)gC6C7R`-`Pq0(4ee$t@$umE=(X_;k<5jbr4aTc~j-04j=|0+48b|a;uvSx7F{xOV zLnW5(1cOq)x>-Q|AYDbZBKmjbi6@O;yGYP(q>?G?L)L8d7`0}WbDawm3!!opT2^IFSNi0i+2WUnj-s#fh4FCjNiVCo&K(5{q zBK)&Rj1^QEqZ$~_pakw1UvU7Bfjntgn%PWN7Nd+S&nqpNw@LyqWH;Et_q%TK@B_F9 zj3`wirkXgYLGt1yZyvx~U<}~Ch_IFDM?S8%};ep5)KZ3+s;e$$Ntx-hvnIt9JYatAb_ja&-KJjhugf8d;lie`0*Nq`)c4GQk2i??*o7=EH-+I^MN+b$&R7q); znEBNSn+S^8#RqubYHR6&g z(OKe+7D4AQ9%pjR<}$G)3)JTuB-g1~l;noD2gRsjc;%{@3M#Sk;*<0f8H$akb3}*=Sc@C-9^S;3@2nlh66umQ zi759ShpMxuvNW5li+Jsl0V=UVhNA<*T*5j)1wiAoh9;14M2}S*^RZH`hCz0;NpAf1t z>~QCH|_SB6()$TRopqUlA z&YN0kp$dXF-L+4?&cof>ng&q1_d1O`o;Re`P8EWtXp*6#r%_Wn-1$(qVBl`^U5A$u z7S~(&Ta2YzCIp_Z$6%#tXNrhO={rx5+IhyX{{Swu{vV`}-bT68 zXxIn?xFXbXwJkm`VA=m(=pz+!|z>!{kEMXl01V^&lTD z2-;N_dbRE0rlaUO^2tOIO-|a66)aLpUPgU{DOkv5B}*1&MN%1jZf*{u;ME1tU$;MH_Eot#XV_y}@gH&EM>(H@^v77}LQeTPg-0+t0=12gx-M_Uj15ASwg#X!nX0SHwfMBvQ&v4xu^D7}oGDJ!j7`ApJV386~Ni(87CnB#5cx=>YjZ&1<3yNKO#RelENPaYp7 zok*UK-9;n&kyL>`BZsrsWgbsK9V%|6bq@xk#c;=)4$BcsnejPXql%icrk4h%a6t-? zt2Bf#JCA@-#mz7Y1dW1yyFHs}{I#O$lOqJm%<(4#dH_ksj8(zWbhjW^RJBpUV2sN> z(n?fnSqib*q%Aw3H)Gt3F!1fg#iXe0`Fu9|(D)>6qFvN1O9088M8q&|mQ*bGP6DjB z%|%^HRlwEDcWN3&7H!Zjv$1AS%pw zRHc^Yub>jO0)&E8Rn#PadWIyQEwt0=>#Th|#B=r|hh-{C91k@;G%^~DLW(H`JT%U( zwJP3ZXwfWA;r-yqr*H&=z%Oe3muKCWELvu#yg~>cv2dw6-AGtUPLiZKDNHL&6(pxr zRNL6z_vPEyaPlnSrxwvsE+z>>Du^(o>ujZJl4^p{S986Vr@Fl}vPz7({+@ZT&UM?^ySS%5Bfz>m16_izUlRZLr*ssCF>a zK^l-0K_n_cQ9dEEqJ8(YxUs!)3h^wfTA@K&HDZ)ufl?C#3=@HZajV9v>Ss=~#tjxB zlCk_V7p1H68lCAYAz>_AkPj*}Yx!!n`zy2oVQ$=&H`g_4*Dec6(4?2GL!*r z2Vol{qJWtds=qM`1Rm|u3``#FP_Ngni^oy1Dm=wqiDWqI4L&7VK~+_Tq!O5_C6b63bmGf;g$^s^P*YY3Y=iD(juVnVM7Y%{=u_V$5z$mi8Rwrv6@|c{ArjN!AiW zD2T-N z=L6|i0GY0c+gR0 z4Wmj-+@t!*7kfJXV72g!I{J5U&@{(8DvX!c7@K@Q(0h)AP+alX`Dx3du3 zWj-Zo;}UvegSw;@9C!)hdTUVM#ZwvS9Y3y&)0MqDQb&T~7~L21Ox;Tat4D@Zn0B8m z!xU4K2Qn*gQcJQvfH{+cr&sl#h;gxhy&|=vQ@oMaF*F^AC(aDLZ6QaQ0@ueyi zQHR?1MZq@WE%3f+`+G|kn^FrM>f9K-)tKilHl<5RLV^asOG^s`#?>7w zgVEJj8C!+Hm->$`Fe#cUijgZgb9GY-n55c&cWE{^2KLjr=RS9Esr=nb*gLYg>sS&x zz*K-|&bPkSqRrK%ILfy4#~!RB3b=1TIha#sOkXX$l1P=X($q$7zi4}eX{O?>ay%{C z*5+d|4J*8!fgaz5LMs!>Q9Bm;eGqH3Aqjr;{ePPv~Y}OQg(1P)gPw(=kxo%ZIpagudN(D*FR{V zK_pc{b)ODgOQqF~8ybh9nmVAY>IH$?S(U&xUD}TK8efrCMDKNYnZr;iz#m{EraZc0 zvlDw*@2pg)#j=%f*)U0-0(J~$FrvSL7KWM{rE?kw-L+WQi(25Zv2%0Y+i$M6^Drc5w3B6$sd@1cS4mkHU}7r4F5XKF-(`Z3kH^r-P^w&RYb*@r+q;EU8}=)Cx-M z$4^gFS3y!&aZ@VAPRtcrc=r}j#_TbcUtJ}<)%RFrk*U_3ONs&nl9e0;@k$m#WSEFC zcK+sD!=>Gt+{>uA4Wv1^k<+FU`1tG_r4=p6^ zhRFzQowzoICjlI5g`3~Md&9gAsjS7N)%Dw3qidCsOPs`tX{ zSW||crc+HjY#rU@a))YyZcBT0Jm|BREHw>lLR3x(3KO#c2SDHkJvdYtT5>fMsy32B zzA;Uh1vV31j?qwKm1hp2mZB7?s}PyKUM6rPm_md!zFHmIK?SW~cw(iLq?C+6CNP3{ z3Fz66T_PKCz)mNl@vGzY*O5I7bcfIzbPJ$azX-;0OuwGs#&E1bGc6V~i)K1{+&Sp6 zD%y%HDj$}>sUlb@UJ7Yul6_oEOrYDDJ(lPD-@N$11}xorthAOeSF5LBsk zL=_UWwviYDp$4Zt;mfkDw!x%XU4CKJLymxwklKg?Kq`%92?T*25OADm36OzhxE9mm zJDZ<}I&PF{I}Ch%+d6pE4y}<^ee3tur$D_;WUP(TpHICsq{%cHStO~dt2k~GOI0NE z(b3aB9|6MYqG!Y4k_je9sgin$WS!aB01M1H?8~#P*K}@guJc^M+tYIDl+qMdP{Uf* zq@^KiRxq%Wpdk=|0ydK&XBo3OiW+T(QqXN6D2=WtOstGxnZyh*5HO6Uwn?8mzi1C&Q@ct!hC9d4;2*#G{oXmh;fa!e~K41geeuyqdSmc3s}=vFy34 zhb_y=(5D*!uR+0DW(1Uyo~h$RIepq}A4}>$b4dgxN5Wvt9*}ks#2vJ5D}8u+QLe72 z#&JJSuZY*xO7m4#Vm(8~r>L4~4(TSANT7(kj!7)W}^9zy$3>#q} zc@F6MaN$|I{{TZ9ya*7=SZoXc2vNcy54fBL9+lo9_>OdAIOEg5QT;n*2rxe^MMEA{ z#Bq!d5T%6_B5%YVqOK~*R13VdG|tZCmeR@unV-@gK>GxPWJYP5dh3z4Nq8SWx2W8x@fP=M^kiyKYK^*1^kWt_=I%fkThfxP_M#Eh) zw7G8iq}(!fAzVhU6w9g`8&G>e{|SRi;|2g{X1UgRkkxM6)*6QC#9dE}@l$=W@> zU0=G5LP-WDImf4~s*DGv{{Tw;YW0cK<>{Y7@WVW$#`uOKBxNYDs&aO{Rv}SuE*Oz6 zPy${;0>+HQ4i{#5gBc~N?=KV((@7;tQNZ*iJXEC^0Wl<)6&UX>@v*z@6}q4afRq8_ zQn~_swsm4)V_Qhmeg%Jry!?UkI27OkG83y% znAtpdMOR;|55W_y8DkQu%$|ue6;@!twkce@iQ=yYD+4O1ks+PhDq6&5xmCPU0q&5; zQ#kIQZ<&4TNNYDqVeN`qQ7o(b>?LUH3Iqejq->vim>wI{B_{}RDJn_pB1srT@c#Q4 zswC?7OZvCcY|_{#Td+J^FXK^?yK(AC;&uvb7CB~HIuB~GUchrWGVH;O(V*?Ch;_5D zw4kBqf&F&PWett>o!UaJl!7+!jCe@Ebdl2o3Jhly)4*fgSQB-+lIGf5>Nh9b`Ecbj zlRvtIFQh0$&fEx+V-I#Gu9A49PZBY5q>^>g@=lxqfSG@Hr4eRkT{(@q4~aFZt)!0a3_5%cKj zsb1hEK0~bRJpSst4_+BlsD86Q3;dhcj-28Z5=#^~MLuD|X-lfSm{g5RSu~`7m5qJJ zDIl`31$Pt4J1n_Pi($pd7`Kn~k~}IStVTR0xMiH=PGtGr##WQ3TKpKmS{yo(pDcE4 zF53XsVpY*|o_;DR;!dyWnBn10nRr-qe!91R!lSzcS3 zuFcRvT3lp~g{Q=k?)TN@ejoWqDD>Y9z`F58fW?ew8tg`VGLhzm9U_7T^5%*ZmvIci zgG)Y!)>J+D3*TS5m6QTXc7&54l_!YuFb5Ahp0c|J?Hmsg`#`NFTvC*si6;@#NXBBV zUnb%CU!@q9H;3g}R};)K)y!F@nOo%Pr~M=$8Lk!qxQqDO$AFBc@P1h_8j~m^qfQ@& zG&;|0^j$1tp-{2b6^wgk1rx5PV%VNY^%Ir4oh<%k9&4wYE8`U^L1w9PC!m&D6m2`4 z7|@Vx4xFlIu=n5)P!ef)tlh zl`JHu`e_FYFw{7029f2joR!kN6x!0Hsii0)LWCU(Jtr6;|!bu&q>@Uo0g_6K^UQ9^>D8WcDg#F)nf;xQB#dYS4Tamd+vUbR$a3K*(zINvVj3S69m zIb(*jdGrE&N~_JNclm`Iip3d?N!o7Q31or0%fn`d)%#)Iwx^GQN^iowC`>2q+DeY1 z1q*XzxGYWD)(_>5m7$^I2yQFLW-24 zOn*ln0BnfIZ5K?Xj+~Fw%ri96%wRNCaJ$T^3kcZSKmh~?+D(nU-vOs24BFIRTe!&+ zsU`vfx>anj+RNkO+HXSL;T{5bp$0(-r z9x1UHJj9Z<(*E7@ndn@D&vxG~P z>NsHpJSrV~W8hCd=BliBHMh-8ifpHnYRKiRYBVpnPfbI;#DD zt1;`O*kx?k7gjSp9%|}TR9j)k*Ak;#BLsR%rL)tIC_p^zrCFmVljVww^GZX-;mp4t_uU3$Sl4K?{FQG{o6e#}y8g>(m z10sxVkmbWaw;EOsF|(+N#7{>GHQhbx-$yZK!m`~iV00Dqn?a^5*!a2^;gn5jAJ0??8gi-X1u#iUSbruoj6v97R0b&vKso3REX-; zmO6;_aprRS=j3I#Wl2;)GvPb| z;p^lv8!9)YK9upVN&f(dWEOQpL#o^f(&Gx%gDvHi*l8NiIF2{9(;~9 zHvV1TfsCFc9iykCZyG9?H%WS& z*_xfQ#WQ161=O`QMN&oc5d&vX?srDk{qNm6*p3hX0G->ok_xn{KcY+@f%4-(%PgNU zaAMxwn1k_+m0}fMl&djZ9)}X?oT6&lwGSp6i%l1nk(jULMN<+VGF5O?f|e=+TyiP1 z-j$`rBJIBjFc#Q2nT%3S0EjXU+$d3(ZtiTNe=^%TV*-_#C!s+?1|0*aa3J4jwtZXh+!FipP$W{7nphvMxN4f>KXG zC*>6Bl|K#K@0N2W8=o?lQCkbeFuJ%Z=qhmh8ffcbmL}XJhji${<14Cxua1X-`)9VQ6*;G6+eL@ArFZ(D7caQTo-*I7gtrRHNvR^fGx8IdWmS_qz4=EEd#&E`cYlAVjOKmi6h$(Sp1zhDN|+yH{E z^Hk4bY5`X=ineLTmh zXH065%|unO%*h=}!q&WV#=#lVG3EhcSxx(r20>++`+2KH$?nvGQnVeYP~b;FIB|-K zTPw75Xq`!dczKUceOX>h>V{P6q)UzEEKWJ8Y3A}>ep#cCRC!>S+9&s7XAQnP`=_`h zivhA06eLvm&C_>-Q)WcQ$TQYBbdD6f#V}RGvW%k>oGnR+#;nCjb_Z~Uf`MrV+B$uo z3-Kz9nozXLaiX1?a;w$jDqR_Z$+e#Muw@}5+(oWf9etO+gGBn^QXt-=>qtLQ_`LZ? zqz{M2f*G+PB_x|2b^!K9@>zA*!sUVcM)u*pSl@o=>c+R5J^5>8e|$9iXry{c=%rU# z^KK!6oG1D9Q?(u$hR`fqgw@qj?TIuX=oh)r4NilCOVp{NkOnF+I?Y3QV+p-*wxAS9 z0V8J}v(P>juvcHd4p_QH_-J7nHmaKm#M>?B%Dj6x)Zj9+(_x#a#XJzk&NogJ`Ebo3 zuwC~1Cg4YWO_hpJ6cj^>THu2Kr%2hrVKa#GikR;*0>z?OKWbK1NCW~^#7-~(1IrpL zeLnm?x*eQ-8|N=u{Zgfi1*6MZhYG;5<`qQ@DGo7S?7nPO%`Mo$8c5;eh$}N7Vn|yM zFXlDdt-wek5}vgkzQNH!=CY;}1;h!RL!uLhiwtC)m~5JF&6syjv#vcyiC5*^Dyq7Y z8hQ~sQ9{r1@ghY9EMZsQ*ap-F`wfNfrvMFr!b(seNiZ-HaVN~3r;Q1Pjk!2Bk6`u> zm0VZg@zZP%sy%ehJ!H%nMHOxxkZ^h|3kdm&I(c56s-|NgSa%`VAb|;tt+p06*Ip;L zZ75a(AWjhyaKv=&AoSx$c5H;GsUQF$A}}H`Fh>o5jhK*YWZWzC)hJr_EvdiePk+C^ z4ndPba3X??-Cim&3Ff#BxR6JMy9=L(6ePu1&?}790$F4ixI0M)?REfxuh;!NUMY%9 zL9IBalnt^lExYW2@wb6GkB@#iRWvDdYKiflrY(5{#YGI&CjS8AKchkqU=8#fU1Xh3 zgV83DK6InqRUi2GXN1IS`f1V}Foeb+rN=V`9I{k8K^0`4T@^akM852hO&Z9JzxQDy0eLXYAn_^0&K(?eHPNtE%N zN>;=rrK;HD55nSlnPfnXxfuj|QQE{a-3cRt+_up!YEyzhl5vBiCjbu#R*@s)QSR{G zxnpPh5|E{>2u`uBI-FDzrsu{Iok}S%2nI+MvR|#wR^4#uhehju3_nuXl=U4*!m6n1 za)xY3!H+cHG}ElqwJg@z9x;ci1g(VIe$i1GDVOTX&xmRoln4N7 z0BLb2i3Dm&u)`PkaeLTPm$;M*YgL~4u&E+jJ=1WkOHi$BuV_fnuol@;?yu9ws!#LH z=&1EWsB*;?B}0PD^|cTiMLcOwb5j^PsVS*bsIl*E4{t1!m%iP?Bf3~ir=dJlI$#iE z*m0;;?BUCtvhy!|pUm3_Ey9ik(HdJ;AI1`(6&qtv;ww$RPaPt~X+0O?{<1pZh16!g zoqCVWSp6PtDEn$@C}FF5EDEwGb}{c+)uyJZvKXoaaS~&wV7U8m`mBfM-=E9eYA+xU zu}fN%m5C-{M8ts@B+jWBQnJcJSw*l2xv)!UWkC2=TWKBgBWMtI5_Nct0*q|C&`(|y zHdA9Cg-5LVifrh(CJj8;E-zMDqJUbwq-*Ou@ZG^HHDksV2e`S`vA7eoiY=G?QTJmF#Zs*R+$(X0zm?U zZ${pxGC!oxQJJ&ws_GVDuElCHo;M8^N~^CeGh(&jYw9*gzT-*oR{LJfZ@`vl@Uv-aUH~M5PeBk5l+@j5 zv35qDC*C+!8sol)GA@1emxgs$BjT}EW>Yp}&r{-yQ9Vs1ZWjhNuLUJO7cTVOPK|g< zh26NVoJa_a{{XWr+~sIil842!%NkCdW>VM+5O9TJQyWBuVNyO{eB(DH2vR%dL7j<$ zR!BWKU<~3oRXb;{k$PvyeMA1Q=lmBL%8=%2QH)?&p9HC?f?PrdVw1~Nf?|M49LXsw zI=ZL5wS|LlMSqjs<7#NFN>EZxpk$fD zjyq3H2Nk}ab5&F|_>V(+nU=G}afT9MIHJB4iWH3Y@}G4*Lmy{-*3-j<2)#p5-!`WI z0KNxOeDK6jb^NFEQdn^-;~#3gpz-pgzd|wWJ1SJ;zLvdGWoqmPr`=e3Sl1KzMv{vI z%#e#=d6o%ax+1{M<<@Kqz7~6fVaXoS@rTf$97@KVWcZWNs5qV>Ly8Fl5Ga<(mu+0` zUqK08$ruH2AnfzTt*`KV^>mn<`@?P!=jje zl9oVCMLMGZSevejIXZTKyb33{bwD9rCd!q7*pP(I7?~gl$6zGX)0EwoNwZqKXq-vf zIukgOJoaEVR?Bn5B117JYJqcoZ`>Q78|m%lTdNW6p-3}MxP3JqF^NG-iqf?4PaRb~ zTrx%aC#IGilB}(JU4gZ{ex65;xPYWutt5v+#>q?ph*9Anz#M43#TNEqu!GP+ky_h& zn)Of7Z^Q4@Mmf+c@wpAM))B_owU5I7-`?0c@J$DI4kJ2`hOxl?IS z(0onL^a&tLouUXmF*^-R$9&jJX%7+?9v}u2#Edo{bp%84vFJ@Zc{F%kMDh|uZ5|Cf zE8R#oN01A!`iF9P-<~q~y_ya^r-z#JGhYz8ohAH^e%yHQ*mNX=Z*_*dK{gr-kS)dk0N4pm#P*#5!uC7tNCQvkw1P>&@ z)V^U!6-nIYM~)bSfxL?)^f%K%#m;V1O)o;8!gvAr(Q@~tz_6a}5^&Y1A8;P(8GQ_T z-}N)fB@Q~vUvGc%bufgnr^S=yep=;XuLn?I+F{) zrD!83$)T2|v21mO>MgWU(umeVS|DXW%1dzjdzqZod3Z?*QX6QgI7(KvIO?V+1R)@q zFjO$<9B$IPth@7u3R-n;!i0@zY$2qaaVk>DNQv+qVv^l|$j2pT>bW95Rv%nmcq8x@ z_g)~~%AmEc;77BWYh!pHNR6WpL9(JdbrmKK(YC5j)F1PVCli;=oIN8cciX56S7;&@ zzTtZT*mtqlnIDl~l_Dhi<3Y^DB-LkiZvd|9MnlIkZcfAK;>GKl2-2zPVT{uhA?6Xg zrsigZotC$}17F=Buik8tIsJ>4thT^$$c3%6$b%$;6FP_x4@uiZ*;7{C=@$q}f|61S zfFUJc#nfUzCuGe5oeaQzHP>X}l{$-p{Jt%fK1xhq5|8Gft*efpNCiDQK_E3X3c-BF zyDKRS2q5ww?Avm3E#tO&*D|w0pJ6}+9`PE&rU}xZNl63{1|WmRiMRg%D6_D(i&jz> z2`VWbB&snINl8f&G5lL7e9T^$Jrz{pIeP^am2hV~(~40=9vK!a?Nv=hSy0R8*3wNA zMH;Ot-CW2^x%d&lZg1HBU;OOl*6CX;gr#9}gaH_I%#k=(KQ}+M zywc^TZX53{RLYQ@Ox!%uO5D{0z@kJYDpmuca5S9jSK#65pQ1Uh6~Ho{dBL*}@?0_u zZlE<~Z4!uPd1Hz-O33O1Oy)9FZ`Vyl`Hxq9kC)n0&G#xu!xWa*dWM2hBczZH%ITKj zcJIEqlPXoFZ*-E{(%4JO4+VI2j9fv4>DmvriHA@+SL&~#nV%5Joll`Pxu%L39+M1; zYI>neeAJPaO8O}*Jiu&eodI@I4uhE9_h)x#%^J$B8d!1U%rw19S_oFeP6Y}HhaqOCb5H3PHn{@Epa8RA($xD@#uePB%-KE2^onkcjov zmYxaaStSaqb+JWT17)~8gReK+c~%`ux5;$6u;Rn4q!leVNrWVVHbj9KMHaW(?`0Qm zrFWT4{ez8(N|;xAnVu;_!eH?z#}gAqf2#TW1@#w)VVJc{6*vth4;62dPen!~q*|;> zv9Su;wonX)qPB7xKmZm+RRAd9cP!uR>mzk)UA?>g;(=5ZAyAPJm{9-@1cSF_OKRT! z%roVLBRO`_N|+ZcExnvcTSWj4lHdobfQ(Z(w^&_bi?%<`Nk_R+QO)OP8`EKm?UZ;*5|=h~=vgDEk&So$ zZaV7nm!?UO1_W=UkwV;)U<(U@eLI1E+HzH~-`4XyQFOuTN|W#knvdSe^P5#^ahDKB z1v0T7-ims{dUfh95fn6Z4LPSQZYkZG;Fe(Qu0hoIBiY}BK@n@z4} zFbz+dPvcJ6hYR%=NrP3?V)!Jf6GjZJ91`wzm3_xCsVCnAT~o=VXF9Z`!EuUsYK47mN0~fq86&GG5*I0Rwl+dZzmH+Y z-O4-Q5|sdTD9ISYq6QrhXguanUx1Z>btuUg!nk446rbsc$M9_Djbv;ldUx`fB&dRY z+a6FnnUxp~0kz5PVmJ+8simn0fydCs6wQK^)2nGDK!QQ(*khg|j{g9l97d-K%Gsj| zYJ`TSn;fZk+6mQ_WAcd?8%P_0_6-i4DtS2S>op6y7Bv^2^)w3uW(M`rki-elTJ-L zP+{~`zC?#;_ja$lWjg!Y@9vdG2E_P*$RSdE*`)&}6Jh1B@i z=s56AT1`!d4yvSC;XBkw&2p%0$3|e5)k3e1q#J|J5l+o#rjiKfGmkK$#K+507_ebt zgtvhNu_EW$t+pN%~<(JmbgEIVCq7nt{5idJQCHh|Z$4eimb*jSUrX%cF)Q6!_1s#cB$ zG|ue6Gm8;xd!ejUx}N%bz>Q7#y-6`vn&gzqN`jtfW^$?lu-lJ@52_8O_fr&C(%~MwUjk+szWEs{KF|> zWL9+wjDU$9q-7poySn5PWwC?z=$3yh@Y;v4z!8p}p!7t8!=khA>HU=ECpofEBs-Qb z!U+mGO0h{!CrCRm1RQz@cp;i{>h=q%kyNqwhz3H>`@6eot;hgtr2a-Ho;A-aWfh?$ z@dM#gfOn=6Qtn1Y-VVbXEKIfqtagNUB&&l)ti*K0;8eaKKBF$TrlTgz?s7GN~< z0MqjA#>uY=lRX(V5v@crk2N+%&8u$Rwnf@30BuPm`~|p_)3aFH4U(xA7bYf%*e23+ z7aITH#EDVSfdg}uBVAaXJiCoM8=iV9gvDa3!f2w6 z>K0aJZI*IK+(KMN$6dR1B?-6|HyU#48!K~MWy5BMWr|^Um08)Ba2CD%zyP-52e^ED z5#z*46xpn3vc~bGvTmkryH#Ix>_{pNv=<`e*x$hDc%dRIQ#8UMnv$MMt?WI(?8VOL z)HyOD+#SrichoJk@#5IRuAQ~$qPQY=C1X$*%R-}cZE_>IBY9ru?)LJ96zHxqQOz5M zNP^VKERKK%R$|IY2pd8O?4wYBHmWJamh=vp#%Biiaik`P#2fvF5H zZrpGl0}?sJ(!jw0DSi-79ll{ZPrA9T2-uJ#5vUQy6nSt$uN+Tu18$Vr-QM7fZ3Nud zi*cUhukJW>36pB*|dw2ds_E5x+PMi zi8Pj$OnWpek!9Fkj-0OFpOzw8%mFP!1A%zkxRO8=cU5u$;!+`0ya1iP&&Tko_%2?- zuu68P!Ih%i;o5cvS!cb0k>w;btXzM<-#|NYg{n?8+SiUXJIH!Fj)*}cDv0ohFGq; zl#g_`_7TbxPb37y(z7q+x=bFH8qm{<#PbY7IKWM>wRgq4a8tLt5@a7}u)VmIO#)=r z)b0>46a)Ib%!38#y)I3{VwSF_GE{73Sf!Fgr==oENkj+qPUSY6Ztve-YhjOCU6w#} zDO&{EQx zBS}$E@{8^Ypa2E^=GV6cc8nq56b>g3P9}tzeY;OIm8C~ffutNb>s}&o+2(2c3d^`b z%2UYEO%)PXtaH^)jkZ#%l?sWbtFapA#ZAVX5tb5$_F<|CJa!oP(2aKK?#Y81u_uf{ z!>bLw8!FrX00~ScX+N)$JfnUnlvSH|vdD_t);k~s?1=~f=snOh1oOdymdd(J`A)%G z$?+>c(u4SV0fik*_nRZZ&NqW$^EMfWV06_IW_(^1K4lUrZa7U7UBhCPLf4TlwCLcU z(=sRyUcKF=SindHN2`iQ_s0x)PfZHSrCLX+=;|FO;Z+0ItmTAcEU$)ToHB|$GQSv; z&lC_3dI%l&?Q%WlaNAS@4cH#!lfWlu*TXN(TFjhCQf=4XBq}uP6QgbfBknWMDZTN0 zTiJe57%kuv187ejn99D;IGSweCQn&CNoCx}S>hKWb+Ko zq|32{X?+Xn$#b^-?LDVjKXil;l(daHPA)C8A=Jl-DNL0BJWA7n0Mp%*<*D5q>e&u} zRHYO+l}47(=pjsyOex1e2r~(8aq(=sPMmrb>F23Vh+=uVhZ1ZzFyR=*W*Jc#iU5S45d0F|350d4w4z=3Hl%ADXgS6dO=&C@C5DckAlNb${ z#b&2!6YfL z2vJJFjcreOoj@4}Z3l9^rB+48^&v@pA-3J%2{WN+CQux}NRUX=B4h-8GW9`<)%vrC z)b1+JlyHotlCi2B4*;R4sKu$?zFJbXRLu3;+MO!uwm-am)sJoN1@q3!wWh3sR1%~q zmV+%eF-nT|EU1t|L4~XCI3!7eP9Z;(IEO>zf)EMlA`GfyX#^xBVX)CL>E%vl%lWnr zqp@0=+!l&_MwicajbyEnyp(v`YZYXcLn4AM3Tk|K4(!U=cX_Ag8c0!K_pqb2K*L~= z4~tO>1|aF6!v$-2IIj`KSnMh%A9Wrw>B8Loh|xy1eIubq6rXO;KAG2JlCR zB^@gdA`@2=G_@5nZZ9d3RF)-fRGwv~dAe72Yg4zb8+~82fTMvXF;Wt}M99MfB*@!a zyLa+2-vo_hlOs?BVYdx{;&z$YN5XH!%hBIjdSj2#^zS<7RF9m~5mx!#*)xtHEHq^B2E-w^5&2`5k}O45@Ai16TJqJ&vp zl5;;BPBKD9Bg6`D`-%u0IPvMKDa5*ojrI4|bRA;O6!l3#oodk0Vf9r{Sy0rfRVe7E zsdQGGVniLCm2^6QI4#febndOSrPa!%Yw3Y-9$#Dk3;Wwy#{{iQfY zl_nAZi31P_;fU0H=>7G7qtqQ%#Bki<)4G(T&bWMvmxwE;iBTsRQ9dKoKX9pj`LE2l9RC1Z1dy(?{UL^=jj(v^ zqm}6IB4-Ys^eY3R&&Dy2B-OHFj2OsjDrc;BYKcg*J35W(NY_E43-Q+2DF6{0Ye)qM z2v*pVdQTJU$DmPh_2G(Q_*H%fjA0Udjdmv-m?Vti%_LLE403z7P-&e@9V|-=_TtOG z*|mpQq>re#8cb?BeZPUms=L&mS7<#iWt}y zq?s00GVI+iBm0?jI0WJl>R`|MWqNtm(jK8`u z{_qJL!Hv|lKni*WueN`^7=hKd8XIV{verbUUd z10_7{9g55)jCnFx`^w;vd+XTT-rSlCp(BN3<&S~n&clbd^{!u!KTfIfewlQ~tf(&7 zULlEKH7v>;2y3a;9e=vbK%e#{U5F zS+)LHsD~R4q!F~XsM*KDpklSgoB6Ieht=UVUVKs1(MAJJhYQDh?Oj_|b7CStXTb9q zhK3ZCh$SmK9NX@|4l3i(U3h(?c-xH~LtAr;QwL$=;&9;zKW+pXC74)v=uI2KTjk_2 zvO0_3dG|_pC3QOLdlAXm<0{k+(K0-`c4M;)IL%^xiH`xo2?log5z;#SXz}`v>A$95 zM;U)EX1=9V=KiJN+175&`XeZ5#IY^uwy>$zdPOq60pJox*AC$Iuxx+_8I{? z_xQ5@BA%qOm3BbtzgBU%vd$wL!Bc}!$rc-jO#>0So?2Q2hB;zAipUrr8}l`{Yq8zg z+{GpAw#f~x7^Q0}bzxgIC2px|O257a50ztO-f?q!N}XKl+W{$&u#5*rAEg$akos8l zFW0@2^j9F}49x+3ja7$XH8WD7@bjvKe=idJUDOUs8OHTxySR{Z3#M)75M6OC>H{1# z97mTNaoa^!_O9J4ODIyw{)$QYQTORD;Fs%Ls+Eyovc6W!wbLZe6+R`IX=ahUsM=Op z1{3qEN^GPLnP`AE3`a2UGy107yC;!o-Ql@fln?_Axb7uU5(b!_GtrDxq>j$>j^w_! z3us8xROg2eBjP{if@-4}s;+}+1cBI*;BI-JDq2E87;zY4C#T!SF{p%yG3oL(X8wh6 zPs379onv{A)>U-xn<+6`bi=UPy8L2~4Vw#UcP~1&2Zh#EOH!385u-A|zFP)XBpzW8 zYS(-6!q{(g8n#*#mG_H%KrIRc1Ox>wA_&w;(xM0gAk>|^3}o(=oZZKe1ZeJ36s39U zAORDOK2&XS&ZB+__$XTHEUQCOAlSm62EsFyW65Usm8ZuuB^*Zn1jGfqi}M_^?2on^ z*h}~J34xp^9wT8=(AYkSN{_Vq(sBK2eiIm`IM@Sv zZfq+GR4TaIP4jh)>*SqW^(+95=2DXZMcIU}c?Gs_g+J?X{?LzQym4kS!B1fWQv-D`QCRCY4T zM|mY?bK>0Q-gUg!yWMl%=5H-vnS_Z-NBj+`2p)4iB-T2*R^p4RQE|c}TZ)tACt&{d zAP%Zm;dSxg)5#_ih~gB_Yi@!C3;;R;L)=*Ye5O;Frzcr<*5c)r5d}@8B~T2+hXIX~ z*GOJu+yERyY9HSd9}0zB*iJ1}YHDh0>SvSf6Hgm4@H?#foBMx{5IgyM_Y}3Q_ZG7x z_h?d-c$51{C$HN|&=$gUgrOjRd_eTVli8As0n9W_ma#ffjA8a6sIh7oDqMGL22=rO24Fq5PGo?ee^-Ph4^540qVU| zRAPNGp~9+P?M;E!RAEP5F6jiKo4Nl0iom}oysNe?=C;z?Z+Gx8O4>_`AP$s(vU+xt z#)jPNOjaDN(clbNWcJbk~V{|;Wd+6zWvSZ zn0oRxD3vF|QwcCcg%buK&dg&>38F=mF(H<-%?2<)bcRvpT(;7#cE~g!mDc3n!;(ew zUz)d4IFW|Qk%;x-6e-Hz{#$z6oB@O6qorPkL7aADvW^xdP`6Ypp_Se-I!nCX_ERaa zEVnu@atJo$AkuyS=^{OwV8cV%N{L~HZ!uLJwo0Yf?6X^O2IWgwo8OXN zT(8er6mf;8*X|M16CH6_g_+%(EZM8#Fj-~c2WnLbQ0h1t94D@=`|$Pa4^Fyckn{8A ztX_u(#3^fOTMwHMn)auxLX&)*C=Aj~?){(%KtmowmlB9r5~7G06Nn@$s$wxP1!aZ8 z5XMn5$~2YdUp+Vi?XBh{)J{b(L|h7ezA04Mj37T}t`W zg*(C90cTw_xa0=PQ)_VWTZl?k3ecY#@GxX2!kxTSCWn`|CidN>wA$9BcoemG69*KK zRpKKE5T36z=5fHYw^ee6E0wx|j>Ch)G75@Xd;*0+!B+zbsadf+Lv=_B>NSZY()PL2 ziCoW`wOU+h1!X7r%;0<~8W93CleJ35CYiCzT)UPZb3$AiRo#xTLDry5f(FEnsHr_V z!@7A{hGG3i%2;%9@e2UGWDj zxNiBB<8qi@ovK@Y7d1`+WN1=X(>PEY(Y~T&uBGQ}*VB9-0+R&Gy+y(s0laT4=34b{ zGM=hACEFyG9(s-B0e2*jFTq}UVE$6WS4wa=?W>*i7#dnQDJCQY>DkqV6YibOzHxNz zs*+n~<+8~*_?#ews1pRJ9lzgnQbVMDCZtY|V|j}eq>~ZEDX8mXulc*E!&02G%MtqLXuBoIn6t~>{J<-8p~NgKL1-pH zOmJ|KB+eZ%w!gDJ9}*-}QWa%&C^b8M?|B@XoBTlUZ;vv?&9m$H*F0lR9+kRhp&wHn zAM3xMT(Ocf%|y7iF;j%pW$a4>!mzr`M!D7?(4iF6P_%KRk&r-<()tp0C!CYdw{7g3 zH+;4N5*+VP;*=6RM^wtpsDenq5rt)5L!D_$PheJvlz>de1Q8#^ouKeEB>o$@udCEu z9mKsLWelFP;vFfkn+saJ*NoF)jZcQuGgQ!g{ux5Gb%d;Cl$9s|PzwSNB@Dvd4_y9X z#ff-@l(v;AC36eXwL)=Fm=Xl-G-sJwr!I7%prF|SZR?F%6^d{YV`xl(NE-!K$Ks9Z zE2o*lvkJpAPGiF}9xa!u6>{zwlyE~Fa^g(hQJR*rz3QxH?oC!f z>$QGf***v%#jQpFKXOO~DOU|rU=K+g+FA^j+q}FbD_ILeNdT^3gpv0YtjPcYC*fM1 z1Wa;=sZe5`qi_go^PU%o3Yr|his7{t*qm*!G*ne|)bX^z=0oqa>I6$-cC%PpKDJ(3 zd%Gf}H>7up3JtWZWS9 zZN1z$?|a@(fd@h(7z%spGjW1{J`EQ?i$VpPsjcX-rE9v|gc%}XTjW%FG^fp!M=;@$7< z6Y^FrHDu9M;)awqpb9`Z7d3sZ1c^F9B%BD_P(EMT&Cq!dsD;~zI?;lO+7M8DNHc*X zM?s-0*XQC*u&hjs0a~XV07!r~O%d-7_PDo8Hj2`em{P&f5nKM=-S>MF z-b8ET5%J?S|JR|svyFN>%2QNf88@iCMZzJFymE*$bv-mLv)yJ57)FQ!zUdaR`#0x4 zpH6Xe3VPDfeG_h_5gRd(diM3ys9S6jO33N)VM8}cJyUecpcJuS{TR)?O~RwY-6f@- zJllbrG8?HwJtMG0I+Y}-UcdrZh^{i*i`Dnew{8@6>1E{O!|hna?2(B(X)|d;qyr4~o=B51<>iT8PqU z`GQTZS7(&=1QU@tb=!BPw+tmqT1t`zDjHP^!(>Of# z6{#K%oZ_Xac?!s5LIcA(h8uyf8g|;Zr^p8Wi%sQYnTb zPm9s2QC3o`1e#_6B@7CAQX_(|<`Zp<0w7H3>+dQ;FbMU0K8Hu_9!x z!-RfgMJWM9Xwn6xQpS2{J>gel^ouY`AZuKG8&YNaR3h63@^j=}z07gcVFxPm5 z*KM+GxZI;l>ImeOXP2>wNE>>1)WK}OB6d;wUj9+w1b&&v?GjPkui5IHKE`u4G5>m4XSP%f% z6+h8EClsFwx@sR@{{Uu|H(k}+nov)LNDu_Fi6ZGyU~HWj>{KD=B8m4EvQc z4kd@K=o2s}p`+Q*{3Qs^h+P0$=irTt5%q|5zc%k+Dz;fYxmcu?tzVJs~vf!zL{ zHTS9HCijT)9L(~^E!3A7R+mW{O1{^0kF~%s*AuW}JXpa3Rc%e@jmYr0kp?(^C_dDj zJoWnOM@;(3=rgP5rqj~Z%Udl(Z(rubuSJVcz`%Kf#VRAGYx}G`87>Ln*CEconx$*| z0t^<;3v8YQaY&2?l9j(lC^8y1~+s`-0~ zCBb8{fhwZL#F7X%*IpJ}FG!^fjB2?(bYq4r#fN3Uq9&z{t7VNG9lO*=5Rlx0-N?VR z+;-%rx~=L;oIX_$Z?*1#hDP7G{0Gd{iv9%IEBdk5%%jvSLY-xf59WBqM6!Fa(I=Dg z)b(?2)5=G68@w62>BFb4KQVTcq+rn`o{S`u(HIIT+}lu_l&MGWLHqz5?KQAJM*SRT zNWD$tvE(Y><^3_vloj=zK%%X9=ZdDTqs#)5lAVvbWLCOOZPB8V#GRv&ZI@NX25t}y$U0jo1b83~OFJY0LX*VAaWqvw z82+4egP==Y}{j;&4$fKb%q_}w-G6rN-*8DppZXX1RB4s*`s^PvtwfNQc=tR8QK+9` z31m@iz#IPn$=_>{(}M`7nsY&(X13V;Ai7MQF!V8k<_TgkR_DsP%)v2av$PC;T8KZi zm}B4n00*ZMHN{7dxC{r(`p~}F8W54yKB~vz6>1U6X)xLA3ED(Nh66%QpMJl$hN(1Z zKpr_#5Eo-`y6pq@{60KVlQi0>7{=$3m}|6ImrHBl2>O2h847GxCY>ZgWRQh~h4)2? zw_$$5-y8DtO~g@+^yP-SVK~-gW%sHkikS_y+Jk#r{t1T!IdXpGc?u`HI}__#yM89! zN`9yQDcGJ!jH^&!w770sg!{HhVvo+7-g9N$G=*DRTx-c!D78)FfeP58r^*MycGfFz zh1s_&c_ws$>>EI$_g?uw)8JC@KznJ6IHPBC(DXHtW)PE<6IU|l)C|FsgrzIqf z!ADdq4)i(%^DLq4q=(d!0`O8uI0-PJhY`cqWd`y+=C{ulZBRm%jCCbI$Vl;|q#xlt zeK=K(f5KpTWr61Z0A8I!^(u`9C4}TmolQdchsjAs)U~+fTU1LGq`9a_A*PXh@wIlb zDhiT#e{R~pD4;gDq@^Mxt51l4cptM4Ck~1)-ki}E&M*}k5S6^*ws&a>?!t)vB#ldz zU;;rq0inn7!>Xb67uC6f);&Eo3tY2N;#5Q#s3nC$QdiSRE-sq0pwd{2A@Dp!z1IfG z3|U9_Cbg<|ha5VH=@5{S(hWvEnpysI-RBb`?%;$++F4+CZK!mGVtNQQTp9QARm}Y) z{5&&frW{g%Pf+WYuL;E>No0luj;R5|v79PMMdX5{7m*YZw7Wvxt;A06L+{y(aF|w| z0buyFuLUFl#Ed%5H0%ABHJImL%ogUBLfLg_fOV~tsWMO40Uvfg85OqIq<>63I>5gT z&Yk*Y$FTUZjJ(-ChYQ7NCPF;fXQvHbk}0#tD4E*#vm*d>ARb7D*|*v@?x(|~B&9+O z1c8XagU6&Eu~?;bbi3D8e9DHUyyKy0{uc|1RD;r-2SEd%)~~*)y*lR}faZ_$Q$?7f z!n4myF%y}3U7ahWF~#!oZ<1U;5O)fXNs5qZYZRT3)`WHfI_)59XIN;Nrb z>A)>9DrC+cBPBcnK=@xk#tJZ4J9OcRL7+F$_EN~d zh`wO;7wcO%Rm;=a6}p0DjHf65 z)2ik71S!Iv?BYsJnIy)U{uu;G0D%V@G0%6M-pyLeENoOuZ3h)`fJk%|zz1nef>e?W zYT8JVTQ+1IrRv|Ry&KE5a*cB$(ASE7c849|*aVZ>{yaSTGQ1WWg*mU93Ea} zO}@^i{3avrQ6+QX5s!rIGqOPuvZ7+zn_ia`N=WeFFg#}shpMP6EM&2eap{(iEW?22 zJUo20WDQRAb@Y`1$exx|mgX`Du>pe;0S4Oh6>i;H6kB#g5(rla=^JOvQNk@x-kq_- zZ>0&;n8s_b#TK&)%@r_KBuup8zV#~;ZX~2di>j=ekOOON$F~d7VQ%kZH&ZfwZhGm4CF&<5Rnp|{v-D!3JjnIbD;hp4fF#j_Q9}%| z`6j;wn`@A6?-Q}J04*rxw#l$WG)#qRNK&Ac5+V)t~q|`75MO81;@# z7wo&AQy0Z1%UvwVam`zaM$}T%Q&US{QzTDsGALk)8N-GHYXS6|a8{nuEL<9GthADG zfR#u%5ddwb*Oa`@Do}uNB*6CUqh(FdUcU6&hD=XCV0lNRG2>W$RTV_}y1tnzq@b#Y zZA?jnBGp#!U;!Iqj!TbqhYiN{Te_V_-rn9YCC|Li4(tL?4lz4$prN;2)(wR@i2HaE z{q_Pp%o+w@#;Lk-oN6ihP?>iXq=6-%qsFAm&j-w`^qxffsO!v+9rrliz%a0MDouh{ z`$Dj6me{suNP?Ayf>cNw2qs{eo&;eSnmKECt`vZ$PLg(~RK_@BBi*xQ2D4{La)t{H z6;@u$FFXttWH@^}I;DcVq_FphzVB|f;Ti2Pr8*n5v@w8En-X{eK*D;cvhOb}8B&as z!0`4}gY+hqGRH`Izt%tHbd+^iZd9s{H>ZR|s`FB;DyoCslY7(=bMFQ5AagdebTMMU zS#1d=0I4WQNF*Xi!Zu<7K2tyjopB7TB}NvoG1x+6<5xHMTJ?&yqpI0kp&eqatT^p9 zMWmktO7vLd`Hw9lsD;8?e9%&WqUvr4dxr1E9ob#p^XGYvV);s$W!~iq0z7&`QxO3E z&rYe4J}s)6%`NA&VDIGvv%7K9JC1 z)wr*o{&23ASX$_tQEA#cjqENQK7<9fw&a&{nBCgkvu$btQ>sw$5+g{}hn_oY9&OR4 zS2z!R^z~I3^*#E%HWnew*(R_U)c%&1b&(tn>_*jPUji8R`UfZcw|XA5{_euYIFt~y zk4?2}hI{N|*^LpJ+T31_uvB8S^>lFp6&6SwGB=9{VPXi>-$B@E$*(Qny9dmdQrdwS zIpFf!gmmLTr|e2W91SRNuS}WaI^#5$&QidksiMsoIjg0_X)8>LhDl3OXsTMVmOE3b zyD2I|Fz^I$L!I`gW4rh2LRop&3VdDKKtp=O1(h5M2_VX3kugO%M&n&)Eh%bswwne9 zvPzalIuenNs0KJr+8+M^5wA};cS19-OM2&nRMXc@fJ;e(V-=L~c`DT8v(e1alEj#2 zV;PW}m0(Ei#y2ZCcQm?1)%Ztxm1$8xAv#D@Kv5)wsNpB=nuR-f$&quAzU`A`GK8Ro z9YlbjLWu)uB07lxQNR2?dX0o~@g$X>Wm{f*{#%+oPG|beShSd3 z1zuO9oJAh;VZ$h7#b#ZE?Q5|LM{6H%F=eLvt2V(nxT65Q#@wOP4QW=D4IEpPc)L#h#9@rVF=iOTt)`d zVnOC8_IJI*Bi{Rq?J0Q)VMqv(sR>%rmkJN?F90!(K&VVtVsq;wl6HG*WEoQ{dig!- z)D)2F8fj~{0G|u3;;4xzAZh@VnjZQ+_=t5M6UJ*Ox@V9voMw*{6%kN~yoe<&8eKoq ze9)4&nSU}c1%O*!*z=}e?8$2K$V(2XGy61>ji7B*t7*nS`$R;XD+#P}iUK%4N-mh;IEHO%YT9DZ;`pW`P%!MjN94#zbe9pR zSqi$F#{`6e0p~9FfrqaH45cAXT|Ic2~vPk zM~O!S0Xt%K9*CM9@|IQ1ok8_GMbiAIiTjkfI}pX{mFJc?r>KUZ78xd3u0+mBP(_W~ zxEgTBc(NNG%ptJC1c87~oJk`XgXc>|>Sg!$X>Ck2KxnJ&1H@DSIAe}DZ0e@GA3t>$ zB=y@L>5e&>aVkn$ifC~RzfHAwO+fptPv%S=nc#3xj~i>?1WB20#j^_`Af#jVsO&og z8Sv-WRd`P)AwXQ)2fP3!A6%w0YR-DB8D9rgqP1b)=eX!*iT``y4 zq;36@5~aq%OHQ(9rW1_`_+L=6{&Abi%DICj&-R* z*}E^-?lPoJwxp?bWZrLPVCo4Voj@kS+>oq$Ox`OUty;f?>IFzXeih?8AdR@~rFI+N z*(P?9<-TciW4Hb&OUVH2{x)44a2??XiLQ0M0Wj30@Mb(Rse`4H6T)Psb0&lVBn_#x ztVk_m$%@~%ci9npm8@}=oRJ+qByIJImFzb+cDIZESo_0Z`PvfVnMucF!^l+dJ`4{E z0BU_Ebq6kIO5Ev$HXDp3W+z!Zt51n1pYpX7@uMPn>liafD()9L4M!Shwk)3Q!nYA{ z$x?}hH>d!AzDl}yz@_W@bkFsd?AL8_3W@MIq~M@9sTyW+1gbjdX7uIJtmo2hnU&2s zcB-Ejt*ganmPmk{o%J7}Gc`GoHKVak;OpB{!9yLO)cH*Eta1?oZd)BqmZ1KRdm zycr4$Z&^51DkQd0;Kf*Cg%WV#9&u7JY8Aoyzl35k#?;A+VYPHE3r8Y>JtK;^3mFdN zk(9U=zhZeI<=4z!tM)E7u%U*9rCodptXJ(TC%CX_x8G^T^qmUU+S43yBtuDlc}r469gDm8G0>`*>LQ_zM}vP?mCAwrQkA%vGU z^6Wmxv|sr4FH&g8nv(Eugh47XXxTQyw(NVCDh8vtBwX$!TKv#WGNT5w`FC(UafE%lCEh^q~iHaIG2U2EhUnAvT8tQWoJDvg!@K9^NN3=)j8OEOV>H35Y9hHeEsYfU`%Tumpmd z0B%QdtL=#uq~dEVGeJz?DyzQcMlAmTq%3X-@YMK`sTKmp{CJ}ZezH9rkt01?7=%lx zg}0*aHVQmKi}>7;pwo?Lif3I+@>&)GRBf&wdN11ddowWiLR=fzgJGj+M>L^Np;g&d zG6qS63p%8cg*SN~SekCHd4QIon4+22W@&)@53xE-rU7gfu zK9i=l970FJy)@SaD**6G1W>@>+su1d?%ZLJd&HJi7tj%KMaMivIFmH*Jt|F55e3ph zLT)VjY8kr=+jWYPSoh*Mid0P}u?i>}85``zq_D6X%PAYgS03{P*SCLR0F}twP0cs8 z3=%`7 z&1*Nn_9P;&s-o6V#|(m|xf9BWk9?_Jss`H_#-_{fDvdk)ZNnsrY?|Sh>hRnuc;ypl8<% zxjJ63xIs{#0F>fjg9;=h3}rcG&Do{T-1RF#M333($)fomA_OCR{HQO%g@H~3ihq)SU# zN~FO4M#U|5J(aJvNiAaAn1SwlM(YmCP@2&-ib!IDSE_d*6L-(d) zHzXT!`zg7sP+^pjvr4fE%Bzio?CiC}SdnG5mfk1o;|o^G@HLVhlhX*Q<1$3sn|K6y zNpExzTI3x7?0Z{F-L4hlX}U}vKO@Mf^CT<|*n*Awl`caAaI0-Lk^we6c}6SAH3oV} zq?q>JKT3+Ed$&`2=thR*-ps&UXgPg&Q>moX^3u&L(P7aF(5eY2_JpbXAk?ud3tL05 z7Sh)5%_-TzB6fLtpTcO!Fj6IFPf`1il6L!Iqt@W{wGOdjQWtuN{n}`Q`9QVqx4)QJ z+i@(xZZ1Z=R+hE>#|YWO@ikL&mauIwf26Ec>HI151ohLEEkDXZ9UGMqQ>zlJZcs9S zp&HgVbFR8t_FrkN(D z8hU{rnJOa2AIwYHmww~4fJUk>sJIu%E#BFy5;au5#uL;=QWXmd~7?c@4W z%2zAHB$Z7ebdvU2OPzs;X#+Nldl7%QaXPloJ1V-WRc0MePF^~wHb^#=RgsGsEx3my z0u)>jO}91e?crq4zL-+06-8At;kA>>;*}z6Nl_^QQHui1yY{lHfIY61vouL9G#EBx$0+H3RMgE+Q(Cy9SJOO8 zG*Bwb38r%(y0-MaxN&QjIdp>>M3Ryeppr2Mi1LClsW*3!$_IX@n@*%?30J;iV-19H z+g0`IXVP9`#k!I+=40x=O|iMg7H<_EcEiKU6_pW4Si$X~C*IRTZc1(LtF5))B~5?< zI!eZ)Cxq=CCxODID=fK!5~kg6N>ZQ!SV%HQ6O4831_cJ0kJHw5ufphZo)y$=iCIc2 zsqpBiAkLV4(xpSGSXmJ5Q576Trx*gal?@7Ff@nyxgp1K94{Hev1;rNl1bK@IaZdD-Z5J& zidHSxNVf^5BFL=1_a<`E*rbe3oKixd$%%|6CuYtxg2|A>h7^Jbg9}L`qCnz(n`F)u zW_s;il`_o+6VhyxPSn&c$vlv2D;QQ?#z~lx^VC#S{*m3acDpx#<|S{_{{WC_7URRH z>M~=(I!Wm``c#{hHkVwHjBps4JpgS#I-;JkX8O$I)|%{d29(y~)Q9CDcoWS^NTT-% zhi|(rY^+$bue%MvU(#HNj@e~4z&YV;;{?H3Khpk-LkI^IoKJ=(mtd~+t)CO=@PY=U zw4I(F3Vh?KLk5Ne$0Tg=_$mGwn5G@oqt+g%;Iq@>`34wa6jDJffMYnlGFIW3suxQa zprw(Ol-*3)+%oec@{4B*0#smW5JANyLPi|`89jJZL7BeYn!!vcf(ge05}-((vT;fE zG(P?v`7aU3INw=%M+Gd@)p>Uvh8#kkSly&a_tnK4!RP+~rOQmwAuT;aF_K1M6M1T& zAnd_QOIHjpNG+@-NlK(@Nm5FHk`bx|q#O)L1jT12_l6YfPq0*^yxLs~P|~d{14>k2 z6_ml!vobIQqzW~CTgh454(Z-2net^lLe=5VNhD=agB_CxF?*I`jpMD2tU=UraLlY3 zyJgm#I(ydC*(oqWRy2}2#Lr&JhTP0n)6EUKR2K$dl;S6xCTg9(7MzWcGL1e*9X-g6 zhvw|e)phvZC5F;YBY03NM@>9b!(@|5A$hlL5_xJzV0nbw=<^Mwi%Yb$-Tk|IZVEJ| zE)TJ%&@e$u$WEemrE-sf~5 zZ;MSfCen~7MHH#IrHgO+N|7@v>C7!cgUSi8~VR#%hkzwmH zQ^=GsQbRwI%^aX@3p{}%M%`zTimv7)b2@uJy|Ld6$;MOpTXyc!+FVF=C`uY=A#Uj^ zQb;an8nzRuMzOE*ujTH(wX~p_?$R`vAQ%8g0$|86c2$M+`=XhOlRINsvoP1zi)(U`=0u0tkWwuVK!27Bop#cCGgp~c;wh+DTVvTU@6j`^)gRib3#z zKqwoTubY*X5t}5#7MH;p?m?R`@1~39P`kEMhMfC+SZj^MJ zHe_KPJ~N2nGvy3IeX&ck`3(L{GJt=2S_$JfCg*0J993zS3*{FsF-k_QB2y;~r>H8OHMW9+O@ z3>2&yw?D*xCJwQF9J%T6z$d7|=_s=`5CZ3Z9Z?+QuZSj{u8cqaX9Mn$wE_`AS-pdJzWNdY>(A^DI26h&BbZXwMKE;k-*Vg%(z`H3Dg`@ z4p`BDNoa&h;00m1Q3SRjwba~=KGuVh<)fzJ*$R`h8I7X}F~gv3>a110U|HU}+z-0| zCLrSjRz7DRIv;v7*Zld>>>nG*!k-MxIUg|jZ;a(U!$`P>3y2jq^QNU%4^3GS7ml)- z;i-C{QD8M9^b+_bV;mW;=`a!5~5$ zP7Wh(!?20RN`Xl*NRTPAucx1eJ!UxhsrpTwsVaApFbW=^(SIi-3)w3w@Od#f<30+~ zNdEx4<}ufuCAa#*-d63qwY6%eAWOv#gVsY~MIi0KDm;Z?>z_*&>UY63po*)`uKqQ?uX>tVEFL@`1c*5>O*K5&%~WgP zJlt|xxDt(0nF6NK9zS*EpR=0)7S3cO77lUz9Gj*(vp+Wq>L&bf3$qn!KH<_ zZi9xF8%tmhG>u-;Xpd(vR9>zgH+XJE@ZHtAFHn*4F7v_>kHVMiaCEPe7ibQ4Qu}ahR)9?ybYpr72i@=o9J}OZu78 zJb5y|RkH3Um9aS~;i_6ZUV@^Aq|?d^MNlBBM1LwkJ;&Q-v9UZ6T4px+ntR)4TXh(u zsR{}Jj7-5G5wZ?FG*(biv=sT_hfm6d4@;h!bBC(_uSe1>mx|#S9ZAFSOj3I6Zmvpd zDtb&dl1l2iWOyQ)W-A12!DEftya#>(cgK7!cLy(bHoi*K(?L4JNeW+yK{5o1+6>G^ z9c7tY+0Du=EyTFuf>1U}iGV#%Ob#T0M|%(aIywPNfM%~#nLZuNK^S&i&9%bz1dv7* z4}0iMhtbY^J@tu^NlR9@iXY!0v`!ZmtbIFgL!x_>0oLPuf6l3xkKyy_GM=3O z04Vi6g4D_nx+cikrYPG_2^N{peLl|#QT2tCDPAipkSBp;;n(|F_1i|N`f}cQj_to! z6YO7`b`Dzx$X{e~Fsw6(@O*Gpg zxN?$h*vK;vtGubE6m0D-7VbJjx)6yY0;L74fRp_MlL7`cyMLzb=5@f8p{CO?R$K>8 zJ7GGHuzAHSeN%P5tJJ4l@$R&)8y*yxwA7wm8`Qm2-c2nmRFE}Ybb(~6u97%}l~oL& z&rr`HRooYxC(LioXL9Yz(v%lgwUnS~LQ2$BLQ}9NP90e7CcAIC`@j8_%Wd+|vhQ%6 zI@Ps!%;N&Jc0A_S1JOER_8`#6>B zWL+S(>OzvBK?NYDNR5Vr*|u2DY|5E*10x9&7!e@wAWtT@@AT#B)6?&&*)dG->9;je z;y=m-8{%+H1ywntd`2dbV05U3JjJ+@J;`;t+WoJ_?Blb{&v7n)KBq0(Z@gG(OI`{J z3X~}U3V={lk`53sJ1dl#rcrZ~gxlV>uvI!>rCNdr@d6G9?N&JBvW7#2(RtE&_4r=N z@46>>OiVA?kS?o#3-TDTvo;T=;j5cKq^dwFaY-FTC87#?jL}+_TuzdQ4_pcM&fdDo zg;dn#>|o{`8y>^y=WXNNG8MFf%r<#?Sau#A_+^wh{zGyvEiUcbau);@zzYN@0o_0l zOb!?kuvK3|Zkz6w(}g&6aM_NkPc3;(8oz3z;=rF1TX8b2xSCSpi>cCETz{H2deLq5W19L0(_c>cs~Pnvi8|z5 zR+>x`7M6n#sjHSH#F44tc7i2V3bK_UfwH(!;y5_${{SVpxXx|Amb}W}ZDG`;m8MdN zD}tmX7)dxzG;?MyE}cqk(0jq+PND!hNStxu)v`|t`SMrLts+ZFM=+?3Sov}?>@I+i zvN$BLF23I#me-1)#y&W>g{p z;f&Fu^jX&G?@u19a*tD_j#^3ttd55gX;dPbD&z9i0#_REP{GJ>FTzM@)=3)GOL1Mt6%TxV8vZts%rpKpNBH3I6~a2vFb-(@LNCP@kvT%$w??F7*om zr+TmJy$q17RFHX(Emav8^42A0m83$gpgsg>3FOU^K8tSg3Lz;0E@~tM!ifZuNCF^Z zhT7s|?wrQalz>XmR@g`ck`Ij_0VI%h2;me5dN!9eWWKB66`7Y0ID2DQM6`_4H87ne zR1-vF1xe_f@FbrF50bWg*wPV z1~qC4*|tHEj~cZa%IZeQIfDSk8c8Z@ql&){nl@5mtfoF{xh~7FNC8%E`u4qtF+Sbk z9!iYB@SpRD9daO@okUhhwUs;FtqQ|X*m%YwI_4=KNt$r{YMz%9f_RK`1*rwCVjWeP zE;|JWQ~3+=_nL9CP^pnA_DG*z0+2D5E&{;YjS&90`iP_S#gAg$HmIY-aYw~xmlDIO zXhd%uRMn*Uv6+U{i2T51TMx6_UikyN`?Rgxgr8Ue$4XKRB zH7TgnnS_B{mesCJ#fLHvF5U5y-vZVxINp_&ZSN9fD^3uSBmgiK2j&~Y{NE~DZvdAX zcsSZpN&T9EN|Uc27Q$vHZ6mr1E^?;DpzBT-h9zp@H4(@w3lRn#wU_-ZRuI;8x9J;U z+NXA;9vN>CVMsO#Sx&T(qxhZM;3ZLk{t>82!h_qaU$hSB0s(bY_5s->-p1gFHPs$7L{Ix2)~TmiL| zfB_uL&d#%!Gm8?32r6M(WC#T$l_5hDfl2m_wSqhIm5jRKE+j{K3XVKe0LPvNk00P& z>vsp}yxGH`dGcA)FJfCU*ys6}gjBM_XsS0;J1Lkt5X>SD;3**(4n!TQ?&{ugtM*f= zQQaviNh(nLl4pPzj}ZeMvxQT1oi43R2*gOo5_$(rjuf}`XX;M~zhK}SGCWA=_K5;g&Z%mQc*%YKv( zOt3s-s{W=kY`7OuF^o1$YL73<(b8iWE(}oozA27Yz`{x#PO$7+95NXZk}YRz4Te*@ zyk^OyBG_y300L!5Q3gs<4g?GeltCoP@ZlsGJ-x(4x`0Hl(&=}OW%Nd`&a5|aZ2 z_=r>ro`N&BXw7+l5`uXt5`v04N_u+AY%&Z!X~Lmui7KR~U(++lcLtEW#fwQPC550p z`*-tKh;dRDQgtU$DMVn9k-*2?p@Ao=vdgo=8M9kRf`q9cD@aP#R3$}ZZ4>sS;sD2O z7=Ewh9HEQ!`dY|o%hyU)mWOYa%{0=zw#*xL;H2swwU3Rt7F#H^u%JlCr=t_IVe1(1 zsV6vWKFX5-sNg)#0(wUrYOp$Ufl=gq(~9)^mU_RL%b0@H&0ifrqo|HD2KGZH=4jI7 zHuZSg!|d{4%C)FUVFGUXK&G~i!)6cC`2 z1nHS2IO8Cs#|q8YuSeZ8&AE3l^@|$Jxqk)0>7`0)40f&u!lkN^4fPN5)M(LGm1a~2 z%MRL+py0Q6H=^R%Nw;Y(IIX3b?=aW`b)8N0pAksHqV4Y8TO7!_a<>|62nl*SsXIwf zK+@+xIzo;$PG8ihf1LjSSHGOc@}716Z^@fym$Ur0mG<`S_rEJ&nS1=h_FeCGb!^ch zXJk&voGS#sm;T?m?*vcZ3ez9bkGdlt*1!MI)B~e^2g3S;)oOeN;oh)bqGduHd6)MR z!&AA)Qag_hMpwCmjWSA3CjsUAsD7NaFE3A5zKwQp>Fzs}@!7EH?xr^z!m4||U%J4v zd&_WcH0*43H{=HL^q&yv;&}B?hTg$e$86Dd>c%8;_EXxDGfiAgIuT)Ey5x|3;J|3Q z>MyAr737TmZTv@BAT`>UF;-P6rFOr;4_jfvEv z0%L5b4=p`(V|kF>KWK}Vbm>ymjVju`AQdWh0Fp*Kb!@_bIzLZ6Ug`}nn+L+;6;Tly zA2|cLYoF2pEJ(4`cJ6JcSZr&i03FtBDG#I(vw{IH32}^@v1bC-{z!5zJY~#j| zv^@;ZM-qA(>}vwUr;M;BuNr|s*LedGnlk2M!DEX9kffDk6+o(F1y;e9?z1h_0xZJnd`BAoXv)9} zZNaNxD1(Qu3i5JSfG#C%LU1Y$2p;Y}{gl1Rc`H5SjB1-XWbDa-VAH~{BU82~`ZXP- zg-*kGXCLltM&7`kIY%CDPvwi^c;nUMaP+pG{gvC5WSp-w5Mwl{yQ*aj^>tDAZ>z7zzMJQIzkVGCb zJo+kcMXS#MRGbJ00wDPwJzZ4~@dfk)j&$oem>UMEz@)6gsViw|E2T-HmYKwB=TS6j zL8ua3OaZbGY&Uzn+jlNmk*Oq;;t_#RBiKj3fvC%PH+ihd1xy%Fz>Weofy67Pff$OR zbj9<}rVgb(YRL0RBoa!o)zh&eD!7Nev9{G z6Ym=c!m&dC04q!LZEz+BgFE@3I+2j_Z>!vly>jSzYJA;Djr`7ycB|ESV)7Xf z4JwYC&;TF&q+Qv06J>YT8>si>Z?R~Q5UvRaVM+dny*m#I0@+?KA#_^Ye{(-#vBRK$ zi`TFzH+Ud(t6TGiq8^tv@XtEP>AdMCEmM!GtZ7#;@Qw@ZMfLr^j2Ajl)2ji8J{ zqgE~zZlK}}5wqqGNIXXx+NY&C=b@jCkEcvuA?Bo{$(>`%l&UL5GcUXw-CSCLIo&M` zj7W7J^)r#7jO!R)x%Yf|JY@w7IV2; zMsn*N_M(CN-GoYVRBwc`Sl_>gqm2jMeMBC{y z<{v|aq=wdENdi;uHqaI;eLcLqXb^Z|QZVru9F7$4nd<&W0$Nlyd7Ab=;a_jp+l!Hf zIB2_Lb?W4*lVCNm(ECBRj~Ad*3ZR1$rVmxVUwE?Zux|G{i|b-MZN-2^SR5-hCf-c1 z2=|0QM`b!47VUobzkjEiCMltf9kcs9q2$Egs|L@woqj7NbvS7jh*s4<%u`h?p8n`` zB#l>huntMvvv?D5khp?DGqV#Wdb(>Gw}#*IcI#F;w2}zv;qR^1vy~U7p0fTGIg6~c zc_RR)#VPW{^fPUwfE25zr&>twQ?XfrU5u{8*;s3*1)2TT)?Iw7N1j^QbwGegQdE}? z2TYNHF(YJ83c)OwFR{P2Mq<^wY+qZtmX@?9Ly1~lKvbz96$cPxg-9WBjZ$CyCnwaN zRP@K`r#1A~tC%%LUd&xx#c_JPk&e~vY%ekl9-VO6aLO8xNb~4qjm&Ye0(540HwADA zS<6c9*tc9Ixsl=okv=0FJRlLpN$~*~)QP`4z^gXzJD^;2un+)ADQ!@sfTIznT%AA^ zB}YQaR8kaNGrnn;G4(pXEanPXs9KsyYAM=gQj)^5l9EP>bV$!-HfxJ^9FO;)i_526 z$L~-QWa$P5K0>mucJk4c<#vof1q?O_0tD$2U}1^dRQPf(3DvJ#oh;~)rF!~|V>RH= z5cZ8?!>ViInW-bc+DBz+HXGQJYXWW$v~FK*D%q(M=tTRf*@DV4`<09jaP~bO0zPz_DedsFt>x0VORROloOnlCsPiC3O)NaHJa+YgnF7jjBRI zvBcxhHsW^qa2Uw~xn*+U%N}uQNeECuz+e^zf=J;YB&($3Rr~9!)5b*gC(`V%(t7hG zIG$w9R5*1eAxdLuso<}Xjx!pwD+wuTu-GMy)9jK_#hDa>{qxG$%~03oQci~((nNwd z6V!B-5;}y8DV@yBT*__%wIW>(YDvW^nIp~=5>j{_m=Y<^AbtrrA4scY#PVJ%9cCPj zO)d|D)#0?Jn*>Oag41EQjFcoX-#Zgf&vt1~U^&Qlhc3xm45hV_l3~RxD90TzlMu|Fmrt5#aE#AG4M|a5 zHW`k;$}nAg*=g?Us1|D=xYGQWSD#pB43&4t3P_ZorBY*rY$u@9CuO^N&PMoc%SQqn zASuZTK$rzYjevPYP>)P~O7t_+H>f;Q)URKYG*HJ5e#X+gQ{~#KntF+9=$bqVT2@yA zd8y$HC193}mL6emcbt;Gy=|QBCCS+1ik&(@#3YhbA;3@CM3l)D^!%G*#!TyJ00e$n zfMGzXMIgdJ23vvmOa*vNSag4lm*JhAsBvtUoip|+mv9V5DJW{>n=Rt7)ce*6RSfaN zD$=}8L&U=JU2pD-a$L908E}ud1JX8+Fryt&>lKcdji*UUh$M6q0Q79f;pbH&)ciA` z-EGD3ezf{c%yb#1EVD7A&0ota>niK3C}*5QhUVJo@hB-JTAHG!I@puU+hu*lcXA)! z8%Eqgxn#*t-z1qxz&K=LsUR!~GYYL`jxE8Z!H&rSC(EifA36$ZI#o{UnU?{orAnG> ziIv_2k~o0(ocWv37+2b=ONIdc-A>UL4aX)!vi z3Z|C4&{R!HS4Aw8yQEm8@|`9oWflR|g8ia*C>)Y)GXSkARBhwY>+$wfRPq;O=y|k~ zQv?Xx)zLui6Pa-D!`s!yOZ8vrgBrv!-kN83IK5U4gw)YTT@)zgJBqaxiwyBVUj#Tt~m2FwDjzvnv!s2nmD3( zrHNmBdxVc@#<`Den`Q5~7jolaFiA?uf)q4>bmNXV40!CRdB=+ksG|~Br)UwUjyy5I z?C7n1>N=VDcVtW%@P3zNxG{?H8V1HQb!AI{Yz64>%qmol5Z%X_Bbx(#c_XIpbc8Rw zwn?9`HtK|Nl^jo`QAg*lxVjVmDM|8@enT41P3t2Ig9w`-W!(9IlOD zeFHT_6Qxst3EjR{7QM%^QMBIO+HE1UKWve*KQ8P5aN8hxnh)w$y-HrA{qn&lId+Y;7u?$WFUOzFw`R){<&hmIw^H`- zBT+IAB#;DbnogVNSBA2lAeRyW>JT`4DK!sVJuyb=X3rQ}o!S)3tGSg$&y>PbxsPJH zTwD?@!bf+*b&yC3Xu!rS52imX0jqv>IFLsl<;j6N4m$^4G=SVF{muhCOQ&zLjaN^)<>_}b`g+fv zoHG9aS8y3~E^(=*j*@&yrom}mo|>s@W(|lu2AUbnNERew1Gl&VCxJcm?ME(Z$;Gzg zueg@gr$Y_`wUOZk2>>M%f`~gY<3|~5E!~#bD{V5fs#X9K0Qi-LsF)l~VM2~Ok6}0m zsBAy2*+;AS5{DSdmGrf=zdxF3X_{DKiYOYHql8G2$0RWquyRGk^&oSd+l$&JSCHjl zo0cxk!_K_x{new2Y?l=Y0a5|bm;*?G0}^D`Rd3U3&ac|;E*b7Et=nn6ZzLFkr(|s* zYn2r%5=Ov~ky}LcSJf{>{dwgmx`ohe$2>`c%N0I2tw8Y9(N#|t@6o|pgM2d!?3UYY zZq3O)%KeP~=`Y&2L1IdRfY%EJDOLoeOb~G}K^tl;y2`FHmJ+9v;CQRLSTdD&WCf>z z3QnY$AV^RmMFE{%>9rPG%vBg(Er?d)ODm23Wlxqo%kFP-5TeooBm=h7$>Pxg(*lBVHeofgPRcf@K*&xZrQV+&x zuK8z$EI$t(rq^Wb-!&j)Q8G2N?sOuZrkU3qE=*hwi9>JAmKmqxRuCy(@_8tRTT($v)EOlLXb z%M5HovMnUkba0FKZ9uw^qrQWfue`-pF1ChKt3q5U8zi9$Fg);swz@C7nF1Nf?Jbma z>P4_xzoK4wC2I2k&!uV)KToQ&zeO?ZT6Pt+v~!Auk*Q@^V{)73g&>%lCc@ul;@fYo zyykyr*2Vt*;3rPCBmy9l1w}(p+A&Pe9u?Zo+uYLKor2e`Y__$W90(~;LQ_1>@2_er{8>3=@eO`Ne@ z+YI^it|RjGV-LbE_V9N4=;v0d#8C?dg{G&nkWT`cLqV+l<=YL=7z%^~(v=F4@=W<^ZJ}}r)Pk@IzQmXb7>N=woK84lu*`aY>(8d&Q@vE`CSmEu zO^Yn`PpA2Ikrcx!QZ^)BtQv?6YO;B;Qj`wswN?BaD*&^u@Mre-r$xo7Q=p<;m{NG4 zY8dU>Acb_$r!T!_Z!Im%rUJDD{iMtS4B&YARbG1crpSF3>+V--ishP(5vu7bDkqYg z5;T~{>5J`ldUQ-T5mO>6wZv>u?ll;(blG|50%iiRk&l#c zPTX*Wr~~C9n=q`)ka~-jE3h2)C#tTjf?8UN%rrNQG$3|h8gxTY27Q&&eP==W4W-srn7({&$U zY6;ZaQZ%qZC*CR`bhoJv6XHe+8zhaLUY&G=gEB2+JdX;=E4A!q3eR@F(!|(b=@$0e zgHWP4d&L~5F$=~d^iJPiVwH87%M+IhOo8Wy!J@A_@u&g5q&iJ)VQd8H~nrSO)>LPg}i_MOLSn5-Ch*KG{D*KMc_JD8l zEV0;8X^DbNXdMJ3#1KcmWK>~!y0%v?1%6Q=kWYn`3}QgRBW5so%#Iac{dekbR5EW_ zmJXdHjg+%q3xnod7MJ;R)kRMgWjg%LJu^s+AQ99ok-IZ)BEXvs3^QHN${T)Dp$Jk? zwCQ_H1rN6sW2DSZ$}PL>&n&uDl-e&$PlXQQF(CL(!>}Eciq0OZ`kR$1=y7~^A=2WM z_@r$UJK?p|SCSyCh8WT&j?9*}-(mNxZOD@~+-$i}8oB~zL2;$WQIZMilSNH-T<%<; zti4yv?f&K;1Z*KBpd|I<)rJ*^CUwg&bwe@?r+`xCJf8DX%~~c`6Vm|*_u`GDrxU9= z+7VjdT;JQsvhQ&$SRONI=^dAnJ@`eng3%wA?H2?rMg${jd|P`poE z(x$UCdXvjgz9&hT@jAF**L2uK6`StB8*EjO+?xs z9tz@ZRdmVf@Ts@}<05gT)*X&PUxUq$*YxW+(o@ni$0c1XVbNV<5;E_eFrr}*4pcV% zr*Rgy6P@(UE#fY$ToD+gr%~HFl6J)4Fr{eh!y?R_(sIo5)oK8QBq7}(ogjp)>QZ$G zm^k4xP53@D)9gi33Uiq-sTk-hGW3EmbtP(;vAxJ5yHdYw0Y<-?tCBw{fGo6an6!$2e@_iY{q{qNsiI(tFMNBqPO^o#r{dOn}`(PIp`ey*}V_oZSvcNv73rKqHd70E9( zY+Kn)itb&+fL`9{@a?EPZC#;c+#e^&wV#zLN7IJ;y|Tk^OYFzFW~7>YMv70LlD7?p z(wS9Sxiou?RTT=_`q=mEbk~TFXn8`h4lMaLsxoisr+yFoz^B&XuZ+`bMFXKPSBE1K z&33IO?wzOO-?4Y-{D}d;6nCBEb2cPSlT(d1WenXrgm z5izVk$swVVK{JEpGYgM)GUDU|pwqD7O1nbKXGlxO{mwonj+**Y-z5ptXb(r`etq0~ z>j2G}b!rx#d}fW{i1#lbV}IUOSniwo;0L=JQYJAC)7NyMjmYe0=x7vnwaMrN4+X9Vp4fXLN!rVr#&@B$eUg_A6 z@Tm9xg#&tc+*tnrsyKZA0Dx@w)KQCIwIO4dFj4~?epzLLaqh0Gv4QsYBm?Zf8UFxe zYgB)%ynoXEG_ZXg?;sMZyCLP?A8yK$lHd(lG?L@7)p>(xD~C=Li(CWxPjm*ZEcI)A!ssh=Z5TW6z8R`R1GxALh# zTM$rVn})qunjCk?U%PhFP%KHTGfZ0!!{Wpe= zwhTKFqs|FVBb>C$m&A^YP=t+8C_Y)x7QWz5Vh0PA+N+D7*)p7P)Zy9q`v;X(UrE-f zK~T@6Di*SFwbjP^U%lb{VLt$e$MySOlD2c}avA~GOOo=#Gc*jn2Kl4@@ z8z*PVxDslmidwuKVrQnfT6bhfSVt=+?ds0qN%u*)yQ%FxKuP?ugTci>_mXP%ze~AB zfNrybm1#_+31vVp_`p(#)RBgh2`3VuD+M1%`oT34VdtlrzIfE{K-5f@AX#kRFR8bM z`(IBUDjlh~HX)Dn%QR{}n73g+es=GoZRynXGt?xp7^%8#n~1Q~(Vw+)O8{W^4%-Wl zXOB1j$T`C^owm}cKFg$fpwDxU+o@m}`r zYZ6H(jjOaPk*q?wsR1lUMb+E&04 zyFfn8dkuK=?*0sR%RRVT4Z0+HNu4z3$;eJ_IO*1mA<)=!&5`azr@ipIBmC4=c3s8s%0X>!<5_=u$6a*xb3=Y}ME?L2U+Q12 zJUbxl#((0g-}Og6O;o7;271N`9^RQOVFiJgFjH!}k{F8HoAy3D@$CaM{+oa5L-C^) z`z7qb8(q6so3H$kE2Q)X>j;9A^!^QZ3${N>00fJuwOO)@SbQ(96Dzb#%pbiU>OjRT zS7m*d@E2$O+T$O0;ar>0f2r7G^6N4+67TW;veSXCrN7>T?_75sy__p|w4BAgub_Xp zin2Q??9`bJ-Jdru53k%mTJ%1Iy+zCVH_B9A@z>4G5E1T!skEBd_WZ%&8oN%+6^G^% z=*oWzRy!%|-58cGkNNjL-@nqcVIPN2sM=#Jn0{EnqI#3Md1cJX^Gvjp^NbB^*JaroEIyPdhWl^R12SI z1diRUpyQw0oW+0h5=Z%n{3-LfU6`Z(ZI7QdTp#`ET-)&8^)=d;4$2Un33tWan&917 zutW86pY6T+zU!5GB_D-c?tf-z`*NpM=BK~;r_Q6n_-T5g7ATo4SQWcs5}iD6Xbtu6 zekcCeU9bLPT>k)h{3@#5Zq3`-ldSpozXJ7eKZWP1x|yMxt@1m0AcXTOW|Sel*|wTO zyS#TDemuC|>(BX_d)g__}D% zhiab?JNVy;PW4>vHxCkjz8{CUQ_Ha2RE;Rf8z6sqx3BxIC#>+LO()@X>K>s-&Srd; zjoi4VtY#&2RV*n1Abz@WqrDePKk-A~>Hh!$NWUw&2>$?^6F=z_?Zw)3hw!B9G?0ko z&AB&WD|P-`SU@(m&;$a&0bmD*hZ$D!+^ha#9_aq)NBSMLQ~irh%!Q0Le$Bs|pBbk{ z{409F?=+d)D4`%-mkF&T06xgHV~BsW7XuS;{{Z@`w)-jH%x;MLG8=zZ+S&e^uu^^& zolwJR#XK3;Dn_GF69TOx?QY#;VjFh6M!n{If3Mtss;ls={%3ZTvm~}3?o9qQlBe*` z&xTq_@oeLkCzB4B&!ivK`N@WGtcxT?*x9Vi55U`jE4}QvKqI}lJwLZrKJR@Qv2(lW z`*Lex{^ZWjVW<^G?D|MZ zFTg+ZFt2apLLcTiIz*!@wjb^+{{Vwb4fswqPT!f$xB`Vf<9}1>*sZOo-zR$k-$U%; z|S8xnPz~O?o)$3VOQs-ao+#rux0+25G58y4>9T3xE4^9ab<4O2tRN=UY z#^}1Wi^E*Okklp*Os-L*F|=Wtp!Y&Yv*CUMFE`xXe|2YAkK=J?u8dgB9AgwV+D}SA z2i%(FSNL1tc+6;Vo~Gl~B_n8Kk#L+j3P#558kILt$6t2Z@U_ zvBL^P{r$tENzgWoFfew((S;PhUVfG{H>MttQ1yQ+^=CO^^S&iRgw!o&An>eI?G%O& zE$QY{?mF!Ot^%Dbc{%Q;_&u9GZOds-gs5qgB{6}S;j$tkqYTR5N($5x2#i1k!7zV> zK*VBZXV$BJ4uJa5%=D?6@Qk0Gu`lM(#Za}7!-$`ohyu_`X5Kv1Xvp&JO6@mW6Mjp{ z&MmE!L3OkeaRxS>vxiP3?VY5G20GQlsgtQuv&GS{4;C0;2FTzIV4KosuNu;T^xHhm zw_`A4S`o_j+!}l6dkgrRadLNt(1ZR`);(B{_n&mz^p&M5P#mOx?e=!h%EI@ zHWAYdEPn?i4~2OcF6WBWT4!V-BI~Lcjbr*ROJX=jldab_A6($xI3Z zq14rVe$N|e!liE}UXhFKfyM%{kMk)&$u3UB6VWP8AMaHnU&BxF1*n2ranpQoMJCl~ z&1E8^B75l@Mrum3qx-;ZuxpjGaVmGSEJS|UAL$lM@gV7$BMrMSGAfQ_7pj;_ztg58 zqik)*;YF{lJr(PBM01mL{{Yl38DEFunB^K`0+zn9XEgx>!%bHwmn4fb!SAA%C6H;N z@Lyw^v6(mC+NcoPf=Nn9iGorj4Ix4f7#}(zdd2%UJF9@N+9gB+sR~j-2~mj(D3US6 zPeor3;lb4!97oYMP^HEv6%%0+;&>>9BYCDjEl|x6NZZ_x01cL-tpft=nFuD?;TkK^j&^fR!YIoPA7=6;zlnLvTlqexKr)q{kA% zpUW`KPZL2sB*e8e>JY4qjJHBd8!-30Igh!HZ1tOg-s}Xd1p*3!f`A%^G6CWsVm5K9 zlPTPLYt446b$#P1f(lYlrqzlU0u)k2q~c(Vcu}wPt?4(aU3cpTOu840Wg!&?R?pR# z{O~D-8SpA93PDp;R#UUfooDd>y_yKX^kX;||F zC`YPmN!aqi6LJt=%#vR2rNJ{2>s*Y4!!w|S(`@L)dc`y zMsV6rCVG-i9S3E74&~X3b4zyaTP7WC4hUBTBr6V$xY2&=wizWRX~OaJmPx*P7KyIc z3A02BVhg(f!4M!*KpF`hDH z&k8`(#`1!@TR5*$8 zY%(aPImm3ck%Mh~(q3%ir9%*UQmv^wVM!o~+d^!fqcXgbiuk%0(eYa%t2FD8A}Y`O z%qg0zQZ4@g!mx$^01A%W$*=Zu-n}|MnOum%bv6~|R2tPhW@{CH=w0_V7s<&!KrEL2wg5(MkHJUc@1WJ)tYCX zEBlwnf*`daA6enWryHG?PqPX%`H}LqwsEx|NH23jx)Sq#g53jr;iu z@J+z)*a83xY-x2M3?)g@yaxqG6I{ponB3%LcP!?X=m|rkLiC6MXaH;*H6*4##8xy@ ze+RrqlMehzI$?w2GHs>I6=ARJX~|D-L~c5%(qK3x9PT8y1_u! zBg;rW?V`EOyO&DKvm0mAwJ$b(iwEE;OT#@hVgeh^jYLMu8q9>DUi(GuV0#Yy`6CJo z$AQPA1B~?bkzZP-2*aR3=hzKms%a)iNn}zI!Zmvxw>D-L?6%U~i*dw4b`Ln?)#vi6 z6%+1(_;a?oRk{er$;23KUChTr?)Zz^{yKP%tC~Q^#Cm={-mfZUM+qN}9OF%MMH%wl z*aCLyx-*XZp8Br3Xf^J5ttvSD_70)bNfagsKaSa`(=du5PS!gh0p*yH80yiTD$&WPdF z@$0LW{0w@=I&14u`bmn)Bckd)6H$b+g2jG*oqm4}khg~CjpJW~_t%)?+SXDttcCq4 zDpPRcBM2!Xa2sGu`J5{j`%=q$`y|~DxrL=i{6%ZPrYt6gakrP8%UAz#g%W3~L8&5)?7v{qaclidD-^j&s`M1#BOAL_=M>oClArk$zUo}}LY0A~n|2`Bw!7hkJ| zms!8&TT%*%2WR;^DUyG_Pl-Je4AaO`5JIIt>ZJRQ28)+l`XBy(dMljz6I%-(>t+#M zheS&KinmSlZ*!&6rDG!eZ*z0iZvJm=blJrYq!Bw(v!QAA1kk?T{8&1RiT>uGqmS_a z02lkoHS@#9u*^#buc*Lrs%NFdF!^Ptsf4YhTA0a>MP)jTtffu)^n5Tl91pTN*ZRqc9t+G)WT}!fd(Aa!0z}|Gmu$74;6siavVtRq0j_2P7 z)V5Wm6p-R1D8Tzy5wwvJfdh>Q7@ieN3bAxR@W{)t5@Y4VE~-Z6_oXZVzN>5K4+Bj+ zRnr7*B{-;U;eun=uB4SVmX)zGg%scyf)|JwoK~(U6z$nped|{c%)YWe2W%&;*;1-_ zb528sHN_;Plgpi>p$kcgMkQa;B27)P+$$}>x4bkWjIFl2)_cV32qm~zi6d4hSqB1B z0w-k6aT|N`w>M)pyRvCT30$oOCJ92kdO_e1i6%G*t!z34jMC-oGY!n}$YYlT#MOg& zBIy?3<$+&#-586HqsM~1<6zw_Z4n{H`gWLz=-McKxYvQ3Hr{ejIA* z@T|+3>hn!BxL#bUub}hMq+Cu|=p!+<(h8%QCAE&?Lf`kh^8=o>X$+_>2=4{Ix*xdA0g9fX7PFJXvX)y&KCoD!nkwRjq z18S=GZp4sySl)YaWb)c*hQgEHq&5OUTYq>lDpsUzBfVfv=j_~&l!X-ogcMAq4z%#%D$j82^OO3gkh(KXhhufLIM|tT{xyYQr_ZUV z!E4=WC~*3U=VYOdK^cmGJQ@FNG^-5yPojXy=?2si~2h8%={iRdyCBP>4=1ZaM?|7SAH#SYM+LIw&=BEJ|i9v{wu$_mZ zqMVBM(K>Sh4+vSD)K7)2Dg z9u*|W8mAq^pprurm85Nt3Z{(-f;iS`SjcX$)494bi#=W7MzatMsogR=wBaEsIINgS zRsu#9o2^(K?Yj$YB}q;tYVd?9Q7R&If=7i361^j6l54)O`b*0BvI%;}j^x3e^Fmj( zRy6bClew>H6r}AmGfvXIN`hKB5=J4kDPwK}vi1%GAnE@ATN18%I6$m|s+v{Z28;}XFLpB|WShN# zAXus5n_E+ozHYMekfY%#P%y2SP9_z=VgbfQMb|B(H)FWH3Mq|2Ng`9%z)E(H4xa@;%Rfh>q{P)B9-Et4@tOXWfkOum91YFGv|950@-r`Odfk z_{`FXATYJWP!bkFP`V2>-M46j25)qpLia!`4uMm(ngK~yN%v5boN&54N}gHq9nQ@u zr&**Y?F|Kp2Xu%B6n>%6wAxgkUM-x6?*{ZVn<4itEB}PcuN?8HFYZ7gC@zDJ|n2Ki_ z#YL_#6es5z>KqTGxK3N9PxP$CRVFJ{U;$ccV$}3-_T6T4B!_ju_ekOkRE4^w9W;XrQ zxdQ#iw%l&|`|_bj`XH0?k6KxjWg_$?Mm$Oh1BTp5^x0d6`g_3gy=PVWchFiXXNN6d zAmUhqG)@*A7casqs-9OW0*7eTPJx)UwdNzJmsD1$l^H)1S!m+Y(9oU&2c`f~H^|?M zCQ<4~Ub=Z|(I_RG37Hl#RZ0z(#zYs~Ig#Ub zmgSlsNYuF2q>Z9+)Si41-5Dmn*bbakB(_2s=R>LE=7jwEh*DdL{VX`d^Zgnh3I& zSTclaF={v^2~kOP*wy%JpL$vfgK!DIl24T&+Ck)NduZjWpPFbTPk$KLE*eaqw{Lik ziSV2O(m|<_kc`;{#CTLNB5?PfI9eVaE9a@+PZ=D#&;VZC}tI4LR{Qly+g^Z3#$EYaMo8*&Q1 z?V>RvBp#83@S@@AwUS_1IDW09yq|%-}udt*wXe>_+lBpCMa6zjV{5ASfllr0S*CN#56%%4Oc2U9G zG-7g8Mr<)Uc*+=|xz?R(B`btB`)ftnpB3P`m{fvG!?hE)?h#0Am#~!@QLpu2#bP zkASwi@X51zVMl;}SFru&U!!wBq2jNu=nvE`xaYhKbs^ z{JOP`oP4SlkkK;!p)X%AIkMv8UIWI2Z`S&!_<$A0tzY@i=^(A9XhvPLB6!OP{ z&p=};$pWzfi|)3d{hmo#jmuYSWT5LP9vR0-RvsL9$-{)lOvC%Jk&6qvo14bcB|x^I z4y6#42~e1kI4pvoFa!e?dtR`8K6JY&{t>+l^eqe$OId?ud>a|3ucj*vRVE^|%TTp+ zGY!5)OqH@o$il>E4utS>n+DZwd3AI&=^>_oz@^k|P>qEN5kKD%Sg`JF_3nR{Tjk%h z(uZzeUjoDa5Z_o?I-rl>LEBUZg>^4CXL?L~roC~ghJL1Hd@7Enin^R^8G?vEmj!$R zA#qR{yt>$j*_1O8V}3#espAe}sF~^O^XdKd(LVGo1rY@!4za+Fj)FK+5Ac!clznpi zRde;>#As=vWZk+06v3Gttj(pn4nLAvo6FRX=<0Gh(jh*6 zB@8xUQ7-%6e<{eWUX7_sQVu`1SV{6BAz1O6-X^1{c$}DhUr)2F;-bEaCYlO~R29Uq z`Z|U2(YrS?O3KwKcR?FQ&paf0pGh1Du1H?qt=oMIB$3DZNf>~xlLK!U zJVBs$(#J}=iJLm*mhx6$r-n?SmN1N08Nut|s3KU6Ykw?)lBS+O7#dY-g99V5^2ky{ zE})I(U*s;5fN*H)NG3|WAOw*d0>0z4K!8D+197r{=gB)|NGVYmXavA|p zHqDAI%-e%$&%Cnw?=a0S<>HigiUE?R5~Q};QrcF~NeBs3fl6G-RPe5(qj&6`%Ue~$ zN^xM294atLS(LZ}rbA!^VS&W$HLibE{{RsVyk}FKaO?}JT~_%_WKphAIF@y0YC9X^ zON=c!QCufWtUgzkvD|Lm!|QCm_F8i3Z7D-n=5+V4=LY+&N`z_JsU9q7xbF5y(v+qx zKt2-5R1$>@R8=JEllI2UD5vIbs%0E%w;hWNhc!h(Q$a#9^cDH4YN3QzMq)M96>DOZ z@YFb$%Zzz#7?69+S5@e-xhZeGQz|KOMc>(fbU~dV6aCF;1Zq~p2d1QzW=K+&Q{I45 z0wvSnSlXkHi6rb8`fUu=okhqqSK@6=g5xnoRe;4sK^e@lyHaDQv6*p+o5~+IOCyO& z(Hks&YN(Lx*3H;lB`F2Qj5<`PW&)WrrKE{E76eP5#Rm#btJaiB(7apHKWK1w{y2I; z{)QvUa7xdcdVek>4NYcSsHuWXyZpJ9Ov72VaiW$u@<|$tMi_2fJ%NO3rH+S-{{SNS zNdeS@-s%UrPxmkQ$prn~F74wK@^5XDuuDoKxzI;^p)Wy)fdc>x9_wZiH4!scPCjP| znrxjFSC@m&hgQQbGhKW`79v2Ifp#Auop4C!zLf}liz5RgHPYCaK}GA0WySFXi!T^=bG z2D3$qLs4B=kmIiJA&yGJ8?2OV5OiIT5Ew?Jf?2t>*u407CGwu|g4qZ`EC2+AVG9a^ zbt`70&?>3DZr{2KWD?O(bSX+5@tgwFwX%(xMkkL{i~~7kjISmHD)N>Sipzpx6Ia$r zShY|5?kP$bs4+;=RYjzPDOB>d$?qNJ_Tq%s!oHz^JjV{q^pW3bqVGtl`BmH$IFmU??D{lD+0Cz3m?|F`+BmOdR z#jk$Ox#j(5!|HI_swgtn2^f5QV}hbOCi7z!*tjHeG^BqhCf}eVcle~^ACyv76kT)s zmv^U7gT%Z1hBK;NX-gN(pVHVhTy|909L&hL1mGjP;%R zb<_;Kf#A5dD^W!*B}s>2^sz-k@gSZg!KJ4xv~owt>Cu3$*wLeuNY~k9PZS#gbxTFBq@b|3K#rDNL&%X z(=A?a&YAZc#c+sl%pNN2`TV;KsEU^fq@|5s2aHpEh(#iS-H;jPk8bh2zq-xEUzTGn zZ7wNpXt&njDsf6A8P%`;I0X0-b{GPXvhCjR-2PdXn=ajyG7yHsWkLc%0G$dkD^QsL zk_Q1VtGPSW_evWW#5%K=X|RZKswK*GRZwBLd83^umLjpj@F@{gg^o7)n8HaQ_qQF* zaBfY1m1iB=Y@Jfd7H$%fwd(~_Gpp`Ik~A4gYDnHK-p@B-Dt9qqEv43y$y!p{n^Fim zF-avWAtn?;RVg9?OaOg)snm%o+E>JBl6s81xlPE!X)M@KQ5dI@Je|I7zz57*&pHzK z)Q(0~Zh-+Rfa!nlSNB3>kY;qx@O`~eQJOQmu&r8?sI&Qh?r8qy5u}2c)fj7yU2{Ul zP|uj>@@l+a7{sfo7cAu}+y@Arj|HW!iaJ_`@)HfjnWF*T+N5P#z`?6D*2KIbZ6An(*YEe*ESCr zO#>bkZk6I}bBl)>03iT0K*Ph(0K)}Jy3ZJz%&ggkoz<{m^=ezQbEx8=;>v(JzU)z@ zB|8WawkXqnC?AOjs*I!S^Qk=y>8@^@4$4_m5vRiF>0qOx-m}utL@Hzx%?ru7rFXby z_eO(3ZcW?6yw~|{!jo+2KoB4Vkss-25((SYvauU4N?b@;7@mXE!=UnNwR3N-k5l=N z{SO+?7?hHsE?P+FA88-DL~tnYs-GU(>A>BuXxZ}^qUAt!4KvrX+fTo0mkdI_KA3x{ z3xs;C^&5cWG`WWY&eiZ&(aa{Ns7Rm<41(ny7{+#uP3|=Wi*U)_)3fK2P`jrJPSGPD zcHW3IovR?x)RB)&Z0C&mQlBw;%=LesGL|XRyv@{HYY@Qk_8-is9-bwqn#>t@i0Omf zNWGM)xC{v44aaC1tLQ0P<_L+@HAhjO516Cwot3tM81H)~t-ys7D`T|W~IT!HAOedK^&q3Pg0K^Ol%gNO{EUX z!*%S<+klJh`^>LNQ;(G#aZ{Md!}>>H;}}4xRju8&SkktVM~4jtFxi9whXG9eIn3Qf z$rxi`I87!i9vq7tVwh1?7|dz3Di!jNxGXJW`=hwzIIPm;l$5afMxs=7I1?&6P6`;F zJvBNZ$1chZ+DqNi65D;^O0+hgwY12=3H}knjJHENV~~3F)r>#W?G{bKvi$kEW{$5A ztHb0oED*sY;#p}NM$L1(?34#}_2g>qZJA|AFPqzl1b9;6f=St^6YrWEAmy%-7h!C; zNmq%a$%x>g5=s0j+VS7RSE-rf2U;9!saQ(ZBqEhDXfkvOi3&u+qQc{&YL%E7DdVM$ z0tWZhhV@|F4CTAt<*JK}ms6|m9qRO}86<%ilZoJXf^nwSt8^-VD$v3J(vk;=s6aSO z;XD%w*dm6EPtbQ&u^y!2-A&5gB-juxN$G*R+#P$hFZd}apQ7MwjKNY zc#K?QB`5t+&+zEgJ*7U^+ih+0;YwQSs-C z%?v|${{W7;^pzN`FSSg~#FXf1A~vQ$9z-Tbq#Ej*@Sf?^arr;z7crGvYPfz9zx4>6 zPlp**%O@V_f2LpfRAQdi^H%mDk?2RkAX1*2@OJ6c@hkrTUh`;-w(+(cHEvI07(@1N z?9%)*N!N&IN0N`T#qXl0duz=>A{ZWr-%{#72!4{&MkcAxdCZkvmld=~cHa92*gIda z1Dac!WAIB{i^nyef1iD!sDcs6qJ}gC!aITRV4?QX&{pqr!m0N z?ekg`G~^+Ws4Q03u=a5hu21}Jzx1P=DO(+=W^Ao)p)7?t0cr_Us3+~zbz>4@c1ex3 zhL`Zg=yfaxHO$$)k$-iuSU-o#>94bdjz6kNZNK!iY_8PvRUh@KJanJ%tE#`li=gyq zi4G^3Sy4`{i?6-^03gCUo(1l%+(s!%JoE$ZrEPYbnykrEHva%X{{V$Sl}DgniP6rG zLsyT441Le$=fs}p$^P!#fiL&k{>|M544K*cKb-BM(|w_4YZ6wUJsQ(nxG&XJl`+$W$Z~!39#gc`N#Xc1|y?LgXf0> zjvjOiS76x7~j7&~DX(^d~3i@kF2h8F4yt1y5xyNdBKG9$` z`08)306B(lb7LW}f&O4KLMtu&&J-|w0mOG{{Ar&B^egF}jiqsfVigkAZSxvjW~uju zIs!@T57EMwbKCpSB%vT|0kn;~Owp6u`I{ZD2puR+6eQsvhwr5-=%RwVCrLWO0Z?&j z(YITGyJQv@VxAxq}`D>(9+(I(BGp#$H?iP4(w0wJ#*gLX?l_m1?VAI0q;MJ z1{c~Ef5!RY{*(L)S4-$a(ri!{s_9M$u>c!<(NzT=&w5F~1BS_LjfwXk#)GQu7dm&t z{K50o6p8mDn`88M=)_I(^!+-?=1_mhgB!QULsDA&W(hk4`Tn%$_Rl;5P37El_=oxm ziGP^h>E2B$VYByIr29?#sukZDOG57fdK*Pn5~|0G2>$zj_h@He3dP z4ada(hwIaU^r__>RDEfB^C#3XdE@@<=Fjxh{{V(``zfsC{{UAoGz;3;4jepfVfqf- zH( zzozHgQR-?CO)p6_FP-p&b&}|cs zd|%y;HNS}Ly}xG=K82`##~NIOv=7^}q@Tx=L5+NP{as_h6U!rB;4R7civev$ynwS- z9C2|Z#>`C)7%a4qUD2r*GHwyeZ?g=P~)bQk}X{wZ8*P&ywQ~!_>=c>TJlGV zWg=^C_H&$CVyiN*@e6AA1y8z#SH=cEgQjE4xQuv?9V={xs+O&0ibHGrvPQ%M@HRft z$fEwiY^a3@^W#B8vH52UE})@cNlK7Xq2>q&*JUIcTF9{i(a8J2wac6L@i+Q-4NGO! zXzQUE2~sfvJgILD9c0lK61i*M>c?G2$6u$DEw)+!!*5qU`V1+=q{I(rKFSd3D5eN5 z?CWcdNwvqs=m#aMdmse^+;ntBI>$pgt(HT$0xk(ZMbEGf2vcdMkQYJWQsshO;zn;} ztabW9{+=yUG@UCOD?D+#D2caQ>Go;I!&8MaNEnKf9UC;7=oiF~zw+(HNn;vmPC%|1 zqZG>d4-7cBQ1N;U0+DP?xSebigKvANoz%65upfsP1~8MepKT|$?=P34-3xI?U~MX1 zJ!K$)>+3}aJN_fSi1HNe44K8T>WINUUI~ZKRJI-lc?2-`@eX*nG@Ym6_{B>$9i8Wy zh?KG2j+a)HA3Z77uV@rqaX-de)8#udW!#ULYR2*el@(MJ+r5WkiL8DX)0$FS8z zKEQawTWwegpLfcdzwBc+v_V@BGW358EwX%x);+K~>d5d6&y>22lW24APH{?XYX`*> z%%rWPeet@fw19#GqsHFsk-CRQxMdtl`voK6YA}G5R);7XtbpqhE)Q0axs66GwKAMId3Mkjz;?EF2SW07bRG$AENOnf0M+oDu0u z8XP#Pm9YlnL#>C?>?eaJEr6iwuT4)BH)|#Lcmdn!9v2)k{J%vb?`s5@c{`K~oh&~) zpKlsA+$q$(6~xdT+qR8%-{JIezT&Ok)@phw8qCAEKSwNn>MLg|>U^~uq;M{%KgRa#2aV0R*lVVX-?KrrBpB;7~pbUp)w_sKw;O#G*DJPLj|vQ!>c5AS*W0btd5ORGS275=_MG z+10iQ9Wk>JSre7+D>v+-;m4eXq$@~3ZYLd!Nm%kQXN4m&XX6*2X)!pdx}lMSyTscb#w?ZKMX#)8cgd&GoQ~M@b3)0D->(cR6y= zI+8?fkslbEBU^VCvEH`gf6XV}oj`kOYg2+tOzQP86fC-K1w#SszJz>70qV3!IFD^S zi=eRyGmj1)f30==tQo*X2VFGw>)Yw}^TyCl0=?hiN?7oH!*H?NVS9J`_;%f$5}TN; z^*BK=65alfuJ-nE+lx6#rcrT?Bjm!1uFV15NGDtVz8`lY_bmp_x)Fv@n06s2jECuEbddieBEO*x`koj_~{h%=-E z{0E3T3Bb^wQTX8gACTP>6wFeyU+mxyVgS9x<{lg>PiOgp@zRmzwET@#S>tH^0>8ng z*uNaFL6BC(Q4jU1Zz+|%+z4x84Tb70^!>+*{{XNzsThPFpBj0_k-5CA=_xaakF{KX z&8ngFC+pv!K9YLf)?Cw$;n?kNP0#hFvj&ESf;Oy-rF8S6)j;y7h=^t&g(k#X_fOJ`T;Arv{^sxcL-^HEej#49GWV!{qxAm(todXmN##Azm~N9yN)#S9nwlrtwbp@ zB*B>3AKwgWG|l&e^A5Fe$XXQ9R22xpQ6Nl-IL}d_pU~}Zs9dXtXR41+HJFAMCIa-8 zwUAIs7@8WibPXjNgXcvX#(nUmlfy&FqgG^}@~aY}5{P$62M};ppW-pJX)(0LAl>;w zU1>OJSWq9{sB|5oM%o&&KT&_pg;sCOSRt1jjxiEc!0$4=fkxDpI)-_oX&3__xl{14 z;qFbmEaz8kTVFVvV6~+yc!d-;f?-Y+i6kd!(n&oLLs##M4XMuTtw|UJ{{Ru-oOVwd zHb3y5F0o?R=U#ft>BFdVF_%5y=M*qZ7%{1)c7lDEH?qMfu(G|OFKupS*Y0;RgPHWE(>T#_kH8cE_WquK&@#7EtxVW5wL;M zHqS;C(N54abQ?ql6r?`3)ul+l_e4sPqs1!O8$rZY%Rhz>NHaYrN~wKJ^@|RZ3eP#? z1HmACJ?&}?E}kPL94M-xQcA74Q|*BP7Pi;pZLPy<>nT}+ zI%5oc>S){*3zfZOtWx`GOm&o$gXiL(O4mQ|q|X?RWc0BH9f*jOWh_>zflP^V(9{u9 zs#I9sHj$KG_P>WP_kJx>#$Z&R^~5Dd&+VU31rcuRg;v1|+JzLKkGRckC-{D6c%BSX zD9uoj%#$P1qdnS9(e5R5?lxY-LBS5<-3DA+WPntmq#dUWW3LIMd*NtqY!pBzM~I$* zA}6YF^{ssW022I$dQ0o`s8}2*@KWQIw7G_jV_>Qy#c9%cHlFuc!`$CZY&n(5DCIluFL+O;IgnbyL;+|)q-0C^&-kFA(`R^$mQ5J+lp+MzN9 z0>}xq#G_j&AcNv>pgaX+F86mjaMHBF>-6b896DmBZR)o!+IN_e*#`mWNjw1dQGbQJ z*cswQK420^-Y;zk1GyLOE!{E`ULVDP|oR8wl~ipY)g6A?3kDmg;;B|?<}x1(sF ziyNNjQSIeVgkUgM_maULBD-{gO5o`^z`co&XuIaM3Px!k}7Dw zM(Oqq!zpDtsBx*W7XY63@EmvmK_?J)^yAg>t4SD8@#)8|6nzfrOJh0D2|14@=1eaU z%el7(jfgmg35g(%x(KCfd37-jwG_{wN{FLt>A}wJXK(J+^H=t&((4W-XeVKfppWRR zN>1Di#uXIr*6K69*<+RuKqth7M1(k>wO&}1sBuXkLBt4M1@yP+f6#BJ%rDjMWa|bO z)La`WVlm^H8!qKhJL7o6#9CZ8`pWY}l-YJDWZCnvNYhlYNn?g4LX)1)_JQ?BVV-14 zv9e)i;^~5iO2JEQYfhDk#JF)*kckteT7WTJQr(`w^V|HxySYc@*=f%ctAimXd;ouR zkvdcco{|m}Oz|0im`hPvSQRQN3(Qees-HGPBZcl1AvXir@#hSi8XygW3GxsprgnMt zSI~MuNYXd}Jvqjjt3S$JNMOt^HZa$AfG>ei2YnCU#c0|3{QCX1xsmJd_|LkbnO>FN zpoHCaRxPfkFmej!wO1O1Ec5X`s}PR?sgId+)*qxG5dDX-XTYAbiMDdE^x!Ik4NL> z@T97d1RvkSt~g`ysLl*i{JbY;nB%q7T&>H4YXukY<9i)=@bL*e2cI3Dbd0M>j&^P6 zj!rcDlyThGkTX>VamaP`7(Oe7)InQ^)zeMo&jj$k=%k8N_k%2h-M8F(ai=uAl9hm< zWGF@i9kM*O(Ph<|F3_f3NKzCCDIgG1a4G8)YB5j5L)UI&q^-hnj<4pKVy%iuCW$dg zkh-`lB9fa~ZVA59G`P6nJ)POhZ5EdrwPh+vkf7Q@9z+g$=m6g4d|tZV76bI4SPy4yFX6#aVWMzC2|Wo<;X-8P7Kz%@L`=#@ zr=>SPRC=Vd2_(%p$~0EB@k-Ll;D8$9V`4?Vi;g%gnj!)aLH_kI9UCjk$?a4Aw2hJW zgUs=sk;aCpJ#%{6F0B_=GkQ#{tAFbaXdo!i?h@(XFMbh!Aj{4s-JY55ku&U>8+vFo zz1Yj91+!frVs>@m$7K{OQx&VmaT=_19jcbDs}U^dhDj0y^772b7c-F^BAH@0!T^Jq<}yFu=u3va^yT;xmgoQ%C#aD!h;en7xMH#C2Lx-Ua?#3jJM)}al2pg4| zKn3NINF>}iHWnk1J8F*?Ob|3<(0XAY@cUyL%6ouRbdqodCL9JM5O4#;p~nI$-@gXj z=YeMw>QANI-0{8}nXq$P9V5x+Z7=a?{dOc_jjPoU_o zYj)q25H0gW5487A2?i$=$s2Y->peBD(doW7(H^qr&VXh`+gX=u>S+Do)@6cQD_H*k ziY8JC@Yj;oY@+jRK136=aRiUV8pb`ySPtA<4T?xwf6YA~;;U_3Z%OlE&7CB{F?rfY zs}UGyD8Q2}B*xo^U^du`8=l4IB@f5^PNEYQfm^Z!63>QrU#2+6u4ZN?jI`9%TOR=g#j=P0G({=RxQ51ChsKobs*O+4=QysZ~ZEn!JQ{>IF>cEs!uP(d-OI%^-Z48hCA+dA5GsYxSKiH7lwQT$RC2ot7= zAFdpiTY%$F)RX>@Ger`$Re6bFNh_0NGo>t19g(k=11;~rRwQ#EJ3qcn$_1v*<#3cq zQ4N_=O4M;aDF>qgP}gdiYVC*T&OQ1eYmFnkOeacGKG{SZXI3U^$ngwDi!}5v2FsWl zB(q_dB~4xzK^%!s39qK4QHRv+LW9gnTix+4Ev@;DO(jfUEpCzmoe6Pqsa@KZd&J{7 z6pVTkvZnBqF3qr%g+oN46QmUc4JQc3W6bTLE7xbOJj>U=Mp%DF@hVxVFnlV54W`82 zX^>W9xXnCbYUmTo4he!n7*nYCukW{q4tGB&8D?ac8jVD+NdT0z(IhsbF$o~Xy}cC) z=b3UF%idDKQi?#0gsK5j5CqD>#EqOV6|epg(%cUnG;!vfX=A9ag<2{~HCUQ9b9jwR z)e2&YFi1B8+5qf%n%6nojB4&%kdp;Vk_aDmgrw?G=6F^KF=UqrO4W+E3?g<(I00K2 z`f=(86@y5xfK^M1V03Ur4P{jYJw(iygfyx1LSHr3R*lha9U`$hskWTvu5nq zZ=HtbH~G9ho!rLFH@~(ijo7x~al28kZrn3NBq|rsI7ZAd>l-GgB&i@uPZ{>~byU39 zLzZz|J@FjXNex@m`HZr>G9=M?dT$dcSucBRvDDj!$RUwFd?^jkOSq^^aXWpxYn};$ zW-OhSmlBU2MS^JFs}PeCgij1eMcPR!gQT&jKva^Y)tjk0RQTlI)w){foXLV==#5(LJ=twrQRaCIZ+6N7BX^G_ zYfEdpc1xkO6#$|;!k`j%91@cR?1E$hXB~j6mQH%=EW5xpDL-Zc#&6=M4U1y!^T}%<1Dh zbxz6mSO3zftc#ZGvW8XuRffhW>6VN{AlxIUDkCxP)vk>4Ztbm)W*QhlWGJ6ASpwgI zF-Z(&FCwBk8s>_Yq(EdoVv-DDg2x;WVuY~-h5!a6sVHs4N=(+tq>VOCk22QB9P!i6 zk-}1CVyK0b-ZADmxtDI1KIwy?hnl*n+^3UvrHiq4dO$a4iQ50~0#sU-J2#8xXR zk`CR6XkDy*!bajoyMg3wm|KSD4j6v_0FTOzT2_((+0P=Huxz7%=bRTY)8Q3^4md_1 zRZ`O}naeCk%SMb1r_FD4zwQ&X9}WUtyK=?Gi;2`0w5B+H!g1Sx#1G;ao|=?5dnNvU zr%;9H?wVV(w4Eaa$M?qx;qIaZ)2vr8^!XbuWARIe)71o-e8ai~BoZEI$Yl*~=GOT0 zF>Y9H==X_*5h6z4Dfv`AWtgul{eyu>2N+hsdPq2I<4!$b%Uwjwl=S%46-1T!eu)f` z$3rQT$z~UlNRsS)quhX5K{^4&mM%8d(n5|BN5`&;Go(LqpyGT@r|k(d5-}ijA6}|1 z*>5jPoN=lgw}MR{&0=*CQi8{8LS=BQ?1#cNxg;M0px~`ecXFe!3G@B+9Wc-4RuGel zh#ph4`c(d^->0NYD_d~(gM;jlQFQS(ugOkcVl zby|MW;ZOLfzXkJ?l^W^XswrRyI`Spn$4JuH z{ya~Tc6-fE8=8BFv`rJAK=t;{|~P{5GPQJR)99w&}X z7UAWrjrs@~l-S>CvD1-dm7nKcMYInQ0Q7)Nk~*M4o|=;GUkxR0oI)j0FbrS^o})b& z3e~4GS6AYBmZu%7luIRB$ve!ew6n7k#iISj4fckh_Zl8_0hETo3BUmYI03WSSc7ok zb!9}!IFtH(YQ=pedhyJCGs!rAr>?bERbo9mq^N3)3P*o2vbA)w29l^-T5s!Y>eTOhhxMH9kDz_^uUqCRy1AO1qC#*v=Osp?HK#T8?K?{ z+_CCcDIT?SFr^+p0;$C?^o>=fkY9K)YDC@H!uzrt$sLJh;4a9oCs*a}WT*H{;0Fjj z90w7w^w3JdOUuZ&bjbb{9*%?6(Zp<`y?|r%wW`!*nwqjL$vR0Hh{nL`Kp>9`Uia6B z*DMsBTSo{pH6b9;h3Pj{x|`7MrD0uY=@v5BMr6PxStu(N2fZ6=^wkJG+39CntkKDR z!{Px1Yf4w)P?0m_NAV7VI!6LV!bJ#eZdYiq<9kLJ>?4X#NIx7#BDO=!m3hd`a|j&_KkdPiHl_;kle*{)XpOrN`W&iRGd+>53_E(HG3xP)Aw zaRPiUx59Cf0VHWPE(AB7wW*>~p|nmZBy3UQKcb!EUW zI$Y{_aE4UOC0~!cRL<4XFB|U~B#DefA0jAM%k&l0874%Wa}JT2gF`TW^@mY~|PuQ5lZg9{P5_76XJ(ea@QL zC-6Jyh9#8p4tnd(Vx?&1%oQ}49vdS>V=__Eugug;0o0_E$g6)4x*J=JrgamJ00Gcv z#7OrKbqO-|v?QqQC)_?nl0{zr9EzyZIMOk22A#eicf*f^jS586)hnn%?;&sZV^p*rYqpww;f)D1|r z`*P&fDa$Hj>4E0lKN}G&?Mp0DM+24%EXBY@Vl}uYOMQ9{G#A~FdJNS{H3*=q@u=!c z;e9me-$&&|r=K=r)i{LcPVI?909eAh*cMsjx6!S5LPp1!kMR$h~kyL${ zV-)#TJi&!I6%fZ6lVIKswpZKSZ0%xB?QiifX*wu|>6k{bwyIhjm6v+K>RSNx%S%U8 z^%KT`YxdG%vd>);*2d73Z#I#jG8ByrdtI(OScx(_BXxMwVggjOgM|1&m3x81 zjYYf5oVUCAZN=k&lG6@2k`BcHbl`S^NW+HO+ymCHQDy1AY^Uknc%FJJr-#EH9Z6#= z)6w}YB=qKYJEV#y0K(1hDxIXAqnTH|FCkWilz}di;ZP6^N@R_Iz!Mk~SQ*#`Smoo6 zUc7uwg3^H?>Hh#+2~YQ$)T7nHwd(aDlIb$`O~Cq!YNWw)1VU>1YSd@*DP*1_ERrz? zb42RlB#ieKAY2Y(TZ{!-{{Vc9LWbV4KEV7^%Ql6p!?V_l0%vk|#urY{*o*xae_p@!=^<2NaI9|}@J!5dM6l&>_xNE~qn zppMe)6MK<5g_1S6f`T}@gAJtdAd;c)t*d&Ihhmwl2agY;pXDmxm1U=^+kYc&q!4?> zGJcKI#aQ@&d6*YAVbB!W(y(25K?g+eN#ej zK|M=kE}c!(4Ck7fs)C~_(8EI1GRUw3xE>tXmMZHs)=!la*C;}ymteYB8)7DA`}vZu zFUk`P0+TXfNlvl^3}*qX2-A)R1!Xqw+_SssVT7q_apHj5QlNmaH3@K^v;wlAgv!*Q z1QB05FI&B1tm|HF9b(N`Z9Oh8)Ows>GYnpnF*YLAv^DicJT8M1p$^eub$DD+G)#aA zU0Uom?dB=&qa}t*MQTxK1S~BDBs=%Iq^y8kLe!~A9vFfvsCO34*|3JtfSgoyB}9dQ z0z{zwrwmRdSmS}B1ywB+lQ1Qv-Vs(`FfP)%I)$+%i8mdrEpADw27`E2qxxs*Z$PO1 zFiF*Jtl*d)Gc*G+;!?eOVj{8V>D4Hx@b~ieLAqIkR8hJc77Qe7jfV<1zc|cQoPJKp z=Nkkv*h)%thZW*l_7j3gO2OHI*JW`dB^L@@fLYL|j}!IC8k%e+Im zq&7l~x8^1GrjiqG=u{-BZ7507bqP$3gq&hxHqCVB>4xc_<`))@r5e;5Q)*PquTv^W z(g`5S4~V5G#XyA+Xan`Ll(6gr)edS*E~*;1aSDNn$K}-1PB+#@CXocRc7>%6a{EGn z*8xEU2`_N&)c#h`SRkTN$6`(g9uPpRZSAisYcAd=izF1hlsr-aPL~KRxRR9;w4H60 zc*#);2N{x9P9IMWB=}dGw1@Y->#-=Ioe8#wcAmrB@?k3^YLCMnHHz>xX`jZX&X7W$(3F_+bG)Oh(Ml| ztR!vdnVpqsd6&?)M6$JJHAdO$q9()e`bkHfS%R^Ws$!-^h^zkqq(K?o??wZqm&_U- zVXePt*@eC5ZBLus!Y@UL849wwOfnU?k@35o?GZ$L#6tN3aK&1$u61AZv3osxo z1RQjz;Y%))bZ?;EpL&l~)NHHNT586@@VaL-Ram|j^!3wCO@G?oj~bP7-NAFDns0U&i8k6Z(F^#&9QVk%ZO99 z;U$3bU&H59rsajMa$Zl4j55c%E6yRFZ$bdi*w~qC)c{%{5HW z!p&6_a!ORQ2;_*cR%W${ZcU%&8>+^Xv!x4k{{VDDiA=@;Aizn1ClU;BsRw!Y8+UtI zy0=pA6W%1afSYF!6d9Z~>Mj)Gk=+0Tc&Mc#S%jWZ=_jS%P5n&9v07YjIZdT`Zf0&}}Ie-r(OF<9ZHVaMd)y+z}7)h znNpUZNhGY#PR%|ZtZBXIu-yIib+>aY)kFoUC~RFehL~t-B=>12N}M}hl@*dC0AL_- ze@-5Y>98zAAH(xBc&zkT39EuAb39V{wf@2ntR1TyFoqL5~809RWhOgN`#XlTf~4w z@W1O057AuBnrR`&DIvtF@T?81DJP9Ed0%Xm^5OWzHuEQyl@@AM9^w^eU`?%(?)PtA zG}$c@gssgg1iCgLEu*n1+LfKB0kXMf(~Cumt`O=}y$yvVfYhH7knq}MVu-*TO&$fr z@XS-J{UyoN6m0R}RT*|Sfi1RkO;rU%+msEZ%Ap4T0BYNq@HMzuderf8UL$dFFgAqh zh{vi(;5Jr#Z~lD6+jiEBf`M&p+i*xAl%+Co*@)Te)j@Yu`iq#l&DQRr_3sji*=sO0&F)UvP>b_H&u9A+jYIvfVOp;EJ zJ3$%&2CpQ6RY!?DG`GlaHH}TE4w8~U^TTB(xXoG7;gWFvA+kjO03SsDwNu}N$EdGN zT>$7tZ=bH2?*z(un=@uLs*?}Iq$yG%hLSkaQyNC#EV8_oH`If{*6`)m7w#mmlC&i{ zLVzS-N!uL+VZtb@EWB>jFrx&O5+n_!Ab$`$6Vb;GHEm<@8T1mDw^y>+8vU82J{sE4 zYrq%s3$gyTuVMTsSNzSjZ2tg$Pxw`qFT{h;mftoGu3&5cE$+!v+r*1OsNzLrcSCDx z_8-EZ7bss3dVj*I=jfJv%08vP7@XJD+>eQ_J%C}Eeni7D2zQufr-F)}fh3R2Rbl#9 zkPCoLr?t4ZJ!w|92xUVZc!RWHPaJqB%4ud>_NhQd36X)tO9a6fa62aoy-Yg~{Qw6| z2_O#-0r2E+Xv8LsUV9o=Q{l+AMi(GoO+JfoT+={dLG``Hrhh73*0ruQ`20_^hJC=K z{{Wb*YlJhg1ZuYJ>^}}A?kdLOE1`uo?gzHV!ri&x&3p3|+?ZGZ`JJt=Zw}miuq(m- zitdjCsH>f#r;NJ*ScF^H4(x0+1H|^@V%|&&^Or#aNslw`{V2BeSJm&O4ujRT7g6(_ z6XFmsGGUlVIGu1k$S_iFR3vyv>G9%$m+FZi12~c6fhAk`xWFsAUGi*7)&zud8It z2p9}}@b}~AT?oo-lVNPrDhbq-B`U&k00RV#oW(2sF!dWL^n=uvPU{C!pAf6UGTtK9 zl}k$_PdT+bktWC`kyXz33`N1PHa-VUyQ{*jhByJl9k^_cn4MjKwo53U4vA1zn2c?bS0X5o9b(JBx} zKAyu^DVSt=hEM+h6f&R(@uT*L_NGYn0*AV+8m5s`jhMX(a%lckz~#B=1P>Znq0q6C36;T%F}z4>G38)2agWi zLQ#P{C#d-o0)4bP%Xcd`%<)SFvHd5M5$ql%AM~QD`#gRzIPsb2dOeXTaO7M0b$In# z)lYv0N=i>I9R{Q{jr}!C$Y@9sX9J8!Ud_8WipVU#vJ@^Advc|8rIdsN{&Mvz)B!}x zIsPHOvNNhkE3@@p6-_b!0D16AYJ5Hwus`ucer=7k8?H}}8aInF5+EF6ei0E4 zNo53ECBi?6(x(sm(T{Z%JX@$)^Eu4ZW}JHz#KXw<6_|xg=Rghr08b$T<4)c5;%8Q) zw9X%=4Ye(?Yi(d5rkh9jt)P4bF~qoZ(&-FB*Rc$sk6>$REDfwR*5L5G>PXso=WQ4+ z?5ITHLx)DaWcA-j^MbQuY>t@Ge;FY2#}mL=oMRFr)WZ*$_QpHzuqT? zDgb~4M#IO^+ht)hViR-btpPO?oz>~=xEij4@tso?CX3*#~;aiQNTsk^VJbE_y7^sUU>}9sp zRef@$q!S2bAp=aEAgx7ekRTl~F}8plz3MZreR{^C!+L?7%`_Db!L02^K?)0<#yTY2 zQo_~&*y*Pti}u1*hlF&V6Trv24{cT4mzXMTroXlq*C7z${vKW zl*1P4u64{AwzWYflK{a@BrksID=UwhY(=+Nab=nWLJW<)9*|GUi5$+in(%jaR<`!Z z*{Sz~iXDC1ULQ#`3}?Q(`d6sS_4#+x_eo&EMDc|<)?vkJu`EI`_6A5Ij#Q?J@7s3r zJKKWWglX{NXVc7Z9SI^u8j7g0#wklJE+Z8p zd4VJwTAr!t!5h4S4(-1F);75Jc^+mKCh?-!+aQVei9Ivr?ZzD6?2XOhwE=*V^J)q~ zRuVsn0bDf=li`piHr4D?ttD+-6_k=BwDk!T(MY zZFAhHr34T`1cEq%FeA(v6gAP{sMP-Yf^2mU(Qze?_@n6>#nq(old; zbFIPsdvd|L@pgeevwEfU@#$_lEK9DLjw~ihztU4s!5h@#6UG>+cxhn;f&vHO&olo#II^ES%Rl;t*J=}VAQT|;SXh$2#~Rt`HhMkGk1 zYt`)2_&)U4rr3s5=#E&--AT<;(#cOxjN&+*Rvkx8P)5|MDytJpQLO6_fGb+e;ZCd8 zZO{lvQjB0p0C~ho@;=&!GDdgTGrCK+@3CmWSSo1^rPZk*&VZs+5kGFdWR0OSRVyu6 zK)da9@g~;*Us0&~xE~0b%)_8c@!(G37)PZ;7Vb_yw2_Ak+f%y4k!JAi z^>~l%;9V@ip$ear(yogQ@|Epk0S8A;?X zDo@BVW;2o!tAwRkcoU>9c#jb${OuZg3ENaV*1uSupglz-l65mSRK6Vcbi$}V&~V6= zh3si5$PRZ411WYo--|HEMn1BvkIT6s)M$BxxVmNW1NQx@XvrNH*qQ==Sl0NmimfKD{3|}u*$I*EKD7w0(|K+j?-z2zTtX6( zq)FE|gM`PQ8n} zq@A82#t+^brW-m6Pk3aYfg2)aLIx5f8IiDY8x2z7a1vcb!2!GdR=>x97VU=GiClcr zwk$Dxw9pHSXa$HG+TI)zBHIDar3aM$CbG5{c(eqQr`7yP=GAW_&Zr;8k&T3?m7`<> zTaHGrTEd8-Ah?k;T&b{mH!>Ss>!-uOX~amhBDA}awu1ivQ2jh^q4WbiDGOfZTy?x^p2njfE=Uln)7rjCe*cI=%Q% zHr+)a5>#*_0-!KGMgcm!%vGq#*55*yYTfgHPaw9sR$!yYzq&oQ;0yAv5r9;AEAXQ| zNBi&e$L6YTs`XFkKMh~`*qI6#z_{C6hIZEf0AWvK$J3YGF94MvMSc{N+@T}IKk3KK zbw<@)di43zPscm_``~%g0I2EyZNSAgCyYZ=3*pq$)Zv~?iBTe_mm93~@s>8fzPCE^ zTKto*nk=~9CK*9cR;3Mq z5KqRdC-KVlY3O^@m!|40r_ipfVA;PP!Eqcex{88l2{TjL=tW{Z9w+$ z)3S}!%r|JMSB$9|%F2llAwp#T0G^Qmbj?GrW~jfjaSI?XSWpLQh}#~7)g}58%~+lr z>LOgb4Dv%3c+2wBOcPd_=v^wJg-Yl=!h~oKk2A|AxKk)wK)}>N9W#jQ;at6K1^6964RsCek^}S=R$~jIr!)3Zzp{l7wP$tAc1><93z9=;pH}{KMw=-99`!~t= zmoIV5(FC~hlr0L-rjVI}lZr`MlC4Qr01PM@y?fa0t>L$|kJ%wwi4qj#PLtG~lRHVE z&!XP5G5&(}TMz1XN5p@sS-S^T6quLG#WggrPN8LvWOX-=QEs|#uf1Y-vC?j84M zSL#k!`FWxNAHd;Cguy{7LWc>HvSPQCZ%aA5L02dZFBJa(Nj-SrM@R?TR}bmW@ecIw z)Es2=!_~eWPn9s7)s8MVn=!l^2a=B%N@>1t52C83h#HDG9%4MnP{_VWDim&G!n+OY zZuzj?;xywbQbF-XAtfLlI4eo&(j=OZZ|3NFK>q->e@3$f z1Uc&^<~%B|2%SuEVvC4VB?|_zNQ})VL+>-f(MZX2|JjrzywCV%Rs9#F$^$gz3x3UNgxJ|6`|V2#C6`_jz}ZBCJZP1&Ti zwf0{Vx4(K7oZ7h2I1oI-f}}w9)X}>+a;$C=r0oRs>?u5a;;H`t((k7nZ_=(W)I5!k z%L|-yGvk$%P$a8(X_I%zvoO`3Sd#AF+&DjI1t5K!8~4**V_O=Sc`L^S^p9soKFF@1-`ghc z*~ZLbl0?o1HsOgq08v`$j!DiPK$<)UBjDJMV8o*nB2i&@eMM~N%C_)grAKoa1P#`( z*5>@3UqY6$6T}5=0}hcqM$=f0X?WeUVQ(!c0O^&Gkv$Sf5_k=}Xx(6bkh3ixNwY6o zy+`8p-5bieTB`=6lB+Of9DY+%HYp^q)2%#o)PkhP zNCaa5la9b(Oh_kyBp8qPyR|I8a~ng8{km7GdzGO@8e{Gnry0P2N4mJ@&qY0J!ZDn; ziFC??66#h=&G>E^jo}%qFJ=5@S~+NI+0`CYYGX7rQ@S^u1AFVX!$LTn_64ex+K5V% zfk`851Mda_0OLDIp|5{|l{rx|J~vAxaKcq3tfrx?b0W<#ia_xu%g7JAZXK^GTUO%kA+E=?C zH}wyuS+5De=!$&BZXsR%tQ3 z7B`M1mTnnZ%)(OQ6r%$eNHSxLQeUGTD9yck>V6y2jF_=g)#A-0v(`^Hl}CqAM22eo zPQG(wijIn%UTNHswN!y}z!RHmRa~eg7{^Z%J+bGG81STd_V8Qo-J6$}M@kTqWBNye zQ_`gv1FX>Tk$pekCRc z%m89eI8Rm-o2v9b>KZ7Y`He1pzw&B4EczniJ)j)uwpgdurlVIK)WXf`G&y?@z8Z zd_RM~r2hay-l_dNW=gKLWV$S8Ic0ow#aCBVj8;+!u=>aq=-D7jsG?Pk(p0*OlVVS9 zV()5u&7N-OaB^g83f0~Y>%JpqlLPG-C>^sS5wfu}v|RHu$uE)_c}Zo){2?u*jcGnS zbf}pHByhmRTWnv2pW&$*h+^r61opnIk5(}{cfa#1llq=waP2#O2l~P2{{V>3Kc!>& z-z>=DZd}J7uz&M9$bSrx?kF$R6BeND9Pc!KY={q?tP zPP~HJ6N;2=G^Ha9NjMK$vNy9aaL49d$7H1-dJ@p|aCKMJ2i`Rk?mnj#rAQ~mJ|2u`q*jl!iKxHP=7pA~E5|f#?%qq7 z-Bo?JxHdie_zrd!B<;h8P}(NCESGhsP{u@)fChHJ=dLSmUr7G|g4d>gndD3tGkTxH zjCx{{i%s)lN*sql&inlUoc#|0}#EnJZ+1(r!<*jycv*j)0-ElIama?m9r04r1&)JX&;P9OkGV>|(s>U9s{ zG3mb(ho{|Jz^PzDZ? zkeMB6SH_knI?QYdLYCk-cwG`>XvD&x^o4rXx8I46;cc3I8sY2JEP;zjnmToe)vX&; zR6?m=hSW-=MFo1q3`~*$M0F8`R$;Nx7>o2{vd-3R_v`$bz zMA3uvtJQh^Kl+=<{Y-_L3VJ+76t1`cH7w`lYY^L8nB0=O-re*(P|N+)xN*~u6NGes ziy$04sx;qxi~B*A+*(1EAgMSE7M~J&F_Di^q3`j_=oB3y^~IHX--AJXAE;P+P|o+T zYPv-U8xl0#EjuH3H?hAZ^Qr4+Q3esEX;(;rAdV0McJ$#~blmH}&GQOWc#4@&>QEqi z4j&o_{W9WBh2+YNK9-WB6_#rHglc#YhFR7%k|t>!tPloG+PmEBxKpPv{{VW~@1F}Q z2muN49fc&2LpRAJ|Qv9==nRxwZ|kaQNfL%O)`l?C&EOru{3#iz|6*BCG|hi*g+5c_7?o z546pb&Zv}#ZZH@m=_W=blo5$Dg+`Z|TM2sQEu?C5_LGm?M8F#W3KIZFimT_-@$QqxnpP=q2T?a)XG-hJJ+zqgZq=3Dm{%er}C2x%%11SLXb zVq?TOZJLNT^7P;3D9hMEamUo$V$!rvg}P}ti>u`(WbyueXhV?cNue8gQTZYH7G49!&#gqKwwIU@FqqQ zr4WFlO6?wY#k8SiwW$fxq6yI{+oeYkl#jh|cm#r?1sgmE52@*=QFDe{$haj6X6N~O zEHbiq(nFOgW{HhtEE?hQmXB&rGN}qnAUbk2doxZ(+S_p?sZtD*R7zArfDi{lM9zp_ zm{E`+V#!&nsd1wTNd+JX7=fik$uYF>D)7z&9cjAj(_A+p=d5QbRMWcGVR*H4QyP}K zy2z^PRROY+TKabcTbZ4^S(>vJ8+Z|=Z6J+1K?H**j74*Edh)TAU%tlOE~^v7E5);C z9u#H&01ce8j8pZxr!(MhQ8~(Vzs!vSVrG&_U_w@C;b5+_L;>9_Y`cmA7UYfr`$f1< zLDorNmsAd%CBOI?%Ot$Bi+K|iuits!MPguxs^97rR}8rZ8Q<#vl8 zVYsCAl-Qmk?@@?7O&;Z>2EImi6w&Eu0@+l1u1I3Q5=SvPOr)O(A`A&Qju`cwy<01z zw(h7TYao*(k${qB6Vx_)_|k_G!m8`BdJGo}GCVZmOj8ru0FUMA2IWHS`Y>jDYE7-F zI&rNdyh>F}!9k{!NlHqT zkf=ga825??XxkXh!9)`p&QYxrVE7aKo*%HoB~ge9nbP+@WS?p%w|$gS4Xj&T1g6E0 zh^@h?b0IU~N$MLEsM?|rRb!pTXrv>$WRxN_l|(H=X_akCXJSDebS(5|quJ-EG`P-3 z!{~)2emhFC;j39_WU4gICUuHAEh7zpoxlaqd&c|*XSv5+l3BycO!o>ZR>qH6zTzQUIk?e3LpatAc^rrOk+#0_I$`+)DPjyo&=)2Ygw&*v}lIA;}Nncg*+!~~I+K4FQAljbGBCw+q* z2v%G26VnoEc`M;TOjw;>F;+0_U>U+nLT-flt7B;$QU2D&vby+K5xGw8HneHkR0^H6 zB;~q#Ma9v3;>mQiaL0+_CPrxd z;IBzciQ5wV_Qp z1ZxS9X9GBG>*(V_erELZ)tmyFo|_A&hceL2hFB-0ks3m_7a%bbZTN!9MUI>jBKf0= zygVT6psTrC$ss9+2GJ2ekHl4idOPZ-UG%wzNtW|{B}5sA5s4}#5IVe{rn*H0sKUik z=&bSYBX`-{2O=!))mQG9Q}&MtkdUm!li; zT(5{bS#f;0_uPaNx@uJ*IJ+jLm7-1L$P;?no@xT{DjNc$h~O6+cr1O`!J+<5nkj-B za}?}PN@UD+rg4p_#HVQlnzZkaK*QIglz$2NSe^OAb8-HXb#uwh39( zK8)u>o$?yWsZTpYEMD;4vNsXzp3|F#)6>;U8|>z_}xc?AcYI zC~^vT9sXz$L7mfqYjQ}X|W1xU(1<1x#F2Xw2?@L)+^iwwbXDt_Fi01 zcDd4Vz>q=UQg|MokVu?pLuY!cMTc83c5IMG5TV2$amKb2%~>;}UyIMC89I;9spP== zyOU@ssc~95nU+fNI;P0ysGiEzaLr}{asYDMA8UYl7Yv!}7lW;&Dg-*&n0X^(t;PYt zuaJ$=)75&um|}2ZDVHcKM40t8WeUAr z9aOP-ZBqjaJ4Dj1(7KCgY<1*~ZKCm%x{@&jA_;;4#1X+mjPanwmSU{2&gAMXgDM1K z3H~9*Cxu(BJ~@?hhfHWQHdMq#b{C36YHE~H!Ts`&8^rcxaDCQQu~Vtnh3N%29u+1R z68b{YWE?@~-$g$;*FGB!Sj5o0K3n1lzZBjkGxav01h!aJp9ITS=x3e#_gL`;>zB+c{x@pP{vD`w^7?p`q zRD-Uf*6chzpGOx8YAGjMQ&me4n?_&;;B~ORn?UhC&Ul!u0W>UhyD23^P<0lxij<(N z2#}Guu~fS`x9=szy}J8270j~_<;hCOBozUM-k*gcecc`qI8f*6L(}g~ePVQ0ewk;# z(KNeiaI9K14N->HulYKdPko0)mOI(f;OYk^3n!6q*jU9X6NU%(kJ5mzHXW@~y1#+v zj)G=PTcjOkrujT$0b*k;hN}*lrfN(k7%Ep-=ZqDo@`;to2HI1pr%e+Cymg@M#7dPKe9BTFag$iD+hxL=%Pp8>!S4&IOv1FJ7*HHil`H~y z9;&yTD+$9g1|t(;n`rXn&ZfF2k=ZD~Yqe^$rHF{F{NaCe0OLS;BzK9(Q>_E`IF*Sf zLEy0`?clL6Fi_)M=t)+1bS#4R@E8NU98h2ZtBMZOih3%!zY)%`Q{;cbCp_lNUZNQ0 z>O{XOM^soar~b6#5>(4Lf3;|^$YO9;U4u*L3<-Gpt@2XxM~dm?ERC9zsFVoUWfA~5 zPSX{TnGRj~-Ql*kPykybDo6yRpcSa&_L88HsAC;wD@*RN)6-6mbj@0R97n+w5d z>$1fY&|r9|fg+=a6i6ohC^ZU1l@l-y&KcQ9ZeylY@8qmI=R>K4t;Hqf1v=i<7ReZ4 z5RtM7uAQxgX4j~m!Qx+r=UV7LnoR~_$`Z#! zF%8qLeN!N6U7lQvYGOjwvs#^>-FqB6Gx^XIOG9>6W^lk`6_)ZdZ<{MLxK5x{q67%EAa z!fQYCUeBI$bCHo)sgUStC2lPXPPtlJUX`y%?-mkTDIq0k(m+Uwte&O%HqBi&=d!L;FY>E#$nO*qme8V0SjyHN%1uxO;5{xKm0rMrZb21+oy0~wfNQ}PlHj@idsB+vPYaqXT>oEfnP~r ziFQvNiaLVO*zrBaW4xA#Q}35sZ6!pKTTTQ*6DOpf4iYc~Qp}$w?B_SSO|_#|&p5Td zq_wU|N>lqb%Ze}(V684GVM#bTNWzOJuFMaoSuV3Ivg4<5psjl+SiH0J|(Uc7wShZ4+y)F}XI01ZGBIGMot?XHq;L%pBd zWN7|$SzYRojYVDQQ)H}_D5))|B|#YbraU)vt zW$M}1Nu=J;LoqX{sfc@_WU@3vO|7?3`<8p!=A)^>vIlzDIB^*5=@l&N8cJ2GUE;f?1G~;D0Bqd~mw$7IoB$nk`$J(TVKrOZXdi*~zympfs%sFi0xTLhW zkMkO;oUtVHRN_;#mwJgBQqrg_Jh{Q%EVf^EDGxR3R{uLGFkJaf$|{C=-fi1bj2CzJMr}i+)P;QkM>znf%W{Q~5&x5NK zqBOGxWTNAMftnLR_Bd4WzbP)1gWQTGHvoVPk3mAp~Ot)-yQ1?WWXI z_b8n~bEph7lxz@oD`^;Pp_8FG&VhYMN1tcVWy~)d#J1U_+|;;iu|gCbH#E+g=m&dg zZc8~^Ln;BmfIwQrbm=kv^hF-EoUb*xB<&(S1X91D-9D<%IL=DQG+?zxV#Tof1p#d2 zR#ry~hG0dPU_I^J`+11>_W`#YUeJ`2w+{$09;8-8S)*HRkLe$AIQxOE&FX&)55xAK z5RoJ423kdpnMdg48Utb8e;#9-d%>71{dvQ;_>bd5#_U)r2S}J7z@PAI6kmp4;r{>; zy7ZGRCy4hPYkP|mKZl15lb&BMYpXx!AI6^iiwXV_{*gc6(O>oB=+DtNLp>Gs8>#s# zrTJ!q8lu9DHWgJ2AEkn}vZ5+zWrX>s^r+5Cn-g(+a8;D%S63G)ORg-Sk*F0Ik8a4K z8|Dz&JOdn0+L44FIz(d|4Ac+9gV2wqtmWvBr~N_e20+WXgCEQk)p(TE_>@t}Q1MMy zGSZ_nNDkQHRSF0eA08>qZ{K3!XhO3=RN|q!M~&l-i*RK#_<7d?4aP?I|Z= z18fMR(;wmY=rR=A-73jypbqqu{{UBcE!%;?ncXY>bzkYv_*A|Uoq+!Uq#xi@_8I6y z(2HVFKssfS!Fgj+#+Hiuuow5F;*ooDs2bHD<8b!UCmsj{jZ+5=7|db(6;hvt23^bf zpVdcR`jwPuDe&A58pp$M+GJmPM@=cR_%PKt;>p3L4~4Rx{HfxsXrZfD{Zbc zM7QTOAW0`;KqW`W2`A;o zDx$qWelOh($Zs|Q>Dvu%pyGb`{$)E$MS@0qUO7sNs?a~F_b5pGVrPeA-I zKHWW2Q$|&}cUQnJh-LY%C~aIDLR{M75@NDXHxyAW;-Ab zswy-OK|@UOVS8hUF>4}(09dnHz-}$~j}3T@z^4c+#O%i&uSoV(s@=>C4M>hkM}kNr z0Sh9Q2KHURle*e~!sormj~XFBf_i_sAUr z90RR871DH>{`Aq+siBc1D0bJ03s|0;TMtcHRmS4%=Y&ryh*V~dbd0s*3R-V5U=1Vl69X51nLo5o>WrDhruKmbdMwu)k{xJCy>#Z zkxtcd6K-XB0ao(8=SE zg?Gz|W^BULl&k>M?1`!3xB9EN_zUntn| zvDGTpeMkeQsO#61UWTZ8gM`z18hV*&1Qjcdc}Av8H|ABxkl0j}ww1w4iGSSg7h%2l z9L!M2BfBPlicTAF#Q43wm{w-)EzWqWb^ic7)2mW@pR_%uJYDEVfMXheiY9nb7payv zq(z8daklbG71r!l<3b2F2ftu#+%lAqtbLn&r}WuVVRkCvy%@jY@9NJrQ1sWW-7dp2 z?t7Fk^7(L@{6>=p$65s~Br{?E05ZawvcR#8SVcd*uqzFueADQEVqs!76A{4TPCGFX zI|xn_hCAi_^LCq4_P2|6*;A}Imelh)xP^p`ZOMsHDnoqjHh^>UA2YFZ>U^tJO6s(< zl=vj|?Nu2|?l}diLa5n_INJTwa`iqpQzh8#eTCrCIK4m|EyXg{p1= z9wn*tv=NK}1Qi(=>KF)uCv3!Q4xB-hH7LX3KD|{U zH2(m0k?*JPPJX5OKhZoB8KLSoNpkLguCA$Cs%qSBrllU9B~6B!DC4|Lg}wXOJ@h1t za#2%yk`gCq#7{xmBy`kYyg4=Idg51YeEp(Qk_sA2aH34=Dp1r2*%J}MXvk20A-fTl4);?uZl!?mBwX=AnNx@wNgXE<^FKO>UEGY>5~g#TtwUgN zB|~rbutiueM0#=fX!^0j+cxyiBT`c0I9#zwRfAMDO+4^NAp$vNhB}6Zs+_pDn1rp) z)(d+WzcG5|&=M45R0Fs7d0|m5ahvZh>@T>wxl)p_bhQvTPNT!<<@8gDaw6f%mp$PaHXjxS zY6Tn^P9CvHOrb;k#ca&=Q-Bn0R&a}{RRojDJhHTaLO>k=1B`9rc5x@FCbH*p_dd^a zg8u+4w_Gl1D=sXQ%4Rg6LKC#&6R7bd0Ytn@Qo&Z>sRefvV%@KA1MR=?;eL@*s-0HJ z!=`!m)uMWR{3E?fdXMN0CtmVqDVM1z@k3E28%JA-?3$)3W^|q8nlyTPLad~0o=DsG zm@3(bg&BI*khvJl2^=={1JtN7j>A~RpLV~N?(OodA4AG0)7~i!k`hz_LSVwy2tRXa zPzL}?fdZ}SO+__Cl+IGhSy{uYue)$rT?tlQG$P>lzmEvQN9kEH`IQl|Ws8!`op=LZ%yAZ*unx7TGGdh}> z_r^$;o^_OY&@k<~CstEp2^?wW$R!SfBLWP9JrC%7s4({9TjfYPg$}gZ%s{ziD9UsmAA`9Sp}A+l2@?b<&qg5!+J8Y z0Nel@wyI%zcyQ|#gBh)pnKSFPd+tFP?9`L?s0?CYf;bRh#2Pa6l!2z&Z>S!@a0RSB z96M#KXawVsDtMwS4#8jnxEddZp3WKu=_h*|Yp0?hZFRlv-}Z9aI%>h*ifn3Y#!#-^ zr?Jor=rsB}aXy?WZoF&1mJ2vGC&K>#SM22qaj$onQ33owJt}nHtok$JQuuyZO_( zZNq47v^Z9whWB@FYks ze!-Qk;>T0NG7y6Z*&QNhs3%GP0D4tIPyYZkxk+8s^DHL=rror7dW)9@QhLK_>4CD1 z_DShS;*FZ=qi&A+Q^;LBr*{QrtjYLzbsAZupBt#2cGJY6JoAhd5EPPQh)&P+;QVSa zxy|xs@wm*Nby&z3D#ZT)ioie~LZ14YkpBP_{)XiFbFW$YgVK(l&{3qaELAkQW}a4M zLdyj;G&nSqNh9`9fZUONFT|LPCmsXACNbCynD%wib+!IYe&9v3S5JR^Hzgo+l_|iG zI!w<%Ckm_jU&Le8l;SCIY+nSgGG5Tv z%&yRVpBs}x{-tWaL<_=4W*wK6;eTp<$N(P_#${CGD$8a zhr*@^;9$Fa zdpLkKCY&x|Q|YkkS!anR0g>1%kM&#KI{Pem@8!a<>BHNFC0oi!F~DKwF|AX-4DUhS zmOVxKg6oGwy-4MWGY%(_Ynkw`F1o6jsp*##s-&GADVcX}K3iPg!%YF^N3QzeyLOyt zsUc0LR7czrfOdmBeIu@d*8wfKXHVWnJp?I2F&zh{X0Dc-@Iw4IQ&s6hNKS-4CyKTG zm;FE8ZWMnsyg%!U=g3krrg-S*{OWX1!GG}WrHnj%9f6o0?N^FDkHGxKgH9JYncji- zx$QrNH{IH-zXY^U=yV3_)`VpG44nwBFGDcy=-h(jVq}8=8dqG)B#V0dJ z&IzQE!P?7kKE4bxYv=C}?|7rBC@M;cg(pnvj;Sdg`U_q#!%IeuBo%<5A_yP^$QW(a z1nt>ZcaHuOKZmXzT`!Z-90){?#TnwPBW=l2H_xTk-wpyF&aXi*>cGcgJ0^sTSX(-g zf=P~q?cz3c(T3Fwpsb8O^W zH*oq}Yy^-LpbCjHNgGDNx2#k%yw@yQoeaWbY-!uahT1E?iO1o&=^~dUW~{T)9*|`m zvyDlUafz_%%sUT)lBS-r1ZiTP7A^pj^mYcs>u+x|FZsRFZvfOnbvGyqQ9%IszT#(4 z+ljAk!wA2#T9kDtl>nmzj4+L{2cu^kCbUZF{{T@j?wD6(?zQCw+gF3uO&m`&PGMJ` z0=rrC4I-q4_TJ*a+i!fU%Lr=iXkN?-#7O|bfzV!W>wL^*^NR<^I=*o;GAZ!C*7*OuZFSSV2Qy>U~ zutyl;PhD(d>Z|bn=$3h?z@g7Ch~pE};faRP)l!NaB_LW+<)W+@Wjsp7LD0K3ylxL7 z4d%&(!3qi~a3CNnN;H6ti7ALZ9X)lE`?S*;!%9us0)kWy1f^afv?yXDfW&oGB6UCT z_Um^*^B~S1pK%4pA*EvC2Z|wBrGX8;nxR^fuVR0KeKnDAu6E{E&e5VhA)~aFn>|_T=`QH!efd# z>hScMD1`7Lpqi@+YZyapUooP(dlz0r`S$29FiE(vT3pls36Lj9feQyplzQ}%MAoux z@I{ivzF>tkQcRdW88USsjY$I>M1U&WeM({&ZX=#>KB(Z83oad*s4(18IR(seMq>#f zPxT75?WeTz9%QKwC>fPP$U8!|C}Ge+2d;#>z}W7PQ;w3P&jm5jEadbOLd4nB6ZSI3ZxON|C1K9Xt8_1u~dO$oQr)QOSM%`sF zesqH9zgOx#J$0KkL5M|&RbW}C1I6dn*b`WB@=fB&gjpjwhR_e4ROAAVf3n?J#1~wcC1a;G< z3DQo4`l`ey=q6mpI)_i2aas!Z%BM5uzvmcTMmJ9gmX3|Pm0q9mTNW|f@Y|)757ogsT z`nL5$mb#zmH>fy--7zgeHgdzUoZ}5AQgAAgl1Ga~u|rNOaRiORv~$wKFPe;FBYKdf zZ|4qWw(4%-3Dr7Kq@Wg5lLRP1Bd1`)2^i7+mQvnjbb!)~tm2gvgV1AC4VZ#(oHorm z(DkPz`fFV6lSfZ;h8>FLtiO!qYJ|?X@5y|>M6FPvJLUa$gM0ay@FN^v1Tk%k;b z!BTxYU=#YD=r(8cBhzYJOD*O+?vqqWo3J>|U-KW7kI$mZ`Hm%xo|^)mp#pBEmL>Uy ziRzYQO{;vHG)`KuR@yK!qODSt;fNT?2gNWpiI_|q_Tjp3=eD1kMaq&J9vgF{B}#*+ zq~J>Q&IWLuFis^$HhOW)of7qz(`>iYk4jaP*j|0YqrtEqon!fts$|CTN2mT(QHmxs zJij8fu?Z4?D5^&jZHz9$4=1}!)vUtV#kFxd4y7+jgafcd0z}M55e9LtFh6GITEo?k0*j(lwYlr0Sd@7FYt8Ln6gak6!{}seKD!K) z4lU(YLh~ssV%+IwdoqAPk$1>#_FnHuLcjq!Oe^?g@Jy*mnG>o2AQLEBWx$o7rbz4A z7@zU5=rP8GJZ6^)%U|s8>jI7?0vH0B!oUnXRSj~u5eaH>t2j#|1HH`Az!IVtBt#TZ1A4<2J( z_0v}?@Vcik+OR?Q&d9?U+lLzKH(|MrzEt(Xu3K*0x*83uyhsZKp9~e5RFNOW1}gWz z3(QxhIM1LikpBQw3Ppk@89hEAX~nkU=}|ZH872xYWoe4L6Ymr&`?lv7yJ2Z7-h`(x zE+X8aAtw?7biq;p;1{H*0jdNZ6xQ{Jk(pg6_?#;WOz~`iqB@``4gpifgYU%Gsh*hA zpjh`t{YhZ?qxn5<61BKyJxi8qYw*lF7Ygf5EjB3&gr=yDWdc-fmyOCcBUy+3)Ehv>q6LCR|*Bq3R6Uh)|fH? z#2y4liqY0+OCSZaS(BXecr97esVPx)f8w?^5_*BtSm|YH{Kn;*VUKvUgZ?UfYWF5R zYv;ge{Mdd>N?Di<%x|`y7@8Y)Qe*|97q<>yMucuDzq>uIL<9pMLR zNgJbVvbNv_fqR+TCHCVn{I&K_`)w6y1zJ?uGGHk>lBCI=Jw}3gCh=TksZh7lq%6q_ z1V>C5m^)yD24IOIoP81c2I-ff4854}yoH!?OvziCrKOg(qYzkNi9S?1#FX@u<&hkR zJLG08!)n=7Y8LGywKaBx(+wMRvKb{(7FMEEAc-L$CyYTe$Au=%vv;$X0^SKsOlcUM zn3Do<00AD_Cx4BXs0u!q`c}p|8wLT1Vs+W*P(t{)pp~#pHkvw=sAiK8x03bl@q~^6 zVt|)(_EgS2fo{rInT)}2GJB*f219_nRHTm(K*vByGI1OtMK9gEHCLV`kPZ`?@{ zv!fZu?l3k~9{Mh}9_iD)xz)VsqM(O{FmxWU zaRb}LE-Fs(7QMYG}lAAVrmZ=d#5u!E)(a>W3@O>!0vV!#bmfK-F2h zrAm{_WCn9S3gSAY8+!?8STXkPza<=%?(8Kboj9QJ1SBb+nN<0R=qotIRf6%HgQ$w(?+hvWm=yV|IZVNB}0Lmfx{^&8;ij(0{JrjZTpv!0t zlGwvcdIbppd15^%uXU?FV_hNZ?pn?meK^GM?9YYbcm&iiOlg`%nKz{K&H*TpkfoSv z05;^AyVeNKGUu34(6*dy;IcIU0fLmLiB>Q+bksq;H*RH@R?mU0EAJU77!p*O3M&2- zrZGEuC^+aJL@|!KVwjFh${4AJlP@Ox-<+h6Z1mLT>jn>j(E`sr)gR>HP#Kwtl2R{j zOt){hXanyg1eh$dG8ChScM$%BWciwWtd6FNYUEOO*JfJPLccQPtvF}$t;k~I zd7f$a64aHLN}Vzbm`{d(xwMJEBn21;X&Od@CvDJ~0WG9RY(XFAe@K&wl5r$#225W~ zveqw?aB5t3k(R$0#9^9B*Lj4OaGRrwN`(x8Lkmbi?oV?Dw{7cI(U>UeDp5<(9uSrrwEJ~s%sSQubSIW({F-=qYIV73M03w1LUv|U8lV;GAQDpxNZX2d0kp`G(@?JC=7%QD8g!URB?~0L(xJ4T02noHIqUHl=s%})%so8m zG-p0EScLOXwHx_ZOiM7lsMT&f#z^KQgoO?FTrjsW_buH!tKb&*?17KCO32{|!VGLG zBW5+5IiCJl<#OG;zM(Oo!(g4Dub>_Y2W|$dM>6#YMW*Y>x zG}vW5G)x4wwaT)yNd-GuVo3wZRW+3nwvovNHny2U{{SS?O0=DBt`esdqC71(BLyf4 zQAr7D0#u0WKx-CRQPfnl6+Zg*g?B0Og#Q4>!nCAqQImpeB4K!b zU(QWSk!T?jq@p=0@j7pwuh>qjPYQ;PDah<1OWc9xdtJ<4Rm&4_qXbAxYVO;fl_-#< zC#0=hKH3sw*)lDz`?gS!QlJ*MkX&>QAq}Ju7aJ0k?IKr&8h)hY2{7z3o258*Q>lj- zhK_7jy1N&sQH(f<2a1v=Ngb)-g&04V<_9H);bpfX468B@tllZ~mde9uLrMLBoC?f< z7Nrpyw3LX$Y}Bv38Dbv^Wi2Qaps2d?;o=jBNP`G(&=$lLC3-@C(owB!2O?|Y32?)7W#wfHqp-`&ogQ{vMR#wMfK za&`Bsn9<*88sl!Ae|DZ4rh4oD)TfNcJh({mF)E)n8mXD*-q%)Sa!5_U$j0K=KJwdN zF%9_$gEJL6oG3Sntm9bhvO^J!#LOf`CvBKng0LRzcL8n+sU>bS=8hOsV9B8q0>lmt zf=PwqFvB(-E65C_M$+9>?F%E=lv@F(x_#n6V{TL@8RJ*g0u3i|S_(|RB|Z^FQ8fxx z#%G-)ZQ^-}StE=9H)x~~eccVLKs;&Fs!VLFj38{93VO}xo7G-l^$k&3NtDw!!Hdx@ zF-9=(Cu4=v#H{TSLP39*P2Ormtm*GI&7*e-9?z|xB{=Vlh=rnc50704qREi z-jyV39b5-Qb#+mM!E%>Ja=E3#`nQ&3%9!0UeB6{0M^y_{Lm~pE8A)UkfNv8LsQZew zi)oJw&#!I@mumk2c-d414JT(*OdcZ=B6wDt%!+&^Saa;7HBagLpgET-QfIj_3OMkb zX(9PK;XWv_irx14X=M8_d!y_~Rn@=*k;32YMrUTN2~pIUkWz!;>FYgX0xQbQ!j+^Cql|c|VhTxQWBsv5aXY7~n#LVyhVYOuk zq!b_-JV!)+`hCl#rvPxI`}$hw{#(u%ZWYv8THG@prmBuwIHRPjrJ1S=*@{Im&hH+#Go+V4%kLS4CSMJxMB0WGc%h$TZ| z+qQl*aL#iI$Jb`lv&*KB58@;EdGsIgA;^<@#po_3_+E61mTBjxs8{{V=13;2Pd;n{>Jpc?Rs$#E0 z)fcFIkDfhY!3nv|KoP14Sj3Ixda;nX&DMFT#teKKG^rE;AoU3xP`4jI(eqi4n`EgTVI zu*M0Ii*6Bo`daq_(u)lk9w=en?Z{W#x2PZKb#;N~M|q`zx?ruO%aMTMukTL+f1^HC zK^X3Oslulex!VM$#A2tGNX^q^@w({h+kgtlZ>EHIzX#}JUMN&?>NShD`Jz;Gy51r| z;6dmk+-ZB0x_8lDuEYG#Ei|$G*UBELKJ(!;w6sX5LV#a0prG>eRjWbj6la{ zwuDJy&ghKF-}EaHC&Wmuu-~q^PW`q&AWaHcEw6#2!=|)&N=Ni(RWC+``YgyK9c}+@)BK z`4T&&@GE43N)~?Nl5rw2A`HiWYMj}g^}hnRC0IC^+71Iy9Xk{tz^ZKMmtS))L9>lk zN6olyF-w&&%39Co7&MY8Fx0vK0DCCBz>cwb+qa^yzhXBogGH$>p(+XrDWeDC@3Ky>KkDH07*Slw0!E!x>wRy>+ezeeUh+AcTnfNQwoNfLK)*UlDMd- zbz*|-l;O8V4b+pnLO545;n+-%B5gZBw2!-s*%L;M(RIcu9V3vX#miXeP5vX=e}@f4 zc+g>q)<}>UZcLZ4y8WSRb|hF1{{WYMDXMLzJWhQGC4JCE!LckxpbKm5A9op1t)xv@ zpG!};a$RrrSP|^giWirr_SmIE5_JQ_5%&HbMuB%v{@jpo z+3CidvaFItL@QxCV@V8i$A9uNUs4D7AM)XLO>nDpg#Q2x!5`5)Nb2bnis2pFq--=q zzY}jrr_}dDE3q7ckipcf4uZKd+{_VHw9ONPh1EL(3^Fm@6Cbf9jld_91-nbSCA4GF zJ3TrH_H@x>_DjAH-`qA%&ne+mh4?+=P-Z@)=WK4Kfv_AuDd8Dgr#L+%k?i?8sv2jm z#xUxZurFF`NqHQ5tTup6xj%MsWu>RxQhZv{4DE!4Pq3@RJgb%e092R%0GWQm%_{&h zhZIr8BLmHJ~LKL>nqca6W2_$4kL%m*cNQSTXK#~8NNu2>fc7K3rPxT!LVmnTkQ?7>b%5F=6y*hW#nji5*$u3IB8N(6sTf4Hdkr)VdQ4bi;G3;WyFOxp#GyJFP1J!BMZVg8XNdW=4fb-n%XK6DPYC0oM8aEm+4Tw=lWD;GivP=DirUKFf! z88ETIT|`tDlx66C^_QCjGFK#REvY^wAfAjR2a0;Zs!jZCF-#|-`J5(k=d)oW0;Gcs!Kx&})Ur<#JR77*e?+S7Ba1H6j{T%wAX>AQvViDANlt}3 z-6hWRzyMwvOa~y35g-6DHJBZc*s1K&^D%iv3XqVXj_|b#Qpg}okP?Eiz$i>swVsga z^B-0{WaWIph(y(O@M1WQWv)14(#H3qNvr0lfhSd_R7tGD6;HEps&pKKx6#z)IU~qU z0HG}>QBnJd01`1K0r4HCx<%Q2pYz@2v`d8p_NB!Y0uV|;AP|ob3Q+)QjUDWDbh5lSOsc3aRh-F*Fk$u-pt7x(_@rnZ+CjulC-u;OqUC2 z)~9~Q11M4pi77-Gl9?qF>;C|&8TSLu87Ct2s}_?g)z_^}T=L;?NrcM3&TD>NolNn# z^Qe5FUJ-DSBQjj;!!FKpTWgzpi>t=N!6FhI0bqA&DliDaTLC*yMK|>cy?K^be`l5D zw+}R2fV~gvEAb(w^#S&{mFv|bT9yLvI%vZBuft@`nAc6Z1wCU+L76jU995>LG(kE^ zhUKbw<1o}z$QCGd4rwZy%dz$VK-M|k7sa}6@4$sL!nA;bAbs(172I1upRjq1qK>_CHQE@UzQlgOFu(G~A>Yp)Sxl=6WY6M&& z3hdQYCL@ZP-sdPE!buQ%aH1a5_d(v&uGq@5m9i0Poo+am&vb}RhSH*iAK8_6s$}8;QARkbs!yst zFT}b-)N1~k;+3=*#az0Ni--_Es$8jvQ{q@|3q^%tlywx?jJ4EKtW?0v)KbU+NLpDQ@PHK`a7*{#k8v!QW0oX5 zl_hIZ)S#qkSd#-#+Dr@-c7iA&+fMMcyt~Hr#k#`V2|`k#qyvFb`wEgsD$=C_O7w*& z$uukaE9xE>hvodm&8q+mWo(fcn8Ko-mW)L@Z;cntE|Mv+3cxoCw~Hflb`;uPbxV*`3IPci!4jolM$(cx zF~)@*oOXq8zO0vRY@0%D0?NYsv`W^Hw7Vl#medOLiEt}QuuLXE>{syztHk<+ie$WN zBR*Zlamu`~JN~31t0Ohxj zb`iUcp?cP`wHSnHKqDAZwUU(|;YbE}z{ZL@IPGoC_k1>+W*JScrxsS~K~s+s8(Kg> z?wizfDQVTIN(m|PO%~r(-l)2PNkg2v0iJTSxJ_0!hSAYMUr&uSZ4Fi*8^t12Q%v!o zt);10fJ3)d1Og(hh{1C<(Zyby-99z#Ru^1^wsE#(`^@1`eTabOhYi@c-1Z! zO$INDEmbLnDW|EZe<2}4WmS!Kuxo;TJR9Vho0+@17LO^w1vDr?{{VBN!=enD_t^3g^>8b_1PhcjHl$75O(NV_iVZ739T-;CL)ZuQY*g=2lkBR-S^6GjB3^8sht7M{{m1LIR8u z1mbq=9zdR<1K1>sAnGDi5Saj|>=V!l8jl#5!cPEonEXSq-^3dbivrL7x04ORa2$5N zs+R-HSWYVx)HHHI7@f<}LR-w0V<0s|?IW}Oor1%OZ$U~WvOx3)fIAdp6T=;#sa!ID zbl=O{TAH+#IFJh5QcS24K!p$_V0kJ zZYs`hZb~h$aqa9oahL6xU`Zz(fEgw_v}~g`J4|iU0^Q6ulBU2Oy0+JF_A-q>9CLm0!9vVVE9T?Y} z?Mat3=(cr1M1+v0;ZS43XB==5GsBHwhwymKhZ(^zHtNP(N{qoA^5JpGg;xn`;(|4r zX=!6=_ezmQ>dxR5P|JG~0Vqwn93nMAJ9ZEE-@=a-+G}m4NAk%Xmeq z{{Yny_)!G)&*Rv+ZbuosDM*KKmL zNKjbgfz(FOV^5-h$B5!F>gP4J&XM0G3Sq@!2@(i90`$-NZK*vY3b(8}f)=J$jP44H zVs0Nq@)eGcIzqioIL!ds5Lk^#y@~C^r6&qTmGPhhKErx~J6w+)ezVMc z-T^DAZz)z3@snW-O$qLIUiP^7jvQpE!9H|bnJQF#suXXoMWMxQ#9qsXR6B? zZyB1a9*QkQEiF35hu6-U?uHpRuH){+&Ka$HiGMojdal`=8Jw%nHe|$t9usFq252f!>*l(r|qko>S>V6xYaXdbeR}2`nOz8y$M9diC z5G)rGRVsU^TkKzY5Wo=LUvw=LK}a(oU}O;;Vg?7N6Ve4`4)f&4crCvyUU7tyJHpsW zE+9|r)vIDj#Zii)4}_6Mn?8On9<(#O)il^nB}0>jyO#;WBU*(Avl`mQo?oQc8~k|c z^G5^}K%OIyR2*mg>H}r{o8;Di-4M5k;Ofqw^oi1%uiW|6EalY9QL`6PF}m!%a2J^p8*6|(t{{T-8+ZfS8)rDqQuI%LMMeco| z{?0ucX|k*UsKEiM)G$8r)8XT%$Lr!!B;(gl%qQ7eihe3tZ!KisT^Z6mwL~f7uY(H3 zDk6v82C}k=W~-S6?u{&fwYyxN+*ap|B+PmGN2WfN(f-YE9CIgVICW_<CCZSxQ0a zfB>F6X$$JJ(?3+Y8`Ex{^-HPULBX?v=SovkM~BeklVUZLP#9vU4=9wCL}idf%!g=@ z6xVI|xz-FxBORE7wl;zA>LQP~b9=3`Ym19(YiC*R3@J)zHiex^P6vq*B1hUnxYEPW zoL-!z&o!^=ixR}}+zOtLd=cRh%OsT*K5#x%uNY>HRvpX@hUNix4o26_G~$7BVtNKU zFca(U*|vo{$9I~yZaVCeJVL-rkY3?sjdVJX%?glmr$ znb?__>Z4ugbJTTzrA)P%sj=>aHhqH^ni|jMRajj6;(`bn9+BQ!DbUh6JKEa~@2M6b zc;MEQ?2w>-;m$mo$6fQt)4dNiq-F-&LP|msu?0kr7y)TL;D}7f>glR%TM&+?9jvU1 zDCrhS+Z(~A5=VUvPA*(vK{ktU8nH8&s|crt=H9p1OzwCIttdT~h+?w@S}_wA%y zug(S#5T@|w9M!(KUw(!hO>)QVS8+YUm+;^Qdg24XI_!f3a8Ov&Ds^RG}P zgVoM=ugQ643STlAu)Hct>Fa6)s-G$u1Fb6UCH&Tn!P~Sg&Bl;~D4k@8=n{GM`D0R^ zdzt2T425M(q4!FlhZmtK7|OBx@qiO4+d80Pu=SmcdNO?Rhv2@8Fsx#aFJY9;4PGgZ z*1OG#)w2fkp`~R8ni$tbzS8$BQ2+qd@X;VMCI%-1C#PVJh{val2e(c9;kFjM?QM68 zSB18d32h@{N~G!};!eS^6Sjtb!{gQOsXs^X=cb7er_2M_AgEJNkfgI8 zlU;~xBl(8f2G%>T&nm@g8oV$>{ps1aY{d0WslbWCtlw+dRlENHkkfRfpdCPzJs^% zKM$jiA}ShEjX10iw0IF=WBX6Th9FWhs_*5Ml-yd^I{iJ*)yst8TGtfV^lDn@ZMWOR zYDDa%p~G0l9^ya%H}M_C{{U_H(Q6uWzQU84+acwSqU8)*r@7vj=Wtwlj(Q6CH|#P& zP=y>Te(R_=Q{ccK4p;0T^VRI9S-DdROO2RPNK#Blk<-+69CjWXYgX>Gei$CN{Tt_+ zezE$0tvHSgfmE8TA2rb9ba+M~0)SOTL{)VV5m1YCV;e~vg8F;Kcqz6DCt77aVqhMk z4xu|@Bpr%1Kc{@HGscar$OTFOEu|!_DhH>+P@%AigT$m72{F&bd+{jDG%{eA*I6;j zSff@+WTl##mCM-6K|^p#^2CM`2; zjVWocIs<7D#&%)p!h(9dey0_$IF>U#T}4W=+IohXqD@BP1G$nyHPqajUqQxH*)tGl zY(VOhuyE=fbo#IL!f^l*0x;>o57fm>%J>ACi!$MvYP{BA@nSV})Uwr_HnOMXmF5u{ z+Mb>>B*GowyUI5+eXA553Mta)fvabf_p3ra|KnRpQ#52pUPnQYzRm>S4EP z+=XB*ueU-t5@>MiqKB98rKK%7wa;;Fe!p+<;FYA%X~olo6rI4=;78qlD@th^+@>r> zg4H3&uqRRM_znXvS(VKivhRi~0^!TJD_jC?pt1T#5Qb#az4dhTuD5aS+dwV!YCeu= zwnc0>4QiL2y*X!G`S{m$7t`NQdW(wms-roH@tE;!A!PIBN5i46S`v{@33Qc~L%6X} zR`w^7^@FXOM$}M~p-XQ`m7U`c=QSmKD8qh9jQSv7{nx;dLW&gD!~unx7OO^ z-HH0J&(q$<;b&3^I+A~wYjdY-aag-X1uV53a3|+UlxV8S5^`t8AT>c~eoBl?td+|Q}DF>vVO7nI13F?k$ z>IGIAi{Z2{Lyzrxc;l~ki{=r$*&SpO1X4$JHYbM`H_5tmAfX7El9a*0B*x$Gc4LhY z-?p?Ml1YIgR8_qyWgp4%dGAD1D zs}{-M@SBfGIEso2&aU-dSr!v3ZO5UFN~3Kne^a>b4a7(~1RrD$cF@yzkTXWqrT9ut#F!9$vCb8zk63cPWa*|UpZY5G zQkZhyHCat9F>+E#XsVhRFd=CMeJAHz zaQZX!^^!7YR5Q0-x_3=YhveMQxB$zTbWv>(HXnz4jZJ2wa>+RNG$b8OwdO_T7DWm! zsB!RhVFdh#RReC4T3Jt&#=t;`_C*<9yJ0XsQCwLR?!)U<)L*jH3o?${@7G)WIUjE= zwvwVaDt#4GHs;)vz1{x+O$XYXeiT!)7GI;p=nT-JHAI73p2VFP+p!)O(*FQQF_${Z z5q{CY6&;7Krn0XuzE!%wlN|HqM9;3ip1Nz*ysJlsbw3D>s%FG|nCldIb+IqW$PbfJ zws0?J*h?mY{fC<_4w6|qSq$Av=? z9e8z6k%;ukFds(Q4+*EMml~ffNmGEmRJIez8iLfOU7qTcP@`}b)3+dpLAkj%1u02U zT%|h%!nPSPGZJbz-WwmtvTgM#dJ@q=R7oFUn1MJ6>#3bDudHlF8l{z~NsbBQkT^0H zzQ^*lvnkpR*0sg&Z3i^sN_JK_6;{Dn!z)tykMwhyG9xY1HswnA5MJla`BN+wI*a-7 zt-d_XJfUYZu~HF%Q+Q8Ib@iuhLl?Klck`P}!6*BZ$RzazjbHC7K7zDuz^dzI!xn0l zZNXz^h(U4~s97QeXwIY?c(3KmMYwDsa5}`#LBRC`>^1aK9TG}*Z5U1mWOU(3tYWhw zDq5vUNsqe|8c7l(XO(ede)7%iyIZ31PB_zKK}h|QwHyi(f#RRyl$hc{ zrAI@$dDs5{K%Snn9%1N5q>i9v{;~`?qKm4SwD@IX;4{V&dbPuFV@mYYC}~zjc<$9w zM%#><@kRDz-eGW)ad^;aE)N1i)5iqQ^v)h4aQ+YlV(wpP?XzYYD_Ba5i7+^rDLXn( zN#Ot>`Y+Yo!T65l3`-g7-=@rKubn}{u~_zX8zf>lW>Usr6|i}jbtOdfRH+qJOkz1C zMv^yq6tQFaJMc?;Vf>2WJ{|DYdyRI+dmgOdLRiDU4DeMgnIEOzksWn9X}QXE?~3 z%B~$+RM<+?^1o=kU=rb#orY8}I0yp_D5`qf=*~$Qmn8HTr1&mw#Qj6!b+1udfj)Gr z%+la=W)Sq)RZC3_Z5BH$gXStDM^QxzqRv)#D47+IUOb@X#n*O=co1|1YCKO`K)@5n z2#{-uJLi|!<<}zDFL_VtRCj~`6leGV{vN(05}8aI8@dtcqtSIIT)K1U!_^N(I?b2* z%hVO1p~PCdIMd;;xZjXomSo*xVfRa{2t=8F|8zwCpT8O`j?F6oV`74XQ(4N zR!NlxH$hD-=ql(SWszuQCOUeERjwnDi?-_!*7ICDXjGo@u_OT4ND4F8rv*Wi;vFD~ zp$_h|Z+P=T)T#rh3UNPj2B1M0M2rldS)&X19$=kN%~SOnx21hd87c7E`YOyX}1eDTJ%mqI9h>=%dc41-8b#}#nVV7Apyw1$swpXT7zU^(8J|MUx z6<{E7J9t-QJ4Wu%wgQ{gsVWG2UX=w1Iy@=yB&J9Q!-2wat)ijB+Vwemsc%8(^h zAG{LXeBDOo1O4~l(fN$V+JMz_M{f^sj!d6UnLef5<|aHLEhH4l z$HYoc4ujJ}KF+K^IhiT*_Ojf0DZ|IfDfiZ+1hUe3Y{gKwbFX^>q~F~Hckn&#dDPvi zo_zZ2ITUn=J34+{Q|vu8v#+vWFp#k+Z_0^Ld>dX=Rl!O|422`YfBM?pB$BWN32$PaymP_Hf+$bm5? za1v`(9)$ihp1JyW)ha9}tT>Bx9}TFjijNS>xSkmdIETF`jpCq|nh2_C>jmtpLoV@V zjDmUE+rG%M3+7bPEfC(M9WFN@i4qhQCk`WMBWNQE$PC|f^7n1~>s1Db1we%uIDZmJ zf;xON#zxxPt25#BQ$bsnF?x9G@XEN%Ra7<5M>I3VA`SHQP(9+4L$TC?Hv?ni&Jf*O zoUZLjX=Ev-s3F8E6be*8QdFEl!f-y(SiakYfU$w;7!l>i^sOO(6HiUK57AGq2(ZqX zuaT7TnmSx^j*Xq=Y8WcsNNQ-qu`FYXSlGl)y9$Cy7d_zYvw3be>vw~1Rr9#;#nS*{e#3+EPR)c4L7*?WWEgSOSGc1%tH@Y(_4hSTh<>U9JG_iTxfe3W`g;U2YYKZS08#c^yO zslJu!ak|_lgE3)ki!{`p^+U%?5vRlw2^2F4WTktk3Vz8}9vm|K%Zw1D7)b_17?jF@ zjlDAm7#PKK-?t2qJi{4)2UBY9mBtdhQc2nO2=%JG^yqT8MLkVn*#|Kough>^IG$Ok zdWfWePlncqrGjUT!n#=`N7M_EeK_v&B<2>5Jde5(@Qh(-#a{!54Vch3a&JNftbcsT z@>T$KZ31e-GF~T#MV8G6o@f43G}ucAi0&eqPbwz2+800#&bG1UB;T;E`eHSJ;Dd*V zN%zhbo{S_E!2S|b)*}e^R9w%RFnTQ0gUyKI(9KneM^QkSc`CI@4KkX9mtY&rDmMcw zXfL#prxn>{?_DzBZL&fLSx}OaPlS$%*mR6=n4+84TV>QGN&!m*B{DS-2B`yV3}r_F zvS^oPEXRuasp+aPd9&4K>s7s?z+u1c?+73c4Wy7jTDZi( zj3k7p_-EXU(R`uN+z+T3M+2K6;5cP7Q)HYvnaXC&My<5|ZHUx@e3UGF*#d@XF0nZX z3i26qJGi~Sai+*{$PcYV7Epxaqz#Hu#WFOd8xb+8nq{;bX2cfK0Vo1e=A*L{IP6gd zNf@tgnr-Rk2Av^%Cnb8DaG1=^43v2JU@*G&lz{~kx`mE{zDXD>EW2ZSevN@7a3`4q zoGEW*qrnGLAM2>XO2EXr&=|^PN&X>((2mK~WvN3~>Ke&}z5cecP60<^96KPuQTtB{ zJo)Dp%AGLFQewHbs*eP~sK67{RL-=}#?gzS7Gf3eb7dEA8*|n+X5faJ1;r{bOsPcm z$Ige(yqjbdxNigDUXA1oHm5W$BGLZ{RC$~#-?{fQu-M*mKnS=rqvIv3|9uxvNNmo#;N8e5Pu*~fo zu(wHjSOdI`Eu@1XNuLtPi39+ivsD3Ig4NVRJ#0Wt9811n2`w72Hr}8T%H8fX`Z<;9 zx=Kh%z?=s`BcSjjqitZa?NtPfK-FFJGX?jEH6RG`K$#`aVYRoqW%eae7AfBSD zX_!+TwF==8nwT~AB#sDoDu@Z>HJopSu2XQUeJ(B3#DJU=tL=#+Tx}@?5G0ZXPdO&- zKbhMh@}wcNvQ8?D6fhnc*a_Q&3b~Gs*X0aX1E!{qOjP;y4b&KIxo-silFNy$S!*DDna&rbX4R(gpKWB0ew!s92w?$ zg^Q%23UOs#1gS}cr%?N#pO;lXZJJ!!Fruc=&>khFqbqVhgpuMn#?ohP8GeO&YU-VR zEct`2wNqhvrxUNMndm*)C539*@`{UsT(Vhqld#wij{%vxtfYo*5;Pzo0FXrJ*g*aq zWP`V+fmubB)?|Y9@huf8N(jK1R^48h0kaL1bU)c&qo3w~{MvbO`TqdqeD5ls`G=jq zb@%yp-?vSc*=;*(!oSS9-goni{jy?XqJ8^jhTqEVyPwNw@W{fYWER>M#iU}WBpZSTvfS-!d%T1anBz4z6;D+$;j~jv4K;l+ zWR6KANn{^t?PVTVU)wSZyR zU92QqY6utO=))SKv7;yHOCg@Rbz3K7YKUH?*{t(N0)(fEox=c2f*HKgVY@3lnD$v+Q);$QJU9`~+O8g{^dF?z zKdHIbGy3VxnWD27&TmTw71Uah9ZnsBRYr^yWB6Q1q7hO=X)}Znl?x z(kxp*Z7Nw?NggGqfJ(NN&M6p}CMF_?4TCF^;eudlj0czyJ)$s)8$nvcaK5y91i`93%&AE-=i+n`*n#DiQ#(%^8?+2czN!e* zfg4Lt+Y5F0Rk9Rx0#3;%06Gc7rwnP;J`$}HrAK7!KaZtl%H2`Gsk5qMnR0wLGeKEP zyAI7%xO{Y`dN*Z}XzN;K^P`$EZ!#;G$x;oiZXP(5TS^RwFj7g|(gx36y<}4Kv{pP= z9*@?Ce38^CdO@0}>bFYj;E8KMY*!DdtPM?6q4#-0HF6_SZ*hmc8xd=QSAwnH-b=0A zxbKN6h+)B;%uVY8hT-Mrr3_#3N9EiMC%pShLsAP?X?V*|B3 zKoDH0W@rQuR0INW!}==z`=Fh?PRi93(Ta&p7nI2ok{l7S)zsO8hSgn2D#JpjLOD8; z2$6_5gVQ`{07RHIcwdCBSgYv1OwYc$BoyYCr}#!Ii_yVX8ED?R0sNx`K{RAb6zzyr zOEg*(aS0@72*us&%tQCR$k@UG+JCw_VKE$1Ai?-l$CNNFER^!6_Nvk_A8I!3;7pB` zP!U#Vj+$mq>r4h;)6Vr(DdsD%oI=Fgf3J; z5JxlCDB<+hT%4p1`oN z3teu*mhs;@0NJ%fdF|QL(M-SEHHD_umj{d>0p@Y`&~1Z$D0rQ9N?~-_MoKy8Swyka zSH>h#32!heDB3`{HU~@GUru@L%tL7eIWxp34~<=2pdcRuC)GpbDJj&?RlPv!-eAHp z+|idKubTy~!?6ls9w9t_Q_)Oki6DA^E#dPRl4J*c{{Yn%=dCi9^1@4NB0&cYpx|e& zFdvRIRdc>-z5pqN;6lFhfg2+ZzCQ}NPf*v8wew6NdEwS+6eIqtFOaH)V2@klhud$!}T43Rz-wi(@%jzfzsBYn*_ycCQ3-_ z;-#u!Wu#c7A&hJdtb2=b(E1%Msj^prUZOPW8cD|k3K;lE6VfSGQ*dpTd*28oASP!? zBn$yFq>LnN=&kc9aJtGI%Q|8x(X?e_M-pB+qwnS_cE7OuIHg;8+0#=>P7y&aZLUh3 zMtZ310g;IIk!u6>+lMU(6l9&02V>KfQ?kKc;@aQZKtG=h#a4r|l22SiGO!BPW+a`X zUwcolmnNuitXXdfmosL3KL?BarFBX~cOKi?MFcoXq&0Bu08%K}u9aqf*_20igPR7vL4=LoXF@ zJAM=R(d%u8Q>4*L>j$Y`jr5|bd^@Yzx`zpT9}aw3>8E|NQP4ZGElpO?NsD?i#^XZ6 zXt}o}?29#G&}ea3sv`n_&HO3m*ZDHMJRky9BLF&j1yZ+Ee;BVr83zT=Iin$GRm~WV zWz2E54};~(5kiQoNlaTXW0Tgw8&uTF@sxAFas^1^OI`Uj*zb_alA?s`@px0GP6P=m zQ6f~LF`3u|Mm5h))w?;i-}}bzt=~&-5F2($Deluc6qJF2h9Kesrb(2+H<(A`KjN+jQ=H;VRib{5w?5L79K- zvZ3NhO0^{a07gJkXQ4wARE%FcS`(A?-eUaz%&K`Ctx^6(smg*fl$i(H@(lxj=GZ4lc{K(KetngDk&r! zG~=aM08W#{(8JdM0K~)a{{ZzD){dL>JEFZ>cMDt&gU!RR%1Iua zh@PUUqu*%W@~S|^3tTmu=WOOqu+};QiBVRS13$u%g!qow1YkUYb84{%YT&Q{qWWnu%#6s4Iyh#PL=A%NlHWzHEJSG$}3-nUr%GqdDA!MUz8Oz ziAP0&Q8VEaRw$mjsUA^BEPGa-x(Y~q#Tv7rDx*?)j=imBJ<|+Z$qG``;($;DgoqlG zwMi;b6R;6oX!>T$b>{aMOxKu(~g7{G|#CZ@-_mH3J0 zZnDcmCKE%2Q)07W)5j$E6isv(MGamZ8;$i5Zf1F4M%wY0+}lCmD>t}nDBYGV60oJX zq-q07$dX)AR~R6~0H}~~7~@iY?qwHy$J#TuuQcgq*p!95+T06EErxuP!6sX$aL_o{&*IE4faraJJV%^~Tk1 z+LRKdq%BDWNm|@qfT7}A(;&={1pXtqrFJpa+y|#Pq%y2{CSRr#Lp?n_D;-WG?TE~X z@o6P9-5Mriy;SWWE}R^8T*u|?9JmJ+x?ss9r2|OAfyBtzYBTzi&C!|XZCfG~mYPu{ zDM|%PUXiO`+OU?A788LZRGB7>_u;XY>ax#6@f__)DygY)+{ZOlOVQR)!RAxt+A~(A zR-hSDrU}`kQ=-VXj0S5CMZKrqo4mm`!U=7ZjA!n3T{|GA2S_!MzfCz~78ym=>z&x| z94StuI;c;DqpL(DwzI7yVx*rLDNfp$q^HeYV(Jxh;1th{W0{7wN~aKu5cLxm6BloG z6dQ);a-d$rw=&beV<56Yc|o??Ku$Q$l;Qx|qD;U5o;A#`%U^bboWJ=dl>7G&IOddN zr6os7l%s+hLNtP<5C9lX$}#x#_yr1W#tQf4@!rJKvaD|cF%TBB)M zqM1Wk)s2WJO>G|JTlU6vaI0_wa|Nk5x}G5L3gQwtVYa7T`0P^mbaLji5VYK+pe^E! zhzgI|G?NagloAl?)|8Zz7Xbw6Ch@~HEK$!;rYDGq-lWE(9~fy`0Yu@sOB+J%SjK*#agq`C(MbX^Gd@T zx0B{rxBwDyue57B2xj*4y#y>b4XAk1K~YYX9U@~D0jeN*X76Ho#&E^cwmCs*D{(0y zZY20hoI+sf`_QBJAz+;;R)Ps3LX9t>k5TdUK|0mdx~#v{O1SXoGcGGhk5uACYoTXI z6m> z^Om>2w=5JmrGTQ5B~1c?ge9mYw3HMjLKMjqZT(z&WX@ec!`B$;1w!R~X9B>mXfaCv z0Gz3Veic%Q^0*tpNlLL3OFNc^b|CEc3(0UyNxM77##<=8Pk!FAq$fyJIRadjnHq=O zoIyCw6_WeuxL2Fd8D32AvbcFpvZbX(w5^tkl%Sy5QB>ek6Q{Z%T0lzFkV-Kh!(Xh} zY`EOj8Lt5~xD?o0PT?z>StqD%$h)ME{JbSgFmvw}J6POuWd8tUTPO+cor9hP9(5NvI)aW`f={{WX} zHtJ#Kol+E;P%1>g*sWN?#?YuZ<5*deb|Ic*H;K$G?=9MK4Jr9b7Xb^9rpf^c(4b5~ z(vSg31t5YG*IeJ9`iayma*L>#PLfhFfOLXM zDp842j@oPL-eAG;9-w2{j{|%rq9|x6C{nvGQ@s`)Uo9m(RHD9~l0;UB)ol+d1VHj` zkO8=!NPCfNwwgu% z&6|nPg-|?i%p1GR8OxA6^mmC_BSxa1v;tH}nZaH}&y{6Eh&MhI@s0rWk@r9mr_5pJ zR@i+C{w*@GE$ZpP(%@mWHa7NqnqSy>RE+m6Rs!4o?O%mZW$%tB*pJ4u)A|hjSyY23 ztI2kYXfVp2B;biFBC($3_Rb~DmodNZKlsbdbZ%9EYL@V&ox{aVXI)^8B6(=0d)$D2B!QPSY2DX(w}9p+7b@05mby$oOXS) zBdf}hC9;<^$BO~6Ae`l*&kFwl$!e<@#dS@GWc6(vdzAYUF>kApE^zUCFi;~D z!cH@=0Y4fMKB1_PaMGV{C*~^GXz9MmE2rdtqk`*vB7%-DZ9S|3fVlA&9j$-Y!-7Pa zqQa=GMmJCmtUN39~W$`ufnEHtf~uwy8HO;B}dsFyOgv zjePNlV)#WYF_*IKnzk5Om&B5!f-TzQdw3eO0K5Ui1xb!DNC&EMtc!Z&vdY!{6qD=+ zWp9s+;q>%al~pY^)s8t#YJGuP-TPQ@e&PZN1E#PR+2ZOFrEMa8qKJRu1J}IA>A$9U z7C)70Cd&Y{Kuf=pW~_dL0mSo}q-wfssfW}XO^eGIR#7U0wv@Q?mQrMLN-D9U@R7$Pn#|j#x0(B}0G9*p| zfE+*~NR6owpW>^Y`|{|xO3GI1^fM50y3pG%~Y{rAtL2GGVkhew$-9dY2}qR(4^uw?J(=QXxD#=VG|d zt)Su#!GMZ$IzsKA{J8}!qx+bg79dNiIBQur8T$YN1j#a z$K2ruALyhCt&dH3SjYWH^y2{t%qp`s4y}7_Qng6-P&;V4>3`$E+QgxA{S)Rvz|Xd% zyvFakw_3UquYs+;@il6UZh4s8v$+?(wjnyGzU%%hw~dtd(CRyVJW{=tL>y=Z&lK$Pjk=rP+4}t)$DH%; zsb4Ex3Rq=aCZy2Q%(2`ZG!_~j4)SY7DYPsK4&U4)EkbFJs{MB8->1A1mm2GqW1`Dc z7_72U(;C%zK55oH^1_hE9ELz6H;@(D6#K_e45ZU4Aeg{y!hTdj#iO~B`@3`(6}A#U zBcRD5HW(nxil;8D;-7&wX|9to)62-3N?2Y?5?jb%l#C3I{w?V*70i?s9+7a2&x7DF zz`~+D&tFehEVFMOT=dHbFA{9~X(O`}VxRzSS(p}-uh{|*@lKeYr~rG<9C!)yA~}Oi z5tz8j*CS7Il_UWeg=!~JorFdd0?R#1#KIS|odb;-mZjC}6_BvLmSI`f^vpXs!F^uZ$OEVJ2_a?)K z>$-JdCsD(!z8ig3;V~Hc0HjYT8Nn~~M>L6vK{xt*57WZLCmLS0;ZHDAT1MNcHo5kF9?lz~5NNS$ky4hJ z0LTUOARgVjUy8zbQzdl*Sddhc;o?X?uYMq0O)E;gHK`Bc+k|F36W4ZYuEgPz0gGXn zHBJ`APRfdO!`2Tm8~2qaM@c}vh$FupbV^e{Zyv3fd7d40pM9NPw!Engr1+4x0*65= zC)oraA}M!}u@Av70Ld6tR&v35iHT-kk*0iA7DG=FtMb?81Wg2yL}K%AR4xmQDObmSoywIZ8CeCieU1ntih+(v# zY~ok(p{9e>-{Lcg$rT@_zKG$N1tES9d}3l^|Kz71a;H#0{mb)8;jFqZoA^O*&3r5p`N0IHVcQ-`LNu@B-FFS zBumCl#K4nV^!ord5u`n8-;tZQ5PCkV!rD7d@}b34tf8o_y;kk$zN3`PIPw8a|gRdYzwe zKT$Qf{t<)VSvM3iH3Zm{BNeQ!iXiaC6$>)7bnax_W@GOFRTQ=C8oWV6E+4p*kN}JZ z7@TL_9cH5K_uk~%vHZO)txI_ruS&bLq>>Ma0t&=^qY)sO25VqS%r;s~T#3O~7C!RW z>NNZLjT$sLSnS)u#_-wIL)I5ceqIA^>c4sBN7^I6pCM5@?s$)#E9q&$O^th-9eZEI zd`-A7Z8JgTt}&@%A^?rYx8dSEc(f)dKB>f1N{G~hyTIFxu9P6sXESB>%-LfV%B@i) z7{##q{6FR+7ifi5JJb2fE-qu=y148#{Aa4) zglA4Me2LfJPPjgL!K!QDW_zW0CWf{twnt4(Q&Uq-RFFirvPA0x24baIh+-viX*>bI zorZn5gO30Lu_X0mUBgXp%c*kO`Nme1f!s+>nA)VJDnf~fl1kG6X;f_?ST{ua>G+=d zgUmUL(q~F=ythk8l#H z1c9()B*dP*rvboDAJ6S~2FTV)=|Y!k903FZR@%@E$ptD<(xHKvB#a~p5&`9IyY+)5^#1@H=+0Ek*sd9qvm}CC zUk9bGnP@8HO_q9yREXS=iMZGT6ar0v<+ZFL0**0+kv$kpc}$v6^A?vE2)T8Z)az0Z z;Yce);6heJfr-FiB=I!7>Sky3@r?AFCg8m{%Q)r|STwbE0nvBldPs~awtn-M#AVlGm zmfXvr=bLpc;-rEji9VYM_<_LABA?CKcQ9p4u=?%PNS6>0Q~=rrut1X-#-YH8p;y(X zs2+oQgvPLZ&C;Hc;k_rSr-o$2(*&=YY8v~p3U*3KAw+^mY}?vDwhftm+wzY(9Q#rM z9cS8PnCiwoc9U-Xoz7B~qU!B;V31N=LPF8NjY<2#!vZ`pfrA3we*~9LEy^M3KQVH6Jh} z)|q`A{{S#Ps5>I{=iS-x(O9K$kUQBx4Hq*2p`Wg(G( z7b66=Qzat_z<_oRk~ZwdWCC=+h^fx%?fkKnCoE|y3K;l@hH(TV4Ra^Os7~24HDI+q zsXqcwPVtIPl5}>ns8v+@MOlbZIae#)g=RZZ?~fabaen|iaS?GQQgH_pj>FJGWRLWt ztWaC>S>@5x<-%Fu0(KGPkR$y$^QzPJnd?*2pQx)fFcIC&gfD{v@ zBw|WT6;B8%j-qj*rP2c_?eC{Iqai{HnK_tgMc=Rz_A= zQbyhukWjfBeQ@A5ayZDPZlxDZ7Tp0zI24$LamR@2k4QCUG~bRV;!WoK%?>?;S0rBZ z`57{a%t{Ge^7#r1D|fxro9V+;+!MDCGJ!r`0gXo=*-W`#!npqcZC}1sh}nkNp;M#3 z@Stq%Ntr3BJxgVrBOAh{XwssuEtaIj;w(tt6$G-$PgF&pu$W&|7$@ST;kCJQAdB}Gk&(6pXKWDrzD zWsRbJlEx)LBvJs;zS1`%0LpHsQNRKdj^A1aDa}I>(hs47`W`g1f)pU=d_E)Falryo zD3NNXNGZUU#CQF^Aot>=rVS!m@TfSw7%Z}O0FM6N{v0H}Z(-}DHtuk!zbLy)5JtEA z`|zls3V*z=MvZJn(r=+Z6XW-DT6Wfhm8?JFn>SWE3;3>dd#%2oW1%_AG2qmcm`dVd zO%%29RLz8lD)+J=id3jj#hq=Tza&hhw3~G#$N_0lh@5zd!}u`-L=!Q#if$a&2_N62 z;zWbu!Z9Cq(Tsr@IGAWl_N)FU?#&()>1*&&tdTK`}iVKEfa*fh8PCu znJ=M05ENu|yXQW&4q89>QYCv8^Ezilr%gYWx80*y`+qKM3qUdN51)5TsmySn{R>5h z)(1p?9e$?zWzN_KsJvSsS7d5@HcU?&qr?75DF!hB(2X=kU^p@to_2rd*p} z=?AG!^h}NvKyDrGR8m9$3Bb&KqaBlmF~SMkR{sDmr=R#z<`WuMx2SHJ!fGQi zh~mLhZS*Ao{#UCJuhGI5lb2;_4mO98tVe~wNf;86G{-^o+fdT~055mpP+1_()A5;# zFW#a(CI0}zgsU<|7H`iUr?PCZP)L#_bT~^>w0|*Z@40ZG2wRJfhYy9$T!M!kX=;?p zbuM&+7(@Xl4w@0<4<#Oel ztMR%Nks+=%@o!m`S}3g|n94ZV2H~LbGYd* zDGos@M92|`4`fHOt)uXu^l^vRbXO;J>jcE!yBf~&;`DffKs=_yD5!(c$gJ*INi=M? z1ORU+9vsZg)v!X_)`1EuT$8X2Bh!fKCY9K}5WrXQ0morG1|34SEy%cD8Ix(Br#Kux zD}>C8uy}t+pdTCC+4S-{-bOpbPfAa_5koA3E%`_xB<eM!%Wcba1`?hikVl>)({2?5?}G*AN$7$)f1-XOwF323(?~ia>dUBIF50kD zVR?%aNMyMH($z`xPynaD=;a$V2LAwOw;)~NwKmsIB4!DI1{f0_SVWI)cRRD}CLZPvOvYMiY{i^6=#u-eUobFgbMC%YS7L-w?~{6XS;iDeHd z2LQD62*clp3}Dmy=-6GmPhlxkPN_X%BVotxR@yQ>G|Lzx^y>_*^fObJalX6N1(K`! z{{SsE7bY1ZkWze|4k7;dD=I0_muk#HqtAs?Ly;ul)+A3*!;g0GD@CQ>?#;3I1&gzIAN9|=(k7{=FSS)S_Ur#HDsTI0mTt5Q&yfaf>@R+}r%;GYl!0 z($k4r9a=)0N>dUFiqaB9#0+PEkSV{VP~{PW$CZ5*^FfF^OSrS7v=@8yjrI?%V) zgWjYj1Soxq8wt{3Z~!Jm5l4fr_-;h?ZRvu$5$KLq>F#XKdFBduv;KU}c%~DQ^ELro zjAf3prV3FESd~2IcFaNtndR7?d7Ny2(TRwR&> zMRHfPUe51rZ&bydhlSHEsgk!-0GRurwyr8nqzLemjijRk#j;PP3S3(`WqkWx)y}qK zI7?tMXUc@mnxEw6rpr%={{X)nLcQs?Q!RX{1a$BgN?3P4nhY~+`KzE#$7gMNfl3)iA?NJyiI5;i5{6JW9VaBr{6F#lUNU!d7$Z zt7ekYLo4q7-Do6?cq^#z93zf3P2l=?bNr(9o0Tm`TGG;60H{e&KvtuP7y|}RuqC=D z=^C5TFG>1=oc&H`DvIaJxV8>5t`pOKvEkHfiHRzvr>n%iPYwCmM3DJ#PNkw>(Y2U@ zw&3?X-WKk{6>b|Oh*4SrAmgx{V`vA42C;8)dne4Zo8xJAi;HGff}rVZ4MHI*k|I)Y z*koWQ3Pj^Rv-*jJ`pw7vXL@#owmPlm^RDoq9 zTsOJw7b9KDT}OBu6RoXk@e{L3ps67}6XNLrV+cLjd!712PoCiY+Q9EX91^6!$E2i@ zwsFFN`q9>Iq56vIt}oU8uVQVBW-M-0mab-0MHW?#2w{l;NTQB42#5d*fC3MGW=>m| zGm~4Q+SLIKHZ-9iU;x|a)^?LwQI=)wWh^Gyfu$%I3`xgnB<&=bB<-0qNGuAM2F0^I z1{Im=K1&Rmrk)zA!5;RfrjkMC$dM(>m5*}(ps^y|&kq66Buwp&l0RP|ODRRK$`=C%td(CsE_lYhB;Pr`AVK z{bKr$!m)mgRn*sH{IP)3VN?>;Qprg2)X6Nhb(1YTp8D>Y!hqH!AU3tR(Js&TRPJt4 z)r!a~Nh)zk#1$yXgS4bf0zkkF1jS`0;be~F7V0+%33b(#CEbE`CA#| zDz~^!q~J!`N#LZYViXJ+2dk#GFzD~&>(T6Tf(ma@T|UL~?kW{pO5Cv|RkROb{#9tJ z9x8}8Hk(AU1@JuQc762mZ*ZlrFSyVN8c^WW6F+d&B1aLl)+pX~d3wUX$<~JxiT$UA zT|!a_SDuv7p-;v`@X(f2&9i0J-Y5T4tG^gPLaoZL&vRsGUCyb6-aNm1$wPyh}D>GJ8LmbWVP(fd^) zv5v`7glxcoG2meJiq=2XH($D)>Zhx?w_AF@R|MF;E~mkErvCsN0teXw`h#m&oA8$XrCPqEe+^o}z|E7Jb}R_giz>MtsFo`l+q4aBLQsTL-Wbqz=Q zJ!-hysFo*d1Md(IhZ6`vi338> zsXx)utQG1>3iYl~?q%x#050MbNO7fw#~BCYQwD&n)6}em4m}2EOiBpqvtAQTidEt4 z$s1Em7+79LVnT$NlEUY>KGDoWXDhh59oRvJoGpckf(|jq5ga;ttE?)`?b*`fiwQ2a zmo$e*!5ha@I!D?{C(fQQ;HAXhTUjl@t6? zj}iqD4yb-B()AN0SLGg>TR`v)~MBZAYxQWTVMAk+h1({KvH4&bCo%!0{#&UWKGj_k#t0oq*`7v&@;7 zsGV4?p`yoYaV*(ih104-Ow!a=EhGqTrV4SrV2UNsumM2sY&n%|GR|C*q=Yn;990QP zQRpf#R7u7*&kDwStDBtNKscqmr0h?LK_iBgi3tN_>;sM!V?8JQF0uT>lj-`u>Qg=7 zxeF{uB&A@ErE4lDjxdbDDrw6@v~B^69%)uK(S?L7ns4H5R&DHAQ_dVUE5ZW0oBNb{ zm85jk+m>zu-$;J>)VA2iLI_fb{{SED1N>b_)~n;J*-Ac?^@9@2*)CeY<&-iX<MJy zEv5>zCJSXiq?8dL!Nlni6W#=Dpw5=tubcHmS#uQWgL96;ga2Vh#AUiy~a{Z^7 zZImdWg~pL{x*S6!w$I!L_vX;CNns#Pi->n=<0Cz@kqvFpNG%Xg5=?<0R}rGR@gHYKlgN-OH4o@j)Y|eUzjU zj8%pk2R{m1=9#x_S<#-)%x! zx6^t(&%AEl_KY+ZenRM}c$#>IK$wj*DCVveCT3WRB9%k-#F7FO8~fmm%b*~GepxBP zY0zuDB6{pnuvbA^3q3*e;}MAwi8extwpLQ6*SN8{T`oAFrUh*{)$9HceIlx+sK@%@ zm{r``N-r6#Axu@33verxfw(9erJX+8|lCp!jwTfMst^oled5)gGHx zwBmR~w8kpPvi>JLGDnBj#acH_Hd!wqGOTV4eU8=KIB?!et>wJ5khKDpI3g7y0U+Ts zw8ZTv#f>oG)PRWv7#KT5ObHn2#E?3As+RD+rRM(tOdV&<8D}gQam30MQeoBDo*Qb+ zGHB54k>Qpx<+U8@-sxfP?jT=?FZXZrAR)q?SdamnW;XF4jlac&#YGpE-r z5giAs%9MFy*Nz3y?ENl&=qtw-UB%c8b12r>z`L)#sF>IUEN-7YR!{@np5J4OMU8|Jhm?si=&(F(^R6ne2t)G1gejYhv(%(_A$gqsX)J)YqRxtDx z8>4&+EktN=d0uFV_c1EzW~xy31Rbt73vxa-Yi-4sNGow=)d&U;+K@VvhzDtaU{HrO zcsFj_X!}q!bZy2@p5IuiQ^RpIp{g-S4%jA7c?qz!?YIvSeM@%lZh1hF*EJdg2A34j zn~>sBvuyf*Z4YI84pTrWSgE==?`f^rb+m*+JG! z5N51jqrRu;I;n|MXJ}E=Fj6{H*UwJDW0p(mRuo}0Xv{xMqju6SeWyj~Y^%bt2b@RB zrrfhTPGB}d(mY)Uh68MLjAP1-&t3g4FB=v843Uxw z)Qb@u#Cyib+7L#B;VxFG$Lpy1V#i?;i>M9#yv9-lE-$$Mn0B^K5 }si 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%0A0!16!L`%=5h0+`LL6>60z7Z+{|jHtwEK|xU% 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

HIAd_Bg7xjsa^ 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�$=NIz)#P4o#bDcOP zP7?|^s373eV4Olw&<99>2__`XcIUIr-A?RfjM;z!klK60#ZIflxhEJ&IzZR}!j0e* z^;od1adxIgL^nDYv0-c2-ov=y>^6(5uJDO0q@)=*Dab0qVBi3f2^=FDoa5U>;~IxE z_1n~)ZXH!TXCZXXY9B6)Mu+)^XesjodF3}_1``a3QXyc~3>~lKt%Lcp#p3?}Ewsu^ zaEx@%PNf2)j0B_z@e^47pyu>ujwV61vQh?^!OOim^%KP`B}qDVcaTi!z{hnXs5u*< zoiN5apVTVPlE8B9B(=5Eomhqa)CcX$E0Bo2*_aOek}}M-ZmAZw$tqgZ5|B2jYCL?- zB=7)}fT?#g%$dmTS9JM=Hkl`BCx9I)QiuR?BvzwYE2x>%)hDg!{a*D_0?U`4Hz`JXA4EOiu~NMyJ_z}_dWTSm;1QggRR&gf*QeU*{RhJ+9++oB0@R>K%!mJ zdGnC2_1quK9M*aRTN_Bgcv9MAPTfUE6&klrrsj+{DD;CX^hXmfi$x;7C67XYNcGhC zaTWD+uC1g005!#=hMWVT4#4StS&JiiaO3eG!j7#&NFx#b&9F||i!RtwElN_IVK7Q~ ztj?g3(<;REZK8SUW7a2GF|1ZDfck^<{{WBl#;PdmYMP>;VO80AcFJdTf_hW3IT}a0 zMzH`7W2N}Q9!>kCA-9@3WJm=N004KWR+T7>VkF}|G*Zr2t&;i{+ldMZAcBWNjwTyg zbr233fryCcqmNDNb0*+@My=`g6PPF_%#?I-R#joMmU&~Rn3EK;5H`lL?IlTINE}o* zal679!(ZK{Do(iBsG@ZQ&H#}Ig%w?9U(5V%IF`iem5>1^fRZHnc~Sbov*mSGU8BWu zsL~3Gh+~pOjIoUijln~=e{_!gh%PeV)2eMafJnwC4xvjL&PtmLUml5$tWQ+~-E{R; zk-7zz@N8Q&rB!`iWyPs*EE^A?j7d{lUsHBi({TwLamKAIvbhR~q@Mx6M)2k~`>kUB zWq5S8ZjEb!Dm)T|3^grh1c?~!AW>c3@QZYSkW{5kl!8BoB$99dNE3-9fCQQwvR+%o z`lXU1&+s%@dQ4{WR-_i)6hx_;dUjSImD9Gok9SA3J8kF7)0rWcS!G&??@9u+ppaJy zDo&gXV;`~B@!tTWnx*z zf=D3h{OMiVksztMd&e8AFJlF>vTjH7sOVV^YlQ z!Fz9!$!B4yJ^OG@!A-K3q~WaUQRy%M^aB7mPy*~K{VgHPLut@~7$g!&Ab&|pB&h8? zc2jOIf#Q>3f7K~l%)@4=`Ie`Z6~9mA`9+1Va5x1xD=8D7-Jxoz7aiz&- zm4aDs$geSQGWyyEbdo2^rYyakcF27~H30y1(uW($(dGA{p-@czSZPJ>s&9XH!v6r# z$Tu~*)JH@gjZfKCpKu7{g!?FA$#gQyI>y@k00U)GR;Lg zMyxj#0_NU6KX)Nq#m%wCrMqiY049bkF9%Sl3T@gw=Iv{HPit^8+ggOs>9*pv`Tqcg z1a%V*i=$LoS1aOlwQEg>RC&UhqB(X?Ur`-0$0wFf$vm}U6|8NqZccllmz^)a&;kZH zg(&;HJUD|voWkM1%re*@f=aqU36t(1W5Tr)%Xw0|R9I0}fdj`)KaKwYk0zGwibW8; zcoulj*O&4hD{nSP?HpsV_K|%w)LYy1aK#NpATG@*sPfJ$C44w?L%p1pLvW<`Ag#rT z7PY)j4;lqDM(NaO&-xVT&MVb_Q-ja0#PZZQEhN=3;ut)s9JFsNf|VzlX;q{7Wd;1e z#Y}_URs`^yIJ@r95Txo0F#yB?i6^K4u zAdOm1*jGAp%hJ#HB5H5?$zIF4pxDj@`w^4Uts8g^fD_U_(1G7_PQ z^P)7|l&U}zg%@ zqK_58>SdGVYN_HZBo=m=;}%0q%Id-zj2rtSe{ql?3$QaHc!`CPJ_h2=mz> zfM@a9Mmwh-uk+mXba>8W&2VN63SF?AJXO=v!&4mJqo{gxg$Ocsz_=kr;ZvdVdnX_ zMzyLcq)+lYt_pkQj-uLdTGLPH?wwL_c%6DKz!U9 zt0g3IipYf==``1d;Y{w})Pyqtje9P-jv6B=N(2RKoHj@46qU@uE2Rz%)c&<~0cEej zv3MU9N{2NVO*H6|JPN~XQVCUERg(62$x-z2#O2L0JY!_X9)1)Iy}WThWDz*JCrprYj{rDb_ zp<36fj^RlnCQXLc1adLV_a^O0J?TjjVpFJkDJDSM(brR!?{9`wfTygkNKi;p!h)Jt zM36~HCuRd_7*YDpzm3ILS|YFM=T7008J-j(lD3L!JXJuDty4FUUJ0V7j2CuO8z`}5 z1Br62(Y4D!dElbpPyqr8RVD!h#?7Q1fO#4#-aYuvbCcXL-KO1XB)ory5>AC^QIfB< z1OOCF@FJu7PV1LTx{T2Dhp5yrRL4s$BQ;)NHNk407rc}v2!Pcs?z`@7ZKnm9%L=$k z-a?W{ASJl)z%i(+tZW0KjPjh??;&-xCtGM*Le#LLd|GjDyD~f{X(JGLQH;&Gb1&r? zjv&Jx(rhf=)w2(1;l++e zYny^?)|WshT4WM}AWQ==X96oKa^2%=El#(Ig#iU4;ttPRW9aweS();EZX1{S`+;IP zl7^xLEr?;*Y?0T&a#RYK2ocF3wb(72*?aIenRb3in|1h(I#gtNNZ5J-q53zShYTqW z4zPoVnEWXF;XjOjqP%ku7*-!PYpJbe+#ri6;xfv>A9#d~39|T`awvCmGZw_DDFgg* zMhVWX*RZJdcWa-83iUsXSE4MhhKyGT))>x#4t10JNuu<9&kiT6QY3>7f31Qw2E5=PcN zw+yF++gLW+uX2*5}?cJvOK4ZjUSPwMTbRKbHs%9g z8{4-tHFl^@!T43$%NhQU;YvC@4-0YR$p9e~T~lI>MaUimkBKCX6dN?1v?*&ZLPT)r zp?{{CU}D&}`JK_pT)8(-!V87Wy?YOo4M-L_p<;ii@Y z!u|N-%@VjKkTT$uwY2n@0IEw$+umm85s)3Tr{|o6wOi9%7k9(N`~*>UUQ>= z`!ToPWNA}i_aVI#A_7i+;sWWiQzQsZ^l z1so__aA_(tjZ~5?yN}UExBR&uZdYTrJE4Bf^I}$nDOkzDOa_OnPRuci5vMv+=~{Sc zBi2dyRp@7|wCjgbQ$zzun-u#_*uv<1dlAmyWv&F68#IXa3g-jK)JnR^_tk%35Jl9! zx#C&)q5fBaQPg0VLyHxa%&2iHw6|c+79f08Pq&im4(Mh_^uApCCn9(iiLB6J*g{=E@8oW_z4Sa@4|$JJp`KDSG5&JCG)L(nVyN{j<9+R77V0#y zZyiU`_wn5{BnD|&harL4<+*U8&2UJ*i+gE%-r(uR;tgzxp;rc}o=FWqo4l-U=lmoh z+@GX)pJ3v&7^GzrRZ*E|`MStKCDvMoH?@whp+60HMB&u~r2OhpQer4#$v9JH&ZA|V zw9CKwjxmH&6(LwM%Ucv>K(}HJqqVub{r>>V*}m!i23%MAR1<{=8Sy9%k_Wzq{{U9> zI3*vfeyU+h38SQ@%{a|GK1zaP@~Rp&+JM=VZSD0AM*E(%T;%qSD{7c+UaCydwc!bU zW1&WZ8q9}?MTE9$JEQ)3Lv^P6Y27))bTF?x1zb^th8u`Ddz?{Xd`>MoYaeBNLF- zF1I_Ci69~DEpu_)^9{2+jTw|B{6c39p0y@1c3B<_3FAX1A=SjkGF3!#86uuTc_ak8J~g)Gh0#r0K#FqZCh8=8lI@MGc*!( z`RGjUgd)88f@wrCG1P*nTj{?hq5}?ETBwakw{bxuZk0U}di703cWifyQ;8TUYSemE z5|BOBxn?n!u!no7k#d|87-OlUiAktbyqhG25=D*eaLy10J&mu$8j3JGK#yKDithZESGOEJ zM<0y~*~<=|oiPk%HbjOR3CF$-l!%!Xje++-H*XsQ#zDf0n{!Mgjw9poqQMlBWd8s} z*yaU?N-HrO3k0sBGt)+IB1)`Qq9nH9j*Yx&;C-CZ(5AhU?xCB6T;Bzp0@Ms180gHD@B&foY0*4JJ$n}`2gX&*Ju)Ne7pD*D50Lx;Ej+r(Y zJk*w|BqD0Rd=kESv+Non&~r0)Cwd%&t@TWj4@gPaFzEPHeZ0H2U2S}IY9kB);18Ei ztx#82x__8*zH`QD=SgD?E!jhzhSxE(s5@Mx&eFo`;oqGlvUL|IOQH@K7{qYE?G?cs z<-g?@i?v=5qCndrMsPhG3~l38W7IlqLL6;{cJ0c?u-4u;`gj++khxW4c22Y@uLM@> zUxA0Eze-u(&`wFuJxjQ$tO2aTvaYiWj!6i7AM~#x zDi0*IyS%O2NdV@1)0w5D5pd=#fMG}NQjP?SCI%;LVKlEN%Chwh4zz_U^A`vSP?D4& z00GoxP2=H7kO@Qx(+S)c(WzNb4|qV9I2U zEIztHQ{^Ktj(Kjf#eJ*8)$d+-w%b>H=}MSdMuMzT2}+be;v*GpP6Qs1wpo`KsBmOZ2m9$BV*LMj{<38`pi!VFQ-)S}m5BtM$974%!Cs)RtP4#aeSFgOI;#l9Cwu(N8? z@y7^BTZ9#B3MvF4!x)5|5M=7ccuM`;-D@Q|bgSE7(JLuJ3P5NfDe-q>QIY&}rW1ii zm?=qs^uhRidPcx;?B$ui&8`-rr#4YnV69z6MLbJIO^3pi!v_${H=Bn%Z1StV*P2Nr zl4z8o*c+bju4Q`LNnOI=HKf9n45?(E^8w?K0T}530Cv!uA>B;99pNlcW~lFmf`05?4} za412)$^p%V9N|XUo3POp;i6g2j9j!9qmiBE-@f3K3^e>V^ zX?09CcOZ}(X}q@v$6v38E6D?6`=RyW* z_T6LnTuge9J#eFO>V~eLEY@dyTAGHR6c{FK%oEeo%Nj`&0?jf2&2Uhk0o)Bh(}ml* z;a!cn#(Spx{=r5$unk?j2L~7a{AiJ9DhwKjq~)JqAH;_ z>V{s+61LsVU>3k>ZcesoAT;7cl1Yx3Gl}7b1kn*8CTV0_9+N+3 zDJbQ}GD}tmrKX0BpjLTBU1UrEG8h?Gbc{XV-R;TCd$T*Ha+@23vYUdNf~2RqDg|)~ zU?Bi0z~P)^DMSdGFWo%#%(pv8HsSW$Q%`u0?8=a_`zHwMv=PT>O*BS9nsQ zwEqCc)D!_kh>{5)$=EBu)|>bFyYRb{2qDQJZAnU?9t4R2CyqOI)pO_Soa@wV+YTXw zym^Nm&A{RYmkLR0Di&$wmD-J|<3j%cF%Vnq0Q;LrBooOWCCm|!+mNM(kk|mN#RR1x zFm)9Y008VHipM?Z&ke{fD1ufs7~wk-NA!{)M^!WQ>p66*D)lnE66@w$lNig@(^Avp zDx235p{I_iB&mEo8RJ!`V4hs5E{uhcZDI%-=J~DV^LHPVQajh%(%YCRDb*e%z#xTT zBpi5PNIcte#@RWO7dI+%xwmwLQI%!fjyT3mY9d^MbFcTkNIfHFadS+ZQfbhplvn z7V19qp@m6S1Q7>}Op#rBx$Unt$&>y`gnRCWuQL`nKsaQ9}yTL8EvfGmGRrQ6NWC^%x^C@+v ziWT`6Rjx|L3H-`c)3-`U(+~j%Rb%G;UEX%Pm^F0hZH);C2uM+c9}<93GdiS?2pdT| zD35ffqa7&pSNQ65qo$o8&2q_l~wZyr-SS z?0>Xu%X)W8>CC~FSAB70>J-aL@c5x!=n2+RrrYrp36%)KOkwVOm0WJ+!ke>g=Sc;y z5C~e5=qPa^N*Y!INpVS%r6DCF#Rj(H>b(a>sk2TpGuB&q>hPS~i(v3(Jhh2Uf@T=E zv(&Mgu9istZ25BSb!P#`+Dr3>{i$8&ZfBzA-r?4@AteY7IL?rk`;u5of#yP1gp`L1 zNm21>bRdY+R!2L_3peQ{wUm`IwJB|_EuYw}MJh`1NDB$nbk34Cic)m{04#LIzP6}z zcc|2VF%#z1(YRZ^k zy1}<8LXwntE*m#C-RcmKlsK;A9}Ma|oXrVKs3%Lve66AsqO>F-AwfVaHWC2R zn809hH2(mMW#3W#Bg@s;Jyjo*hGGd2sHno}DdmBph!Bd63KJTDZb=)M`^?9O`Oj(t zJSi8UHepC*5)c9x+^jg#h1wMBMQLzrl)8=pAt}O^w{FeSn<;{}RN|6BDO|W^K}j%5 zNARQwPRwG8ECB6h3gX4Zkmq||c$-Rfmf>gB- zb;cn{aU^L{a4Av>bVQ_pC{}_{0#3jnBj2UMjbpHS@RAroUTq6X- zaCxiXz^Nu!X=|P~r;x!|imm6xG%V<2V`IAg^&A4;verz^jhiR-jhp@Vp+Q^ z7?3JDs?9yLm^zyWSt(rr>3Qj42qO2m^mW3&Oo8m~U9^am+)_o;u@48H|T zba>?0RTd=_^%ELOC}I*VJXm$j~*&@V>jR14$yLQcWU?LE?Yv>?S?9C z*AhYRm{Hh)Dm}`{Q)H`2QZb=LvnNrKR0uG5i0SL=8+hYPJ#6SEKL!bnO+kucG;vna z5egcEfbU0*KqZnz8(X+1?Pz(3c^31f$6G5(7Nn~bE<#*NuppVhf@FKC3(cww z5+{h@dT6EkPUwCSoH1GbN@x5_5}r&y9HF9256mk=8qV8es3-_yFPZ^hPQh|4c`xsl z@GivzDz-ylDV40f65%NlQ#&;2z!Bo>p!K%i@kIG>8!?WW*sBug?@p?*D6uumxO3H{ z5>tsy97Ti@kn%(ruh@0~k?kDj+gI1<1)$@EV7LlYNEj>77@tZ=FBPAYtigmk)>A;(=yiT?mxQwpGq38r~xd9eyPmMBWokC|$Ac))O%C_VnldC{+?t?2xY zV|s2%6pzZ67F|#Y32A91Qm+753NbOO?c+olvQ6V)0;$vhDV`whjvXX$$Auby!egU; zw7(CJOE~vYJz8b)hvh6WBgN`4s%C2ZZ+%2jrA1n-1*4KQ2n$9}nk>gtWizh&-SlQXfNzalgu_g5j7W#RVX01cS$_ zX!&(7)dqU&Ze+k@z$r!_)6}HJ+F2uV*o@T`R7M;wwwaY){mP5BU1*_A2+i5O{+NCU5? zfb0V$b%!&0Z^*p?hfPNk*KIF)g`5Sw(5Zx05G{MZ>KSF``asg*5@(% zLc7H>h#JF=PM8=7M3W<+Ml?JN40zSIWbx?3i7`eO@XzXvekIf>Fg*J~R@tW=!7EI) z%_iD3rorpYG*mRy}5_`g`J63$l_!ZJk17OcIhS~RqDqV&KX}Ho(vx`y-VZRB}^+-M^PmR zL|U3KNNPHXA^~P98Dt2gfWqet^Nr#DVVU0-8}D6a?&)kklcC)zb=7EIkVA+Vlne@F zi6F%Y?3pOHY)k@_f;f4OgV)Cj*W(@Q&pDPFbn2XfS%XDSlq9 z+|pG~Qj6ux)33W29?O+2&ZJmw^V!9vy~VUjkezBIV04TUHsEGQPRa)h#Im&^!T_8& znCqkEgY+)5uDMeO$NJ1^>99!B8L-T;MH5j_$L3h7)o%i7ih>Qz#_QZ^$v(!-84{3( zmXM_sq!R%6h!7?ZT7qPliY#+6?^2@DP5_d8hr8B^KjMeeDqJHT>CCuJ5V(Cl8BL94 z(G5IGk(H#Vg1R!Xt9zhFDb>C1=b0I6Z~U_Q?$JRZO|2nXa0(z`vDBoI6OAX!-~9Us zbWA8now)EmRD|j#OkC~wSAQU+Uphl2CE2bD+HJJ#l2 zR9`NHj|pC>2MHKRFnDyD2PQO_NqQREWZzEz04pLgqX^iOW=jhZuh-n^!7GS%)oN+U z3I|Gr$e)276tSDsT%j(tic|qfh`{VIv>uU1`T9j&)jp8)zKbYf`Ij(bRlm+KxU%*T zCz)o&FxrHYma0l{Oiy^IF(LN>maAsHzXMZWWU| zi~N~3S1)Ge!J!N8l!c`ULxu_z@l*oX#1JvZ3b?h$x^bVfW8faDF^X)NnKB+_s=@Mo z3*x^qjV>RKVM3oB%b&=nw9`ceS{WiN>ajZ=tZYFBUO0x^xk3_6&v&UPR-lC=R+5su zQi6qJ1{DOvfl=CCbuU{4=~cRk)U?Ed5|sh8r9%nCY@mbE##hLAx2Eonb!VyKpAgI4 zGo{VAc51@vmWoB)Be0k)?vvYhjmI=$7dn&&=} z)m6Sd)83=g*1S{|SX6Ye&{ShNc;bWk6;V}OLOE+?g(`NR^mkyS66b-e-pR#o`M{+O zH~SR=p9o=H>tSFWTTrmt+yhclLP~;YYRdFn5~7_>5LMIS8Ua06iVgh;bt->UUXn7` zs1>fM>HZ;>u^dMSsll+EL7UEJ_-F*wR~+A79g&&)X7GkTvbv*GyK-y(V1P2 zdH(5UV}0`c=PW`TZH7xPCA9#MQtFBlkYi9;P$(ctf@pBn`wiueTCG}qL%SIC34kyf zK#qa4jWv2V!8+6GAJg`E>Hh#uCN;G9eO61v+Is0>i7D%%YOEonrl&5_maU`mRjOLs zM0;diyI6fF=1yhXzj14MnzrCCwCo0EbdZ_v4hbF8fnFR+wa6fdtTfK_R1YyT)k5n) zn}n&Ou|TBG$WV-Ws>}T*buGOodYi*??jubkEtfIX!s|pZIU8DLqnplU+(=~inV+|N z+nK+G30O&SV_Ceb0*AE0D{xHR3m^TDxWcqHF`gb78!uy z9TUPj$6YK*O_gy2Pg5}h!kV>h3HXmWR^A@=oaUEc8Ic$7W#?jP(vue;YtKFZ3D z((-lRTeR~+N*AZiD;RqS9@-(lgicNB_Aly3GJ2B3aEh9KoM!A9AzIqBc*K&^*g~+Z zp;&HkS(GVIMfV%>Ywg22%dRq{StaBy;Vz|VZ6;KKh*?xfOoI?{>Y(o9=} zQnW2m0YOA5AOnh^>^&55Jy777Ze8^)J}ZY6hHC0+97r%5O4LRE>KgXBF^l{-QQ4K! zuW~fD<{`DX);P)zG3ls*QNL&wpO(x^?chjlcyL(QeRPVaUtPT<{5X0Y*G%u#zPx9w z+ZR)_RYf*x$k;9n^;HQ)^RT0(RvKd)W7}ICq}j&C>;?7Y_ED6xX3geHd^^pSo9(w2CFU9*+{&lyE*%1PeSifh zowyB0XM_r8GRrTnT1EC{eBGE%lC$2p&vHVQ=QkSGo6m!*F| zeH9oUfAzc9oKHPhv?i>>hSVD46-0I^8HyroyM>syvr<0K1eV!lu27UM$FV*l8Aw`$ zK}jwWq6pzA21Eb`H6A^`+4gE&%kmo@;Q$k<4aan&hK080<*kd0KXD3hwwz9*6lwYc zo%%hTdU=^}{*h8e1e>Vy8b=%4PfD%iiG)YqiOg&_DJI7L9Etv|a!m6--Rmsg@ov3r z!;ptobwVxxN_<$HRudsaMj&jg{{ZZI<1x0DGc~17Eu<)<2ramgE+bIztus1QHh?P+ ztg3o^YKI|pUW9H+h^nx9mAD#Sy^upY~Pz4%(APas7saH@uep`begl0MFc$F`py z2QEyCG)5F6V3p}lH_L4v@J$H>d_lLzk)6umnh>-oQ>L9nVP5Q7=S@5KpKl}UrAedq zg$h{{Eo1rH9;C|IUX|-BYS^rBr*Dff{nTFUPJ`*>XPVun(K10&lysp961Nt1Ap?m# zcqC$QqxOIRsYE3pNm1AbN%#S@oCO_zq2_D@pcxi!gmn6KsK;y6e^@a%v?vPeNec}_ zTSNW@{{UIE$M@9Z-Q~LAsYWhcN$`-9BE^HnrqBFR=kcmq1j^yNWE=MraIp=i`;reI z_#(Q`0p-AARdC|M5EjJ%(!$z!S$r%z@T%y|4aPLHp{Dmli*va4{?CUa*VP7=ry5yP zQiYLTLGZVQxEyui6zCMP!Ek&=rlblgSCtR?qyh1`(@q8gT)S8erAsGZ0H0(EvXmPh zBNYDtS6!4c)MxtBjnGgqHYoFllm3atxZmmKNACAx+t0ltRjr$vf26UYG1DrHC@FEB zFvsyvl`;;rbWV~|w69%>N~1+cMLMyy?5!!e7Wi{Ea$lqj(fC$la@#|STk(=Ik$oxT*>nqqE$*^( zT3PSDZNnKCJZ8G3%cvA?nooHy}7)nA-2homhBm7grsRtcG^-v*|Z5b zaVBW>`}N!sR<$e4nD%V^-#Lp}lvc zf}(Vo#GGTIiJeerOl_re*HdOZnFcL{r=9Z8`K?2S+LiP1e^q~(`OSOU{!?$?fADtx-;W*sT)kRj4|HwYO@47PGx*Ja z|JH?s*KL(TXo|;m#ru0tx1IGOMSPmwH8ayfRV7j}^H;;bcHvUd7*HL?$ijqN6BUvG z8aFD}QKztfM*}ai6-Dj1rd1%3v)RwsKha&J83J*U>E_g3MI?(wlb6!t<$6_YjIeTRJEN;Q6~~f z{00rf_7XNGL%18TQ>D2x zZjSS#bT7X?wtM{ztR!m)C{lzK$pt18BN!q{6%6)=x>tMQZr!sECA1|)P6ZMQuz>^v zu_ag$1wv$jIU8n8_AlB26m^TFf)M71l5I|ZU*3h+nEVx zn4HbO&8QTq;jR_5YR4GE*;#jWmZVy=gdm{^X(>Wgfk{$86V?zt^yAeW)z*C1)a*6- zEr?+>b=266Eck@@yb@HR;CO7MB#M$Km=Bt(#3W{nx!Ar)BpYzWcME9&4QV9(+NJ^z z-w_g{fEd6NLBwv_G=)7O5NAm7DM}KM48nAzc#IvpDLv|A)n`yTTby#vQp?!`9nO@w znxWvA5yPi}V#A$TLW+c$gGx%0@)Z`11^htcZsv%~^bYC8YdS}E0fW~)Snv_XgSMNp zZr=zvK%GbJ1ENpEY3Qa*(VF@NnR7;8=r5@3!$CuXW?JUOmkX=Jh8+$d*lyV#S>#5G z<`O3nuE|`hc2y$$$DZ6bqThA*V*cYwm2l%FmJ-l#x}~h>N~NK!A+V(>NS$3kA7^F1oER)ko6-+Mj z`|iP`ETml6cvxx7H0;YSV<*Witr&GKskYPJDK2Y0;=D?esGX)U*Z>qL%I(=jx>|2a zfEa-UN$R9eQT;A-6RWwS1J3#9FUKx5mPK&Ft09s|WTZ8*`86*Rp%M9yAG^7fkS-L9 zo(=cEb{OAlPsrvAc(bT0LL5>Cq4uc9+*7qWqz;T|p6_++F4x{IpcDp~Nh!i-V8d=Z zC{)MtzBe8~88@btG`K|YMNLmlEnPEI!yGX(Z&rmKGUek1Z@5^U#`dvp>mbvYqb;&f zWeE+pIzq^41Zn^h0aB7Q%CN+fLO0oQwmZ9RDNq0>P%20QHh@7mb&4kbrSk@JtH)?^ z#%VNTO_>p*ri#z};3GOKNpGq@5&?1_KyO6EaRdgN0#7 zXt&pHyxq0IZ@`^kHcS$u8kML@NC3dcX)}!z3c6IO#GY9N(Fjww#{L@UFUi%lX-ERF z>E^?Z6&->G6yrsMVeuqCFiNG`%zLT6gdc~88e7UUAHJ2dW`u<5*^WIN@Zm^I&x_%d zG?g`#3@rmO-h6B?yX)YJ(UrKMk;XrD0&^>-m_nALf=M&wjQZBI-m7|zTb?@WhEib? zm#eJA779BJ<)&v4z=20^dAs%&*ORtn@-pz#V*-KaDv!kN;T0C{oszGZdG`eClBvVO zargirVrH&d3=1F1nS(6!=Ajn0lMO|dX%DuY1aXiE*5^^-eqw#y`sGVI6*7Fz%E*gb zG^C-k{4hd%hCYIoxSd@lJ)Gx^NCAnJMg60|U&j1{^E~OLD5M-yffY4bSSeVa;xY{! z9+YGeD~h?06XSmY?fUr$US1Wbr6-<>oHES6R2ZXKLzU^*Y-+Z*jkpGQ>pgWXHE0u2 zI+0yL(_WJ1uAo$^7%(g&5wDm(W=Lt>m=E>OW$?YP#VG-yJ7XB>>h+~BwcNC&C!>#E zA3FK``s?c52UI!^HB$7>C9VOPDw-S-;8lWR2Uf>87ectDp zOOq(Lg)Rbn#mLPiricE-Rk*^NSC&{{9L)K}dgfJoR@aS7-fPf6oM@29CuvWaGO zRYkIZ4X%5IBU}4EJe5Llph}kuGe%aHC>D|9KuK-7TKC#J9`VIG7a(;Ih!!pDXx~-llX_~U8{?rmW z=ycNjhj)VLo37{s;X-l$02q}=xJ?SO+aTi#e4GK(9cPcA7*)JtKAievn5ji%6b*&d zNC`7x?$Ei@yTUIE{b|6{cLhAhKA_WXr*Hn#`>8IGgV@b^@IabW9Yq5_0^$H&-chjn`<R-~T6Wo`$?`{p&(k>7Rqo~Fc<}vq*0JQS$9X;Nxa8hT7 zP*xM>4FZv5{M|kePg#gm(c()2A1#I;wXhAtYetgF7F25+D-u9D9{fGEwpsu>fsLLi z9b$ePX^YF&mQ;|EncLyedWis$=Kyt3G`MzW$oRbS(hS^W%or|P z!zyGqHBsU2De7U^p*-4pcL^gi4I10U{5c|8p}UzXNF+`p?w?$KGzWg}=E@3PSdcJL zlo7Wbqp$FyTaJ23>9%meF+9W4%CkI_k~~75Kw_$-bQX9eQ~+$T7cPTa>#rC_SjFO0 zwg@C)#U%zYN!jO!^`YqA`|PD?P2ylEYT%%>osJAowJP)kQa(RLl~`^GNj@i*MlDes zW~N!`>P;@4S*KMgpw4wndgtudV8NUKUBY+SLJhp;Fz^gr=bTpj_6NWle`AbH2$g_ORP4mzMdxxalpwH>sMuT)JaI@cI>?hW(Tsi@eyXVQ zshG_;sh6c{u( zOt{-IRiyKpvAnuATQf{RvAu=t7#{Cy3$=GccJ~TyM8i<6JY)8d4^G~pSN{NF*Dicc zf))k`1qq+xCmkSSAWY%28Zn(E{4qT;{{U97Ir_oUF09dJNoc7*oY7LnLna#qaf~fm z)5%FWjz|MvVM4&In2q-U3h!-svu-H1&A>n>N=33_Hf<}DA`UT)4sH7+%M{u}=yTPZ?gasH%mP?up z#;8H@9yr8PM^E|@>OnBtjqdRC|l{*fe+kk$j5@(LV z>>O%z?9(C3@;lYGnLYDrNo`W3>yUgPj0s3H1kV~WUXk+u08c#w`sU8r6Rw#~snVu~ zM9R}qVDsY@DFLjOq^vZ!d~-TSB{Qfmw#nt~ETGuHdFE{G##YOrYAI}Jc_0~5!2v7N zwNNHvcIu8IXvsraMe~TfZdRGlLUoW8jEJAOMm!=7TwK1p{W1BF%T~FLgu@_^8FD6I zj?AEix&B|JugrKE{kg!U!RFHc0KuuXS?#eS1&A~K&0mER{{US*aP)!d!=^YdMX{$;vBGMPD>}?y zxQ!I5EeGl4?VFiVJB{76^qTDJKrF4iz9HdaM+$3!stx5J~q?jp`@y zNb3(@{WG6RJw(L6tu*-NGl3cFnvz&6{!WsyXO<}#qQNncC>xE4@xLS69oK6reOD|J zpV_S;B+5Y|Fgrl%Gu25mY~_o#lFLde*0h2kh!Zo9TvpXx5cP@a)2&g{()8OgL+8^) z6o1NU{{YdeV^mOzrWq}}u+<3%!XjRY(eEv-^Z-xr;1==E87HLEZ4V7)7=%p_5^En|ZR72~0+$3RQpAX+>_-{GsBvsR z2CJ20pAZv0Iu;jm5{7UGdnh+NS#MzF!!A6L;A=@)=+t38a%r;QNdu>4JvCsa*Y|C5 zb@2FnctE7m#F?h5+JRL}9B4(w$A-O+3tvX0(xjNA&NCZ%N{()zs-F!=()RqgMp%PN zlDgEB@q!g~-l_V76?AT}vSCou0&Yr03~}$<;2DDf;ys+}M`t#`STK%;&d$7kb#{)V zPhZZdQ82YiHKdR#iya(kyS~wG{{UZe$u<7~35paUFaW10XzE$ko|AK25J^o%v=#@y zj=lI@w`Ch3;YKs1Fq{_?qFC%(dV*AFbT?*u-u@p(oOq{750x$lO&<)ntBT<;QdP{; zQcx_$1tgV?rF%$L&8dlG%Tixk)jDgzU=`A}WM27;__FMQ2*D41oHX_9$=NY-tU z8-Tty*Fp8@IF-X63Mx>VYs-0i62&uiRG6cp)Z&z8GHwKd8ROo=Pk2TF*S8C_ck0kK zl>zM{lBnVB_)#GBt(xBv%{B4CaToJEVzm*Fp?@{@?`8i003ekH_PzO<-J_oJ;imrp z<7^=(%;S$tR5s#5a)9Im`&U#ta0yKf{{V#+cExfxT4_3|m+9$$n&7x*A+ltO(m@$O zk0@l+GXrhk9dy4r&Dt(rjLO97>r{PJvieOWt76~(&hlk5(Y6_8q{EYJ@qNk z=f%2tM@vDEWh`Qg9%Q10MR@WFPC5{SAvZR&^IAbXPRfH5GLRW64z2 zP)l`{B`sB1EN-?oD(ASh@64aRvu&mWsl*TfBVh#aBdU{{Vl7kQ4xUqHe#;_swfl>*Ld>T{@HN zYdd3kBLk>Ng=*U>Gh5QnQLN ziq_03Dhz5_m`6_xk;J;%?7-i+03Jmd?(wy|?xBZJr4^(ol&K&kCuD=P?Jzv5V9K*& zop2+sYFzh0gFdAGs zY+6A!B^t@{(BE@tHj`oQi<{_llLj%w$6aIh`#5ANx>cC` z!j^@G)S%CSDpHbwN{WPlwFH<1j*3%s^3}ZycDqh8T1) z2~E*dpE!maRO#(u!uz%tmbRDPfR!j9Vo!-l)CSIui36sEnSX0}K5KmLU2Wg3))b_= zLqH)R3kX`}N)m*qfq>L!1l1ST$hECOTL3#{DJG)ZLl9SYj|-K79%It8UBu}ycwt8i z(e)fzm(`z2uwdF%=M21rji%sY5V6$w>8Ituw)|Z8StatuF>Lws@ESU?8sBVxexHqF z^-GRZW)D<7L&pO)&o_i4oYs?cL8vq$u8*&q51HEXrY%Rk>M z<3U~@RP+rcb{`{C%^s;FY{7sw0@m+l@H%`C2CHl=8b#hk8C;8wY87^Og}nuxHeiXDb%{Q3v|JV9goM$D>j?^@Rc z+2z*vK|$XF!q46IoF_<7@XrA-PTCarifkmK#*&}m+C0;=d?<}WoMEYse~@camXVMt zxB$QO>8RlnEfTGwwx>;PQTS&196-^y=OxqNh z(pOhW)wDu{k!H9&552lJ*^R?@#JYzWN}44abSVl}y(&o{s}cwz0NF_{GgcXI^3Ibc z7l2fb0EGZRk%1I-^FQOk>l&7e&&fH1DpyY+nP8@#2$oiOkTdTeG&Ugy;GXcg(p&vO476LfIZa(KOUc1 z7;YI3359io44zs^S!43>dO{i$flZlDuYN|W-21gVuk#O#W;HTK-n7hh z6G^V!%WssY7UPI2I~!Ap1FQ%!?;TYyrC;!)-nhlptUi;~e^F`Qr!|nx4l6!Zpb*#6 zJ3;yim|9;ny2mLCENZ84H(Twoz1BkZzWK+U0z{?0?Eq=wFg|1x2hxaNWs5dH;d|?G z^pH{?DpFJ@6qyN6mcfAp;s{Z6v+*AMdb1u`rp%olqN>apKN_ff8wAF2oQX9tuN4m? z(@Xk5lE}(}#!ZGB-%>bZTH;3;*gC$<|vINcwwPRgCO)!zW)GwazzB2r&?*r z1wkF@POt{1!Aew>o7 z%ZUjJm?;WMRg4%qh>&=U36>A|pn9O{zf|dRgq?24*;@_9Wp$SplMZ@(K8Jc40his9 zbz7ab0NChA8uCR#tn$=%&A)V|rw}{11kd=U2TTKp3L8707Y34sh=4xhBy7fMzppSA zt4wP;b^ib)=PBi#Y35A1iPga<-*S&6Q$~s-duT&7t}koyZOMCHe$^e)-ndAKkib~~ z089`u>Zk)X+)duz2mb&yd1ldaBUgB_BgrZQ4=M*L`cLUw6NW0ObM_BXT&qa6*!4h_ zTf`Jr`#ZGMlWlk=J+PrzD(2|_0MEHU=xWXGCPK*lowH;8)xrLXkoB2ArWgUFT$|J? zWuQf=hBc?oHMG&we9iu9Dqtk{QemWnK_;8;#H;Nt(djFC;!G1ZImjw@00GI0@rot!DBrr%au8F-K}S!eKmCu(l(dwx$Q*n}RPc|-r>=xpa34X` zCljQs>Sj4pB=ZW1BA*$k*;7=GUK#2Fy_w*VnU&Zxh9s#M;VXTtx{{c2;syYleNdCM zC&C~eJv3t83)jhJ9y;xII1^8Oj~49) z^(>@IJxP7ViE9n*cejr;du4vfX((I33_s#ci3ehQJ2=3?ie2p2cCNwi8f?j&9#HWe zyAA}=t-efF?nHG*1*A$O2*YAWFK3F6b1&gd=1~DMGykwvobmU=s z+iqYM<+Y#&-%%kZ$asW>YAMmTSBUk&+eQucU%P5oe59W8Agl8(YK=N$R=rWD!xIsP z%4Dg`e}%S9j}FJMeyie8%^a^v%} z7vlaO$W9=GDh0UfNybPtfsV>IS%(Uc!a)NC2iJ^o4w^f77eJrV3id(RCxmM7k z5P%hq-n>mo8DD4lE>&~+`&Q5&3D6x=%5gz45#w3IP6MD|D^tJ3TN%imPW36&9Ldq@ z*RR0y7Hq{UaH`KLNKEvy?SC-D_GMOUji%n;5y7@cYU9?(Z%IndI!*)vNyKn4M2-gv zL3-jtidGRkHhOx|De2B#t)awfpv6fFh`aB5?%nQ%BlhX14IN=@9WG!-+CY^BVkkt# zmY$ks5Dl!?B!m0kNYJS_`n!8LMx{r-o>FMu`e34b7YxIs%XCv$Vi<-ahLxv;E6X(U z)+r)A#`aW8_qb4foC#(FQx1>#8=mwUG_rHMc?vuhkN4qCeyQW?4jbzqs2wNi_6PzL+NYhUsWAS!+kvT-l8q99xoOjHFVI* zLsUTxEXqoUu(C52xW3NZg)?8NEWXO%<@p0|U%xPvG>_TpCN^m<7Rkge5|S~IMi!g5 za?@p3D@!OJaKNZ_5>Aw!qDklmt()+6!M_Zg!|LA}=uf0r^DTIjB4$i89n9GELq!H* zq^L1RB_$;^z%)rtZz{^M#x|0+VXreob$7FT+Q^)_&f9Du7c9KXZ6{l{?zgC-Qi&cQ zNS*v z%VyhAT3m1iDI`G&Aw~!!!I{}L(wvnSdEKLT4;Gq~jY?C4PkH=FLT6gSRVhlakO3ze zy5B=Tg$7Rat?Qqpy+NYRH94~pTst#jb#%iFFvCh|A&!Q`;7zMygfVgFDCvYxl`1(Y0Gq-L&0-)Es9X}R|u+UpDpG5KvTw)v)5P9 zMI+Ej^6rwfbrF@g^O=IZ#L?NN_GX*Ux>q?P7cOP)wv;a`bqE6GRxpyx1uH{^WhDfq zdXg0e2#SGo45=u24y8KUS<!jFBdr)Uq!YjrmvVHZda1Q%~x zON_WqmBB0T77igIG>r#lp|-O6!y^Gf^fadsn`a>S}D}padk0H4wQ8J7Pe>YPz#u zQ+odZHh<||2dOOagwN89`{nt664yNK zhh#$H(&cXC_K0fmw)1R_8k%q|wIsNf9h&<$pbk6$BGwk?J9}We%uV&B)?ioN_hFV6q$L{JX-iIoguq%_T8cHF5i_b{ zYZ&)e^Do=2Hvu9FyS*oCVj!q+Uas&F&=PpnZDQ0lSWS9KPb{!2g2-aCqXG$C=;4Ol zZ|&r8)zDCZ zs0pi*yC~A?Si8K9gr@7U)UkB?`SWR*+W!C{&+eN(9XC!Sh=|j0peKjgK!L)hP1$=( z>yv>9Gv-10)9!cmmzC22j|b^(G+5T{kVLBSjlTS@jrOf&2IF<~=5+RH z^p%-!D+2F6U*s54l%yadRojU%q?D+Hvf0{_=ZwsRK?ZqW=KLnbe=8?bx$!5cTYj;_q7rWE=xg zh~Y*}W=;bTBiHeuCmZ$8>URrznretJ0;Mkrl7e4 z>DMdGU2WlWaE|RI5Hu@LBTUHxFxoN4pixV2s3d|0+OW(!@rCshQAq)8iI<$DNLyuX zaJ~J5$tO{$@9{i>-ui24fDnuKNI-%9OxZE8YC7@5jVAn}6lP96f2Cx?KO5ZTlCiOk zX5NtC_?2}tGr;MKP8tAK%+ZOd2u3S#SX)gvD%`He#^7G6^@UsAIH)7@R_h_P13HkF z-Uyk33X-KHiAe^FZ*tRejRD0ZaRZN?B09VO016uFUS+7oa_$+@8a4iPggqrJt(Ycc zS)qSDq?JV=5-!HkMVmu&W67g?H*Ws`eO!50ud;z~!&c5EmR$owPm6@DI-WA_zYM4p zgct&3kd3{9a>XR1m1$8>*d)Y8&5>2bm;V45KTsJT0;s_74wU7X-fD>|5GE^LDbUW_ z#?nNXp-9f0K>HKzG4P;I zs{a6rU#xDYVsu9epoc2MPYrYv(&2U0iA^Mx8$@+Tj5hi3pxO(E?!`bhu)8VjKPSo3 zptTptC?QTZf}j&Jf<`)2Ou|Zb07=G^JDohZ(vY39aWm!76vNWL#DmxW07i4h6V)6e zGg0C=wM0*c)60k>u%<&85|xN3hC?V(y6dR`-s1d{?KcB1%GMss`^#4wC1Gr+B}9-@ z1er0VN)d>HL`4w4cJ0b^IufLqz|RgiRhjxR{6@OJ>LbB?kfY*C$to@hAkRSuX);XVjMArbRX97c zBS;Y&BLP-->k}wZj;3K%Q$~_ORfnReWVqc7mfT01y6>=5)*0U3?N$Vik0A%?)!x zfuN~s5SR1p#aW&}5q-dyx!`LvRfd3v7KVX3rAq;7i~%6w=5e8#UwTPGO3us@U{25| z8^N=0t_oT#R~X0oM~GoKW-WwbSbjB)LzPmJIywrva}`XI+UyY)%*|pH3+rwZ?%n;J zjrv@-x=C8)8hgz_L3k8_uuNea4$3IbEESos5pc;VLXzM*bm>wIrBk;KJtBkdfc_s@ zA2jE8&3#wurWt}|?7M~s#4E5ml$NItuc=M6bj>5)J+el^P{0*sx*I<-r90VoXL!8GlHt+bZBT@i2qsKMk_h2M z6RsYg^UtSVy5k)w&$40ogs(<%Og|HbOVHO)6!T)lDBKbYNf_Ev=WLfl;mL<6xpy*k z!t**EEv;)q;H6C|Db}L{4R8*FidQl=&=Tzo+OW~LcUxM}lr5qZ97>Lml27o0VS5yq z#;#k?c3$;ijCy#*I)CY>sNd#}zZslkiC;4)H55xm(jOwF5=ki@RY$aufxBrBU;zM5 z(Q@0YsjEB0kbwFfDTR=tgrqD3ryO>K$euA2d6M2*X6ky`#P^}KAP`e23M8c9c7Sl0 ziP7{o-R!(kCd zzoFURAavHBH^V*)RSs3keO1a>#vz8+`Ep4vSn3WA_#QZ{;02Nwnr-peXaLla$b%qp zYGo_A(6yybC2$B3l{kO~B!zcj9=PE(H(hB?q@q$h3KP}=K9fF`UjG1y9Nw~UuD4)6 zgU)FonL{REq1^y3jr%4VF_$NP>dv% z83qZ16s7!>+U3Yo$4Mqo5AhNPt+Dq+`KE!#+Kv^JC}w$=b8WMaK=0Z~ZR5=l`egq)R@ zy0eacCRlz!$uyaNDp2NcPVm%bTox6c47oIkNj4biSp;mdOHW50=!Amugj=(cc@|z< zm)7bX@TtEFlA?Sn(j*Z)3EPeWLE=RES7zc6a4MVt#zLTCMB%Ul6l6N7)mki%pE3q) z^s|tMTeANErz#9N&Myvbo+>ITNmdA8!|=>47)4i@A;R4yiR&Cjw83R{ce^crdoGD1{kJ8&i{ zS;_LjeQNtk8dQ{}U_wvZAi*F;uBaR-C+M1oJ7f%rMS^6!eu8RT{{V&NJhw&j9&*VH zn57D1xJWn>@9u!3VP10B487VWC2%qVAB}_Fi$l8=>-E39H zplxGrP?^Q4B~WysT+0zg${$uBbOX_~N68}}fU0)uKd5+m(bYQspy2fK z$A>&oQ_w>w3p!K83aqjy(M+v&D|2qgw>sUrJFESb%aLZ{f}E1KNc&3Fv<{G%03IkfB$s&azTls;}9LsG3- zPgNh5q?ik%M*5A7VsskvhqZm(Zz|sr2?ZIIuA~(g2p2Yl>N*fpt!1Y?B%A^UF(Alq z*|nc!Z5x}%EZebtNj=uBPIu6z)SU`RE+I%E0EY*Np6rn{OY$#EzZK57dSAxyO8nJ^ z^v|aqI(g{VF2YipwI_iDf{rO`mvC?h*)c3N(@UNkyI}px8W*Jvf%d^KHlDE`#m7y(_C&m+?lA36rH2Mhi zk2gViS}nA6xif(^*&o#2E1$C^H&MR{-k4!n9%00&Qwn^YoGInQs|+v_!x+H4 z@$wjyYK?hBaxBYlc}TDU$9qA#$ukD+?sDSF9U&I?R^?ZXxU~{Hr!)r5yPY^e6RAob zDkQhu4689ijtliV<3u=Z`_}GM!iqGxpj>yVQk+srLi7L?DMS?%P+61x5qj+Fj(W`f zGWE;WsQOn&NU4fdVXIjc9Sq{H%wq5pDx`og_v{oc$8*VlHoI}6r!QabT9RDv904Uq z9Vu-qAzTbdff1GgLAv`qjVP1ACOIFm=v4o_OhDL&+M%lM&LlS`KcmZx)?g6#mVSi4oot z53;eFH)=pNIG{*sNSxzh-W>cjSqPya0o>o9etYeBhGUa<-kZQTI4p`e)kC4 z1mF@jt!5H|B$^a9fRvT2grsdz*gA(wj|7Z-hBS3CzM$k^Oc)hcOgcSQn4WN}UndvG zPzFj(J?d&s;JWtG;d`+yr!lZyJDDv{l?fq8Q|KiqN)Oz{kvN$?7w>HVl<>SfLD7#<>nDpH%lM5#R_$sdTSitGOXNV7Lg^E9;;C|aIkRJa!J+Ted4bt7;$ zrr$qcDY9g6KK}qvc8W~y8z>W?4IMhb9#xExd-m6`C-eNdl)@au38cUp!Hs9!kCjzM zKaJ60wJbt}o~kIsn~s)8U|RmcuL5_u-G*8}${%R}?9{Y_BY?(?$S4|>fax?$I?MQs z`flj1Gf|W4>GAA$Fi|@1qQS6f<&hYhp=qQE5|0o|SdSiKhVb^6kRSkVP@&{@aR8Ve zlxo^T$dr<)*`+03-H}%5lzPR{>_?*bXIJy?FGYZ1nU01T(XmR(WK}yo=;UUS%PO{v z0X8Dn=QoAX-V232m#r$dK_n7%EJ;6lPQe>GsaQg75v6HRQRxyR)89nD8ugj!11e$@ zHb%}-W@eSFDeyOrc2+0GSxQ8mk9YRpf=iv~%QBXx?ckLSpe1W0^=L^1bZ!WsI zRJNQt$R86m7aaUVpq~pA85aw|aP=%63XH{@u)!X^gHlm6vv>ahSaTjP`(?_q^(fn0 z-dro8HtTIa>68z`hRtrn&ZGxiZ6D_aP%SU6yyr<#J7x~F?^SdVo*&4{tl@oJD-6-7^HuFYxR@xemk+Z_~>uGAJPP zF@-L$+U6003DoeJ*72aT&0|d+RGsU(J((%vk&*sFP`+KmTT6gPx5tFeHxuNqfunqa z8_XEg0sW$O?4s}Zee~a`nZu~ql?GeFYim|)4yIP}5!fok=*nD;6-#IfTIaUB;E&d` z2J3fhQqoI~CiX%QlC^0puTcp|CKHCD1Pms+<+#gD)zi&3H7GWsKpt514ZStK-b(qZ ztdoJySsTSt_;m-F8?BvW@(?mG{{RqeEx?ZKIJYv(QsPQfSZ7j5f)0d&2s;e$J1edh zME59>2SQ{Wvjc5ZAF7_SV;-|Q#-511HRoFFtA=IDsPSCyn=nTI07_J#lpo}nRX{sZ zS!N+8pHQS2)Djxew`nPLd2>riKtqm{pe!i&ib4vM>?EdIV`@aFy?CM&5Sdmv-|sRv zk24ufw3gci$DIU(%5Vu9NGbtFHo;#~NH(q0451cG$QV{vsKjgW1)_j&t;MTevbIIG z=8~qWUwTFZ#=s81TZ8S;v|dw}HiuT@iXg2;#T6{-#3U220Rbr(Ct$3Mv_fr~0FwX{ zDp4d2xRc1ObbUpBCp~@Z_ffiu=o6(`Vk{YPC?5_Ps*jjzIA&@ljiK zR`96u0I`;}v#T!biOZW++~)TIR^^~eNN>7Y-gCr;5WQ*&X#xYPQbLwxFa*{K*mk1+ z^g5euDQUM~T1wHVtro1S#HIM7Te?U9VWx1BAg%g+=?+@-o6A3^e|9i)F~XU&`D2C00o?*6TSWB zW-P+|Zp9Y}{j<&$5(v=&DNZIZ8%XKm4;ppcsZBTBtf@+nRHFei$4X-kvPmRX81b)D zIQOW$!&lV0T(?b@2Ugm$e?@+tx&i8zn-#%2^OEqaav$dn zLr)fBrKfpkrlUah6%-Ioe9=tvdy60*{?oK=0G@I7tJ)RDX}os(t!&}9WhqLomZFp` z?NYLqmSJf~Z6P|6ph}nF7#hP(^Zd5(<|5t6N^RAoc*|-l+Eg^C5|SVZz~dZh!SP?h zFVSTlB`!D83@;k#J}gKgrzGYKLkQY!r}`vP8d5$6J93$iW|lWf*3*u*t_M(LfO$#i`6mg|9Eu;)LF=FZk zfEOoB#>(SlI8~+yHdf+orsma@?$1fb*Zi3H9OctYp2@!8VK4&2kCZR{rL^&w|(;G6A35GpVZcJWY!|e z%|ijLXh->=$@eCVy;IPkA!-jm_^lN^^A3FV(Lj_+x`_4a|xR?dQ7Dqh7C!l$gZ z&Qbv3N1GyLddwP@IR4PE_VOe`9BjeIuBR&-a)Cq68Ab~G{{UIxgI*&;Hj_16-;769 zX*xsreCFyzBvLYOHhWo@_kSmk=Yo_YYvR1On%V5`J)9H!niQkbCz-N1za9L8MH z{{HF52Ne;ILVP3B15#C)EZg^e1QX{Utyt|gHCYV+o-nPs)NMK+pj+5G@jF6rrAmEC zOo+y@;@O6X!FrlBGO#PTO^E|r6T{X-9k@|7)5%c9B51MaY{i1qQ@m8v@`{Z}RZZo< z@L{Q72L~+Ow`t;9f=3ce4{4~H@v(N8LPER$af2kjaH>vKN zbpHSm&yjvJ(R9xp9Kv%XxQ$0os%t4J zYH1!MsiBn5QAIH}Sz(a~s3@k^R}L+3!0<_TW#2TQNkJ(fDIaor6bQygL6Or$R(a87 zX*yD{m4c)%1gvpNfx;EiAn^uiwqBd(+!GEIxQ-oEl{j@3Fsj9H**G}K1V zO+31p8a=w3aE&axZ}*a-00mqXAH}DFj?*4gF8uwi@7W0jN+ARgq)!cd3P!}q>x@kV zZGvFgoHk6(l#tiMiKEEz)PTxP-ptZkL~;$5%x-=>M6{yd7Tg+vnFkT%XAwu1>s^|| zttg>Mh$%3ABLnd2pckkeI?Wv}r;ubC$#AM!;%L7|9Mi%GHVHi{T$tNSu#A93@8iH- z+X0dLFAoibj*Le~P8Bs|*Xp}h?fiUBARf3RV0t9_QSle}JtD(!tPd*VnWB=W z7~{iWSe6XIflkiKkup+LyGaWYz#;;qb_8FT-=1#mk!jcavde)hQCmh5N>WHAIHydE zKuq);Yb0{4&f_m5^3NS6AuA?8Kf?+IGmg=PZ|#F&HMLj{8BvVXPW9g@Oln!7H=tSAgp+bQcfC7z@G`(<-)U_C@KJ%m=nX@O1fxarH!Ga zK@v9NRdg3U&(e6LncGUn8!A3EjbV9b0n=;BrMQ$qi7Q6Y zv=r*pk`G9&NdEv8uD#@rw0gMeO*f{gYqM5Y%$S`HG5p4p4#Yf(CrT)VMLbL72Vy24 zXn?l|US)@7ckE;ta+=IYWnJ^D33(;81T2CIlCTJqF(63Bu@iVVW!%>_UT`*4&wIx630_ zO3`;|sE!V_55|FyS{9Bva3gAv3~e!uUXS2O)clK){d7{z)@)s}$IMV-6qq7nkX2Jh zRbN{yRMhlT?KEOFm6h12Bwy^U$+sb%(lgsT+@Z8uI@6#!3x&55tsyBoNzzUQL<7;b zhCQEJmNRrd>Y+Lmk%&~dr~pVNBom3~@~xVB@zjol`gZ(6ve#JsL1v6UCs0;oTuO@$ zs>J6IMKx@Ageg%HIn#V}58M#iTY^GXSAZ%qQ=kYEdQ8MtUfvcm?9g1k zuz;p?f}#K_3fU(KgF~(#_?UVG#b-)9Kdt#XNu*$^pU>%o5_MsQ7zCg`S9$LY1 zX8w1YC50x#CTO7DPZk`^Pnw3Pta8s_v5T_qTd4b&5AQ zwtz?*{w2t-G2B~R$ZBYoRC+NOT3R(I9*SMnRKq%mn?rRM z@a|6ohZ=kss8XvmZmI7Jo7>twhlpHFC<> z*Q7IDqc@Ntuu@yQ5#fH^5;{tkLSz{Ng}kRj=F_etEz~L-5T&hVu(FK^C;K?9hOpFV z%>o3_t%B1kVh-%g&kI29%m?u07-0aZ*#=`V@@SoB+?RMgW|s($mvbDpe`>Y7%<3beH^Fis;up#+q{}xA{tT{lOn-LVbw@{uLMI zZ>HZRVFPM{%=GJX@Dyaf4w@#yG0bqqc9x!slA=Po0*u!xNz&)H)2Z#uCf_?!8f_;N zsFUoY%O*v=ni8Hcqv|Teb7o`CI7WWLb6-s{nw$?9!`5RJL=t&h2n!=d_5?gm#9dnI z!%{qX5Zh&_d9vHd3QD$vi2V;(#8pdrw$jJe_pO}2oH{v_JxS%6sj?4TvZgnNq>#gh z$22(PQG-u4RAGhVmWfGytO&CeQb8Qn>29OBQ|q*Fm#o$b&{j^S7pNT_V2RR45hjBf zgQ~Y|l)xlG!)T5@eI}2`;j8$V(sh3g&Ga6(GoA~A=OK+j4h>aa(b3jo6g3gM0^|1w}EoNE;#!J1ZPrYx5YkHf_fasGgcXzOK60 znLRh={JooStU8+%qO3tpJX1!@}W!I`b@hD$bR>7LSIO5T-x6Hl&q70F>!6m;?#K)NPzN z?Z0-cGWV?5ykx!~bS1T+&goxrNh*MKK?4KB3C9aU^tbB!uAYwn00Jm;jTU#y^fZ-t zJ|z|pO;eX@4Ql+-2xAe{!&;F^A~_))q1C&CYj6#l?us+K%@3``gf_|)xCqd6f>MGH zicSeSNSTla7=qV-E^_R~<0G*{f8|%sA!sGVK0!(Y@1ej$Z6PVdC23Jf1O;r0%FDe} z>s4o^NqS|4^@f6^VOc7r=fElO7$lJ?zEl~bnxs?`j4lvJK-XQj?UYN(k9Jm<5vVj2 zKu9D2h#$wp?Zgh4;aID6msqu)q33ef!WVv!msNDMpsc$fp}y`2Do9yOk$}dAK8;p- zy2>7!Ggd2-bL2D9FG{f#s-vmPwA)h+S|n+aY8G(DL_if@$6ZRE1UH)}QnL1yaP*`U zDJczsD=07ufjlH^jx;pgyx%Nic^2CiB?@}!#-4Cosa^%T3e;OtA_|g|0La)4YX@IT z3t^Pg#IJf}fg_D?W9AK|q&B^j0Cf1@!;uBYh-$_`0tUmY0#8ueUA(w-rO4?fdZLeC z;qipi(R%*r4FoIZEgo&d4%PvQDg>tQ+QF}HqmiFzO~yrd*fFW1*gHrrDF~jtRkDvV zr}Vmq5Ae#P{7_7K#Ra~!dT6}`^>v;4M^l(To=ZuL)kte1q!Ecec4IyE?j>1TO{d#! zI3j7Z_2El@bc#=m*ClsDI80x7Fd5T?6?EuxZ5rOrMzM_-ZuTLv! z7QTxuRZ?aHND@h+Xv9^q`IZ2ew8myOVZQd>1czs~;*VsbP76#MA3H72T)TFGWor8ro3_g=;ypS%- z_6jfY2jRq_l#T+nr5>73(&cE9No7S_p+4!1TU~V)_Hl&T41Wqtr%gF!iR$tuIYZQZ zrdBLR1+1m7qj@2YRgR{Xb(R)rrB;qWvH*6lD&3e^@hh2n9YF+OMm|HI-$`FcylqUm zidK~*i6TOT5hG-dJS%GNRsMtMdb^S7eO3DQ^;6Wm#}m~>h9tBZK1ztN+WBBwksTHZ zLsnWEGOe*@f(3}_X4GFEoz2>_d2Jr!QB+IG3S5(`N!4^Cr^1A%%VlF`MZL?tQV`M^ zZ5mW1N?9`4)1aw+-oOSVgrDIG#;Ir44@NQ;Le6<#4(Yaitm-~l#PCS*3?~)D=y3`f zl!@ke=B1X06L*#eic~k-WozEo^hLk8t@kFW&f(|C89oWnjc87w( zbs^0P&_a_sLBN18gV)q(sZEfu)tkv_BUu3gtX^s$!DZP6L8I0;*wObsT7b?;ZyBux)&P zjtSXp5nD8qr@?R_QjQu(#FkfL(d&B=FZ;~v1qSTh3tt`JuH4#zHC-Mn9+dJ*B#CHG~Q<{mf1if z?kbkZk>J8e{vBIK&alsP?K8#|-?)_kmh{8YXZD9yl%1;6u%Cra>sCm>FfU6BkIzpE z)JGL8Wyst-$m+_CmLK64zi*F+F%v9!{$&Pweif8f=Uc=LnES<7g>EHFSycr_E9BJ9 z>hEadP{nRd>_zSly6g0EbY0SvK~kiij*1pr+a-kQK!HXRqWC@l(ALrzB9zNRM>%#y z+$3__w%lq+x6pXCP7o3SKWa|Xw9Po79@9~Jxro#?B?``k51l5>6cJ?t!p7aaKE5Sk z&h1l21I8kgST#)=(Zf=eaZ5d9Vp-DXd^=pmt02<%18}wUJa;mMge)y8D+Njdbs&Qp zSJr;v5+K!CRw_wJ0VV-43c_VQLt&W4j6X#^D|PqO-%@D$Z_=y^s-n87oV3kLF{hQ{fr*WSX%s%o@`v*^ zhTBX|(qsTS&0IcF^c(4u(sxN43;axazk}sGMyfcbOsAFVz z8Sc`pDJC$~e)R#gX-=8`Do=Wu{9a+`7gF)Qh<+X&Ji&T#iC05QSznv6bc+(lD-BgL zN{$4C#TyukgXTP&NYO_ETZ!1K+w*4C*6>|A^GPa0c8nDv3DB~V3#Snz92!Ca8&yL+ z=H53lm)6^1AyAbmWNp-tLDR+redR-_RUc5*k1jf_O1#y$ zh2c}OC>WKE%!f}YQ~_~r$DJ|BH)6|mSuEw2$hJnp8%C0$AI7sQS?McLtZ{nv+wv6h z%FkJxW&{m@M*u5iANWr03)B3$_=#YcPgLtEsWE(K1IB6aY%Qt*sh7>9CT5y6B|AxR3!hE|Db z>+5YxR)9lY;#aC$K!B8J*Z>+p0tU+1f7d@%v5u1ZO2;$Lrx&NM#=1v} zVR?`FeH%>|pC$oaPc|=0UX=DL4AfN;dCCafnt;Om;Kt|fmRFo+k7XH(LO(rk`Euz} z3y&8Pmr-zp5~ZP9lBBk^00zW^jZNF#dbdz+TO^bcNCyBW3M6d+MiC>R(RcNg)eN1Q zy#)1J)VHJ>N-WWzx|f9En07gsvQo@yU8-6s>co#q!bccY0VvABr$j0w0B#%_c0`-} zi$6`4d>ynx6rpO%$|a`Q5Qf@G#SN&2`^Y2}g#~RUN$zdGGhkO_lCoecyMnI{1x7Jf z-Lq(dBM7ZWy1(jY73$ZgzLoTGXy&3`nBlm#6(sT3I>(4DMN&&nuT2L%vzt9z4_n^G6vcWF~?lc^U;dOO8D zsgxGLQd>#@2ug?CWPo!4>1ILo4Uey1@ouBm^$QlBwuchTl2t8Y;&d2u$cp%WD)j(G z=0KsuCXtyH6cPo;C%xF-e8+QcQFCdfR|p5Y!vOIGC|L&uVnNV+B;kOlLonS&v%3qm z~8il`nMkU0`8gr+*QNeJMQ?zkA=5>-xiC+&>vz|y{Q%RaKhF_?vs6xT!lD7_) zmX=v}`{GuijR@QWZ36t~&utgEiwU2)o&EixTSQWE2iq`Zd0Z~-eMxSfe`s3!=l z2HniRG0Wb4yVBeR!V-cBLYfK}0YqS+Tq)2&RE{wfO(tzS*B> zx5>9*L6#6y;u>-^LrGEZpF1^a5(Mc%jU!exDMgA>Jl! zJDKvNH25AFicv>bizPKWM=ea%v{AsJq(Ql)X&?l#C%3neUH)tNtegizgQZGKX#|9! z8j6$xcp#y|H1P%w6g9QCN^P|Lz!{U$lK}dD6ruG!4mX%E$QvD<=0QnQO&Tz@k=JPp zVd1Ab_4FH?C}(+%o6=O}igc1pgtF=(B6cJNkO06M58p6`+6rs|`%GhrP&n4Q9eu(5 ze|0PHlIh+F>609SX5z=tr%lsHc2fmmk8f+QR%dDA>U`oonl{7#h%3FzVsflcldT!z#Q0pcF&MOXqwGG>gl@<}4q zLRh-n-(47M*b%7*LO*8%FWZF@NTXKKB8zTm$n}+YPecPhl{@VS^; z{#K&o17mCGcu3{A0QG!mDR|$D%8*rgR|Kh*Y&@rxNMq!U2+(a-`s@kQw+q4z5qDyk zo2PgsRFxFsb`Ha__cT#p7>zD__;HmnuW6+zw+gRfc}PW-@O)5IDUS@q;N0zE8A;i* zc?E6>`g8#CDYGd`)H*7zTS7tTB8;Cxko3dXe@wGcMloVyriMxO?Tj;Ql~ldR+(6WJ z_G`f3<-6tx{`n*iUXOhcT((KWh$H7)HhRs=HRlM*dB~>JT8gT0Ng>E89at~05#Ns5 zSqoQGln>z`$5H)hyJZ!F(TBdMi`V8Cm2$UVvUgK)iYe@6DJn4Pq70QD zEwNZxMy=z)7WJ^>h(goh3u!WA5>g6CPg%m6vnfK1;zEe@IO9hD0M*; z99$<2M1#Qk(Syo9n6mCf>HRhdnnFj?S zP)q{{3^+|6Z#%aZs#9$#T2z2w3^;`ef=Dsb#weYBAH6Kfy=u$7K+0LJi_fTs3Z|0} zX=R$8Drt+nLV3KmR53)v6TC28PcuV2%^tHuF1D;fj-nuvn8bRC7;UH*D9f6>?;CM4 zAV51Of%H2%DDLzt(#Ku;Ns^l`^}i)#?!5HPqLO?!FwkabWEfRRj1QBBw|dD1Jyd~F z;$+#s-d#rkmz(2ln!l;Lm#uC9?$(zZQk3Fj0T`15VH*Y;DP5jMt2XA2Lx407)l zZ!rbIz3v7($(>wp7Vfr{El)XOscl6iB}iB(jVBPT3L-Wb1W;DPCTA$kONmHAZoc$` zAu3ENWNi`w>c)f)w&mN>>BeJz(X<(jM~Z0OHI^;knxtxP&zRTS~f zPU7ks_XTVs?4vVU8G7FFX(b6|Z9=ESq=aeIIG6!LftfV*-GE}{w`~ytUE&5zz)C&J56@ojqrD=MMZ`Gj~m} zymFfY>7G!Iiedzc1Rdxxtvdb2cPxL#$& za`rHoiaeE=9wfC4tsO~`nam@2@+1do_X7`j9tm;_=JHnCaVK7hz@#Tyg!ohd#Y&I6 zj@&j=8O4z@R{bJqQ%=6hN4VH3L^mq3_7cLRfQW! z?3=H1#93o4+TOY@65Gnqy+LxISKOFc`%07v)D99x&J{LYUOf#jQi`AgwHYgw0HRLG zBWzXDbuS@go}&6Q>MjxJs)=a&hfgfIZx*MarUc^ESX>lzb+F2fWHnV7T2KrXfn+>>mjlaqT_qJ>PN}P^uN(0UD!&hUSgIzL zIS|1!A&my@L#FLP9GaW4{?Vr8E)}W7g=<4;KYAM}IxxjWCsqo1iNp=bz7gn0BIxMTtwN>YQU zLE@NiHIC?9JKhqh)RCve7N9{JH9|T`B$2ZkBVL|;VrLweLy?k-Y)>v`T#ty;&4*Rf zRzTQ9wNW!gO$}noHx`LpqU{8#mLp5^uREo>54V;(WqPKR8A>&sU$oE{r1u2)ROkd1 z2**l5JPa#)n4@?W%LqX3$Z$HXYD1mUfGG?V!h(Z=B~!5@P}vl5JxTRXIN~3OeDGt~ zZBARuT}q*($LKJc_*$J~{$WZbl2i}xH~a7tg?o_cwUnFkcFSA0wX{XMFAIXmEveB2 z>OnA-X$elQ?4XbU0GNRl5@%U^St^2AEtbjx&>MI@5|U4aYe_$~Ne5b03IxPO0zRg? zf1PMLON^IkJeXECCN|uzu{PrySn5KZZ>@m83-c6**-%Xbvi!}b9RM79_;u1ZqM7Ee zs(*(`z-tw2an6oru?!MS+ofC!Goh6hJ=fbDIF&mMJ9&U#!-n0GUjG0t&tA4FI&Rq3 zl;Nknw;(9_skLnCqR!APMfP5Yc6TcwU*fDt!=gk_Nv)87;X8hy{{Wiw!#;E;5|?{r ztWuX9qJ_1!E+D>5NCbCLJYfF-!C#oS^?{I!JG(sD0t3yi-Nk==j}kxLN%m0dvU`no zj$4x@wFLpxM0+qErid@AUYO#&4D~nE46BY-$t+RhbJfz;RI|w}ly!Ehr)FYFE4D&_ z6Q+yVbraTgWAmc}kuz;J zA(5#nDQ6BIG<2~aX4-(GP))plE)`}Bmfle7psN5ihaNR!9UvWJ!@5yflzl7bYAiFT z`O5*Ts>}1u95T~US5wreFx8n=if@kMMP)Y8lf#_G?drNDi?4 zA>;zEP!eS-3qQn&kZNn)64I4%YU-8)%&BSaRiVVX*d-cNa7vU3N!8&AGI~XE^*hjq zPO?v3vA91Ne^atjOIwG>i!h?Zyr^qtc4U?rX<=Q;@s%4!(9#3$+T6o?+s2k$D|@{t z5JP&LP*x;1lxfnK0|5sU7;T|8TVa|v-7#%wiyb9u7cPWeDMdsQuJox61-ewC>ei?v z5R$Dx&?k~TME)DO8=`oxM*TAM4;bopcJpgKQ#Hdt)X|t?n7uV?%*}}u<;-R8EzH{cLW+V~E!-`J)CxjN zVYd_!q^O^}yit%u5Fp6)Gt>{`E$U;Y8B42h58usT1PpUs&3x>bqR zLRKaZ?}f5j=iVA{>9pUzONnvE8c>8Gl%=-PleFTXqA>pGPK4qUL1kxI22ZBYTd7KH zmXhGMQ44hvzUePEkl1vTNC`NsZ3haM);^AOYbIlvQzQN=Jx$ARy{{W`gU#JAGfC#ePbn#GTTp3m`Ds8kAMvsWnNKWrM30akmwv*Y5j?yf0o3F{= z*j+XpfWxl@y28jw)&aLmg*Zy3V_XbMVvyhVb(v>uC-ZmBsaSxA067I4h=;rLQI`Oupw9g49qG;K$)KJF}e3iX3g7` zKGIUtgtCB<0V)C4P})-Ct3EFh)}j<($up0u6_q(lt(c}wtEXr%{Bj9NfzXCjtcZp( zE9<#QAoJ$qwEfRs>t{EX${I@-3R`Am7RtNE%1;!OC_(n(4R-4z%#)hgvhXq-Z8PT( zsT?r}3aAd9S5?tN{H~z>lMSevl3m^n3$$e0#^8NC>9*nKASJgr5-~jr0Q~AI%$X_$ zJs&C)3vJvI%M&%!umt_DhL`Xit~s8JnZ#5;u@xEW7B*b0$#-Z94C2Uu__=A zvIoYDTS->RG5t8`cUklGYEtEVtB6S?g-Wx+Vhj(B-}gqE+wR~g>*kgTN!1+y{BQ@- zXvHf^4~U8AnLfc*HPhcf8K)0OF^^C<%^q2y(27VLPg^hekq6mZ`~wl}sSG&&a^0ar3s(J_7C(mi}K%TKjPD~poU>Pm?Z__9y z%h)4=D%zR$R@V;Ko}^wxR`J?H5vJfY3OzDta~{=VD7k{xHaG zqlT?@4c+#D>&w*A6XE+c4+=Wc*ur|%Cyv}{AC|g*)BLRp47G&P(wN1+$%b$F4ojVR zl$INVljY`9ZiO9yxh_B$00F=OzySk=0xtKrF}@x*lsNc&KMDvvMs)fd>y)0VoJl22 zAnjf4v*C67I(F^Mm)*;hWlITdDMCjCq$duj6d7vqZZGz#DxM^hRT+-u`Ed7o85788 z_i1l;;(dVldpVl+H{J9pCT1vPh3MHq_7hmO_<~WvxvDNeTOFl`vrlJhazVYmV=rjC zaN-+C5~8&wFgoOqeGcuPO5jd3I%QltAEl9G#VMMWnFajXhYF&@-eoSr>VK!0ZN0s; z?yf|F9KCJD$Jod1RCHh$$d>5dYoRwHsH&0MxEM=vRW_2y#+aV3_ zcmh7Ya}%^K*D}rZW4N`jdE!3DR#MSNUNWE$2qcZM6mR*!(AYgs%9(n*_?G6rr9d$B z!^0wmMrf(yjIv(Ky{0b0-vt-%%vZ>B9NQz*ZB~Z0V!5}Bf zPsWM1JJrsjW|V4Z=)AbdvGXJ^q0-{TSHFe0XMKH~X5jv6`r&hd30Z9?suLJeKjuJD zc+TAu#xsm*O8 z`5iOwq&7R${5GyOSs5kn7u{BEI}u@Zzm5BL@5AeCooP5o_K)91?%xAQ5sB1da-w1Q zERI~p(sn1^Q0uZbal|R!qC7eX6j+vhqSw=D z3N^5`#=4(x4%u;}k>XMI{OJRdcna80`6f*N0EXND06L$_o6Y`F{J-RUnqQXr+x))o zJN%~0d)t1ibDW=-fBQ%IZDxD@TBTFn{o5yR368m`=ktmDhj|0+(;O#dfB(=gcxEjm zP3{5+C$+o{&Ap$0JKTk774sEyZWK(=kB4HC5<$JbpV#T)#HuI~^8iqtf>%7jV@-4b z06c$<_|t-MpheSKaWtEGdWF}{p~vZC)5R#najZdDV)eJRE+0sQdF?#n>k>w$^GW-< zMu5oHEVxffGQq$kJ=^pG!JXPLI z@mtw?Zd@|jd@ZCL0H3sUiN#0w)&1xd+pfaZ&xE zgqpDm+JRAr)`(m)`86xKNH%dB0xmp3@9aDwxNtnnnn*qe1_p7`L`dQe2cY3uR_cSO zP#DToF!DVWU4D|iDfF|Y`DUM}oiD@x0GFKY1r)fPYQ)DIQ?!Ob70uNpm6_OI?H*y4 z>)PLMW?7b9UEDbOdytdfK`nrzt_T3AD4`%v+K>`3s1I}ZUf(Eh^EUdwZj?$%kbr@T zQO8MFiU}}q1}Sy;ih7#DJtz7^&0SHckygH42X>x0}jc#S}p7a!g>6nx-ut!sTQ(36&$Q&iEMRGH~g#n6h^+@XJ=?R{-7;Ta83{~1z*H`kT4(L z6BQYD3AhdB_o(oG#h@19j61ZS3MY!5Sd+x0N!v_4M$DN<1L@u@dWnp~f#9`p{EbC* zT~MZuF;>C@x}k{KB)f{C2XSHm*O;oOK|$6+QxPP`zoxs%ecktJE|8R*37s$w00YCI zN2LRFUX?QD1sa}?XT0x|;Yg6f4Gv&>+EhTGD>W`IlZ~5grs1a^ZrETOTZxV#WkNs2 zP$SlW%iU)YjkU|o^(q`s`_?of^qV1d_a|owt9qx@%6!q5cDuVxm1Bn!GTdz~EhOts z$>2`Q=r)cEvio-y?~UQ6IJM&^WJ*<}dBmNO#(|l`JI7|w8Gq$2SJ3fO5Rfr4nFRX) z+eU{sdJ**P>Vwu!Ov_oH3#_Qca4ZEgHfP1@>*}d1B!OH-gW&t%kxe}`tVwv#f*m&`k?;ZB~=WkqGAK8)O zXhNHBNbseip|A}jT#`zO+67-%syzPy{>2`Fb0%Zy$d3=jGVTnNI1Fa;D&m!nwDb{y zIdb4nAkm9l1AYN=?2%ieyMLBx!iBcVoLi*If{eK8fmGv(3Bmz@000Wf&Em{|v-y6u zuvDQ4o6AKg@? z`c9Plh84)p)%T0@nd_~f;L1|hs2Y|2^sIcSvCo^9Nd+A{gENZ&Pt$V4z<82v$&nUt zH64|VPUe7}0QkK9v(P$e9gXMQI|aj!^A(YnWhz+#xwXi#&;WaIL2s9-^>||rngZq- z^Hy!clj0GC$>_&sG*h#eSEs~bYI&7o*jSbXn|LaYN!IytZ9G*1-d(+%02BZd!ghY1 z`mS$P9Y?5KtT1YMLJHRbj_pVq_8s_Lon8bsP>d%Eoc9kV1^)1f&@jS;kHOz3rZd$H z{nb2CRilCmEEPAXE4pTCiS2&F%S9S^9%629c?&6+pO@iT^4*{I<9I}I)2&V|G<#!TEmdQQ5dyDkY_aXF`4{IG03Z!O!ZDM??e*D0Y>waW zP)?mr7=Z&wz(-cvGaWX;qgr(+0RY*LA4YPi2<+K%-xmY17C6YjgFVj|0^! zGMp$vrJz8d0d6QuLWFIgR9;L`OaJ66njDX zZNWxgZsLg`_*_y@2S`EGvV4?49WhZ}d3J#6=Mu|tx!c0Wf^C znX1;8GvIXKxXU?`L=#O;ZQBpTf%%FlEwroc98J18^Vai~-vS+K14>o}*5XFr;sX#i zl=)G0?TRjvE?FR?&Zx!++v(@>s^-D7#8m3*G+tDwqRIi(gQyxEqg&kle8?tl=MpFs z^{7uBwBw3r5sT4DL50D(X^KGyE)#~)lp0vUOo7MOChlXZ@mJ%w98C4ep&AvaW5ko`!i1@R zNl_Frf~unJZvuPU=;4zhns>yY2LVXD>M<#BYKlxAK^0rZ;ur8)8$f;laOj~+LV^q^ zj0xa+Xo2zp6SIvHE}Le5#A*(_Cqca@+wv*j)D^psfE@bE_wHPo>YZ_ zjSyVfxsMk)XuMmEJm4-ON~=ldujwB!~vK zjOp!0X{N~dZWo*2rliFwDQV!XN(mY18lhreJ*kU;{!xeSRl+1{k>c&avjyov& z`oQ$*(f+>rM}DZBpG$&b_%0Z@?FgiXI4Yp0jeOZ@Ow@rc3>Q0f3f;S3nZ3Ci&vk8f z*l|kI@d;8^NrJDm;&4zgKFSF8leo4y=1jNQWevK^ed}cjN=}rGNfq^4jHKvWS1 zwT;Da?14{2YI;wb>ZZgIR#_>r7#U%W9j@1_k87=lqTt_|(RZJtDKT`kAgk>KQb_55 zBm>hvQ(Td>-DPKJ*J6iPrv(s=2?zQzPLf9v9?BYXzu~j%BdJ|Cld5@xr_EVUM-i!l zqK>KoT~!XkMA6X`9ZRWO5U!h#+6qr_dbigqxL0yKhm6iMM*hJz4AbL0Ezp6&__(II7d=}gF+9YoVS^}z3OWr z^z%Mtj6QjBjCP8ey9}hnYUsS^9&|GK)bfDvDT!Lnk}&@Oi1!%Xz8B@3w&7EyWg!DX zw5nWEPyh;uDg=OM2`6Z*oXTv1ooxt}0;K)G5Jch%hgQ=ab@Y&GdU`uiQVp=c7AVEZ zvLM)k=H%Hx7bfS&nDmCjKp<=a2dAB9G)5K4R_br#$1BxeAB!e&#xh6Ywblyky)c6j z#V|pEQnt7AajKYbr3-C$kx*@K9u-{LjKxgZ?fk>+GaVsrq$q!+)Osi$fLruwS6@E)CE5&XR^G!(S48+VEb#CKl{?Ot_1INoI1_l`+`P5|IB zz}Ge-Pbpj)jqOLwSgFsqzx&W{E zc;KjK5d`N=lNIEF=I(3fmaQG)r^ON^*@f z?*)DbLeCp8A?V?2A0FxB-{aqtEuLuOf9Dc_{M z49S^>q5S+FhA3i3cVS5ag-|RtD{l7sxRW)`S8OmcNfCzA=|a0(o1EGH?N6;KN=lTX z;Ste^F^P;k=)mE=n=&RZlBULTreFTBm678UVOU&qz#RpOG^(37hSJ-KzMPMo-ZvS1 zA=M$Q0f!V4s61nAM;NJ^!*MeV(#XGPZ!TA=0@_Q3q12@q0}?h8PXR=)9-)UQ(Pnyz zd;#*#CxJ;_MLaXp#ZNNN3JdNL+y&gi+VW*en|ZXZQ0i8VV1Ni9f<`1y3Juz~n(qE+ z&R+Y@p~B-~X$x>^C2&%pV90|aDSP-s-&7NH_=r2pv&hNEVq}wyTvqrKLl> zX(Pf}1jdwp} zfpt=C$12l`_wELQiM32B5@-HgRqhUr>3Zxa7e1? zzE#*H;Y7&Awn&X}eXK0Nj{>@mNWnUiLD)t!v(~3@;3rJu(KI=9FYyfZQP7T}&y?iE zj%drY5Wyt4ek;0Ze@J$(m07IOfI9dVXPiYL{Myjq zK*U6mSEJBh#6Q#DStS`?FjkzIk4)QQq{SUpDRtM#tp5Nc$Kb_J!u-U1=Wy?`gq5Us z$o`XHl04J24!RK{B#bSAM zL~k*yFQT2=`#XJnC_<&gr=*XKESO0>RiZDfJaZJy6togoNH$gCc=db*ed1DT*-7(3 z&=x(d{BO>??&&H@r*4$e;=L$OJSd>$Yy_bU^Kn{1KI8Een?HDTBy~x z2^dw^^v5ewQhpe@mo!g8D{&0bjzLXGkx;21t>TkbvhDsf@9rBRH5 zvk%k(H50pjRhuEbP?R8*c%Tw`XACf+EkTxZCIwvuHZz6Q(ZuAqYN}b|R%3Pd8Po>d z*-iN#-MW>g5<&7aQsOR<fZQq)ON z1k+L~8jym9OSEOdK*IXz`EWCxZ$kGf*yc^3IHnYZ1gPMnAVG=@-J`xjlQAMav`ha0 z60gJWu0E6Jro=HkFylEEk~pa-^Cb*t$vYi@O87x7NjAPd;~#lWw&3%3J4DO-OLcED zLvE<*Qz||r;3OtvT1NsZ9Nt$-Em^hz{>>pexDzIRI1RNg&;=y)&|`Jv0%fP7i(lRw zn5jMP4}dy&@V9#{_2^GT(9J z$alC18#*ZEN|RO7>dyqCpQ%+9IQ45KWEHq&9Bfqial)DAkfVeJ4YGFh?Ssak_#_`NaKKjTJs#;k5sq|Yq#ZZSiw+}8Lxp8ng(X~MvHt*l zLP86@%P0+Cd;VOIH&u0=H!B2_Cq6tRK=BQPe~+>?G}zUZ=?zQtt_g+ChLMx#An z-s}_+&YAveb8e?bu*8&;j7*L*$I6N&USjGlXvJ5jd4n+3RN%M_qK^%to>{z#Xxg9= z98n9R_>t`7kY07&OsQT3#*q;cM%*zmhfu`>lQ3fFk|0`Z)|aZQmplAc7-k+qPqEXCsah-~(hys|@@oFhf!6 zzoZl%aZ?^(NyGi71tOJ$4c8li_q7CQG`Ax?{clb}>vDW+WfC^{pFo^v9yrmm-u%06 zJN*`%S5^pBY(v#A!voN6IqPdO&)3Z7T?1mdZSxn+;&{~^B+}w7iBC#IPF6MY{HWH^ zu84K+MTLUp@UWnQqDo0W(F6(D1OdQA4i(D_4f4$Ltf%t!PNAe*_lRtzgs)U5S{qPN zP%2W1QBd)j=oP4@XvvsnS?Vr3gJq^C42Kb|f|c4|GjvHY2*z*UEG_R18^5!H7 z!|=>9TodNSZB8j$J5tF5i4rRDfLyz4(Y_cX$Oo7q(Q0X?UxHU(L zB5BhuV--2NlQ81Ate*5zK_o)n_}?vnRvP=i!-}n4H)UmAIC|1o)A?|aIw?($!H<$ka60U$j=&vMn zH!XUz$8a3?m+3HydaUV}I%|(r%RMv^d-PJ$Nl0imDlm_7?*9NL9^{kEH&|7*!IxP9 zB#k}du!3+YFQFjp3euFp7-CIh-K%#Ns_$V9l1MG7z;vNlhRTM89_->FUM?hxpx?yP zs!!E!wq@Mdde2SQhm!|-YJAHUS^loo`EbtGq{MLVA{P0mSd!9}yQvrLZccWssSF`X zNJ&^GMCo2JsWXY_CRIPuH6`xjS_}RVkXDl^B&AZHxK1OWjB)-WwuntNRXs$*=Sdrq z!M2N78w01a#GV*UNd!Qohg5z>pDV>tA9(5#>bpSqNhF_d!;2b0I{~F^C=;}7pzjF8 zWf&^e&+jQmW>Rdd2XBG;eZBSIosg|EMJ`YRk<{}?QBc)$uq;3)Yg@l=CrfHFqA6h@ zK$?>kbYih~S)W3r`$5$EN9TSnKv07o?tfZLs%gY&>mZO}4+~FN?pnxfN;ay#%Y06p zM)aUT5@hvZ(McpL8h^?ZXAG>OGGS-umcE_icV!-0hZeHj0$Hwg@Ei-i-n0-Cjx@uk zY@QW*S&t&+j87rbWQ=-}EJBVri%I5rjI6BYKtWP2Mf9+@!^e;V3sXu8NrEarLxl>| zlLo2BJ!PyXC}(U!im_CjIf;%sb|ZXs1c>7Imqm|F#`+JBC&nEPp(`U8_VD&iN=z@j zKs?B$m#6CJu{>)MpeJ*!1w3rF(MmfF-w&^gSaZHH(2zQ?q|f+3^O|w%g>@!f%Kre( zX<1UCoTMT}2Yb2z$6scqR!NSXpS{eAx zb7q&^qdas0_Ub~C5;~HX5|jb55)YjfuX!6%b$(b$+ZqWzWT290;NxG4-$c(+X!2wF zUC8*|Z1^<>Fl%X2kfbz^OeF?+YEepxR2vxF*a2Z;2O~>P%Clx{)caY%WeIi0v=lg! zrxLP~LQ>)T&LHueXlVXwg*=ssP?E?Kc=DTQa&_7}U&Dtic0at%#=O}ue&p(Ost*D+MI%mqXxgPLD+7TE zN4vvTS?C+p$49#7>eHn7?41nD`3jp6%x@kYj6($#HY(NaM>?vca8L6M6Pv7sl&!6M z^FDhj?C*FoX0G2xXt&!)3j6BrO`KHfX`9!gbc*g-0Vt;D4M z$b;S_5HMP>2|N!*+SYs3o`1#iH{yMtdV%S02bJqGu6o9*u)I2omPw*;W zo|ZCRJCkxIL8!#BT&IiSG;>o{;{zGQ&K*aMVzWX_0;Sbsp_gkIUR~RdyazL_8@+4Z zJiEe|R`!zOTp)xHkRdaOfIK8Y0tm+%F0{`RYEoEqBfFR>AP^Jx>KtN8SXQAblY{`e z%~bxP{YPaC);fvM3^O%nIIFQdu~CiC;nQI_#tn+a7%nkClaXm^XGYz$OBgLOcD(_GU2gG*ZJm+oOyy8NE8ph55ipdLW z+^;#y+P+o8Y3`d1l1zTk3={4tP~jksG-JIMdS2=uPM-wFG3*MmhY!vSFv|F9RiiYO zK_ptLdbphVv4vJ$T}GOV@DqQW67HlJQ)g0D<%&;1(nQu%Zhm2vJ7D`(ueNRrExKC< zR+2)Xr=;{pMmSc+pNQwF=z49FIz^TG2~|gzX>-0zN_pYMD5_b7E*kOCQu!3L?jCBm z+1e=4uXJwq98uaYWI2ZOTmJwy%-vf503zxT;Y)!*+lPU5MM*!iN=}t6ZX`;SK!Kzh z;#I>rmgr_~wQ~DTpnk<^NYn%KsZSwbL^zTYpm9zk0aR<#e_p*z!g1(&Ba|~8CLh(d z#c?_eTLHy#rA#$)!%7&_#Wpgsc~Qq4J73CG7aB1qUUN%&yDb^}rR&6~*@PiYI@`%8 zO38&oF{w&8r&^2-6(HH>(+Nq32_U3`2^=xlFvgPk*VRYjGo3RG8FXeG9;#lJV$_(t zQc+>?#Yotcid9~rC1SNtMH4%$d#n$=+zth@-pY4=(Qby@U-?62rIk2JgK{JwfHZ4R z0Y)T%M#?o^)xwAH%6bME^z^{_bXCK2qaO9Y{?ECaGj-QF$BOlTG-0WW<&lQrkwS2~ zN@%5*3>CpaguQgdw#IH*Ps04cE$7LyhI57)%h_48WzO#8sl}|VYf?h=sQ7_x01`oj z;f^s!}n-o5d zPbHqrQ=8@4J1pl;CD&4&B0k`Rl9Yuk$yg}>f}yGm90X84<%aGZAvj~hk6%?-r%E~_ z(SDF%@L^cqTpd%yFv=g0j~30?jb%+!Q7fy%M(G1AEfhxESgB)eN$9s!5^Fr<;s&>)Cw#s}# zbuIq$MRrF_kEiN!m`q z?xItMdLHS{ITZN7#qsJ|sA{VrG2!^VMGPQEBQ25?a-apafNRML&n!)=eb`#n995)~ z)=r(ZLu^Tqr4J%N_Erk-MOj)HNrxQGOE4sR_~k>cpf9>vjhEZwerekz5%;V8=kTY) zOa7Yw0Mk)+>Q|*K0|uuR*nVQn$kRy#H6^jR*YrMWw1Pd&p}wnsy4)@YxxixwjCpiX zRmGm8B}&9bCWHKY(Y8}pkPO$G4#(TK`P_^^Hz1G~O*@|+_Tj(g%626_$_*;We@R~2 zM@i`;D69qK&6%l~5JI*v$Fo}J-S+!<*XD}9g&*l@zsV>1OaA~(N$k_n91aYTis6}W zG-e3up)s_+b|vRhxONwCj0VY9?E(&l$CPO4P$UdGqO9ex(n3_PZ1QM8>DNUuJe}0s zji0jqVa)lGd=nMJ>L8@5uQf0#N;b)O&~9Zru6>>)4kfyEZ#J~H+CqpwYJ5cP5g7X@ zr@07FI+StZaIM7p(bWtisW}r2%9u!=dWvZ&s-%`kjB!P_EwV-nevz8y)&j!Xo=8n@ z>QqaK5LFvVoJ5=}%rN6)#Q=U3ReGbJy*c#GuPkDIp>doVgA=EbsIVXAVlz-BsUVc6 zgzkH}0_;VHiw;Sh%Nb*6Q?PUo2`Q2~NEpYT4w@U~d%W%XliebF#c2vr(uFIa69Ar} zG)Qyb;@3xqXPi?a^rtFH(&2`loZ=O;Mj@0-xQR_XN3bK@R$+VI+z{W}y=v}-!c2*s zus~MM5(w$3T<*obQ*ygo)hTW^Mx?Y-8^c1PJhAs=yr(mzT`m^|&9ZnbRN zXh9M7f}{c^BopGC3UzItISb0=DJDjh5Mb@nsp0+Y9kxZoC~$ugek1X%Wq%BK@d>)6nmT)nM-tRk<@{!jP3Ll~ zvB*#Z;yvSIaiZ#cd7jI-OZJIyeWW2^^+2pzut8vPa}`gSL%OY4#ALGsV9Ts*M}J}FZd>ISHpD!p(oUEPAu0eZJ7;K+aI9WVePwnF zX?KY_JV{icSonH~#Bmj1e}(23h~$4%Sy!b!L$8Mh!SiJ{H-W8iK6=v4Sw_nQ?HNAs zigiW+eWD1xxL=uNs(#JOb%6yXLN=0^KDc}h9@<_a;p8onNeTiCfsF7qaUCu7xzI02 zc^+Pg^(_|_!}6tNY&~7X8W`CzOv9ORw!RzT5W_hNdr!zr~sVnf@i+ z4b5;@Q(~D{8_YQFSB|VA!Y~^`Bya^G z+BmcYOg8GU(x@}H5jgc7HBWe+OY0X-{VM0qqf1GPW^D7E`tO6_wNvbps}Zb=Db+nh zLKxygWMpKv2T6+> zaLXsN%`Z@d<^h(Fmm5&hP6Z`Eg%jbGv`Rsk)<7f)Acr(=#@WUGRIPX|B}8CkVH*w# z9?WXQs{a5HOhc-D3eK3mU+G+PW-OhHS7BWg&j&6&eh-VohR+o&FG*K4WBoc9;%Q4S zxgxLyRe`=+v$^@U^sVM>fu+^t3y+SCdZG=rtdDOAXjM2svY!rDTdLumne z5~owBr@^mCz$rrvMxZb?Ro;qv{{ZSA()U<@&fGbML78(kWpr7Jrx=viVM+YJg)_rI zPnMFSg;sk8MPDpj1I(ex`x3IqYz3|TzL(p?_iMl;!A_L{{7H>x_>WaZ+0OK4cb7-J zbxR5$omh#}0Fkmlz+r$8DF^*r$bD1m4sGjaTVtxsxWx5sHaAg-u@$woQtpk+MhnK2 zu@qHOwoxA24h^zx%geWAA$Bb(E)7t(6s4#VbseTLlZ;8}pe6od{o3W_NH7Qh0TBbs zhgAo-E>X*wmldUcsN%JFP8yLp6425b>W#zvoD}f}MFg&bSq{}UCgYNY?|$laAZu2@ z3ZMz&Fm`R}H5>#s72_o->Jm>>a}+LRY?s!Y!-8YE$E6uR7p2J}mZJ~MxTlfxaV#|< zBa!Olh7%G>(JGm|yLnA_Qi9`wH015vT(@m-^G&$of|IO~dG@4&d$hJn0zrtQ^N>9x=DxXlZt9m&uuNuwCdko2 zQfOV~ddip?7*s@xt>qMD1-CL^c(v3M!A|gYm1CC{EG}(vd?^9YrqU3iKtj%-7NrGX zQiWoZu$ZN%KFgYE=5AY9c`0p77TXK&3yybWDm*|V0Obmf@X8E{0um}8Er+#CavlEbJHuvBXE$$Fi92;==ZWGXu zl}YlUlGzv5uCl0?8z6Dk900d2Bq5+T%tC@4~jg{Nh6F@N!g{}V6kp=!T~k%ycwAGl`|J*+jSi!k=e#oI>Ksap zX~iIoCs35A@jXyu9yN+ixTe;iq>WS8IBz7^WX`)_`GSgp@wy3o@n25_ zp?6ZxACoJpy@Z<)_Z0h0;oFcOX#2LE@W`(+wF&&g4z>sP#V1U4>WJ%#9Auf2vTN3E z__pFs*paY_#sLNlf+B$KrC>jUf1*!PR2Xg@Ta0z15umE98G{U~qMB(1Q(9VBL#++wc(14XCEd~)O@UL8@DnSZKB`GS@p^EgJWqj8r-b~{1 z;@#&%ECLjgq!t`9sqUI}w;ow*LWk|tfr@ma1sx-=Oub_I;>Mdf;{JiXJ{+x;^Mr`+ zQ;JcuLqy}Jj(e?cqM6dAoqz&OHz~>ZP!rq?IZ;hm8ofQ!TlIaPtBf){dYmqTt5@_nd%b; z>GnW~twgv+6^O?RQ9@6=V25>|;U3KoZB4ltUuQ+trMKOZwGAj!p=yJ~Fw~d{p9nY{ z4w@O|`TdhW<#|3@HKixHSW967s>Ps?p@@YQ}4^23J zP;6p~I3bG>hCe=PbS0Lk#;+d5QrEJJ4$Q}ayI1ZIr5h#NvRsj&gqNJs1jaBU_=(b# zNE0zMC1)tf@-T;roLZ2z1c32<#hX0*5-Q-b6& z3#%tu&9Mq;M9iNGQhYFRqkPMJKQxrvSy~6wq?4s+Q)MX%g(Ua7RJDQP(gq12f&mmQ z`ijH)J(*|0bM|w=alAI6;FgHu7!_PI#{rAqQBg^V5Ny{V1eX3B!=B%AOWdP0ZTs7l z-F{(_rD|`wTFXa7EeVur2_TY{0DqzlWcOz|uk$Ms7(!4QQ3Vokkunr9gV3ay>8hQ^ zx+l<_Z#`Gd)6TPDaaCh8ijU>lhXTcL$x>GUFf|Y*O*?KN>JNSZcVl?&@}|&(XzSnr zpV+M`Bn)IA$-rPl;xQE@T%){|C=|?@z=7&YPr8i0UHm(}Qs)Q~qa+NwjzCAfH3mG6 zqreg#C15uA6$hOi$$L#^^`WNAFa!V$+YzvJs9{ij(`+GRckOvepKw1KUEyDbmUXAA zF?CxyW!x2FZL-G}B9AO&{{V=v7GdFWrw`oiKEM!$(DIcqr1vgLPeFviJzn}N32j>( zM$hR*8r+%aBho%isD@nSnjpsJAUC?z6Wn*wI07!G@98;J3nSpk^V6u zKkwMkHO#>cpA*fe%fx-MeiU`ObwTN?A=--~Www>mP3=t$G8=g447_=jW>;#3w99y4 zrK?#4pXjGq2hBsGqr2SZ-8d;uz12EX<%XYup(hjSE@_DcCR|E<9-V$`c!4?=%rkYbdW4@+aFNp_kSd5Q^el`T9; zl6mT&YF@o`%PU6Incp6wpq?!mT42qmakVbm4oesL&4q$By!%KUYfSnHljtbg%PhTn z?P+QqAaM1dD>{B4{+sfPJJVt>h_ZX9%TXE=@M#Ut)TfY*-)gxga8?NBU)H z7}T3@x|dF3;Y)sIPq0x-&tHnhTdGNDvYr{d5?5g*n1U=1nA>Cf`5M34_2bxD*`>TN zQ_gB2^yzO8N%NtLTduR^-Oa35-0eWzO&H0X{;2EYH>MmtnIR`hlDv zns(ez%~v$i5)FvixwN*H1HTV#Y=c4?Km+^Kfk{+Wym2*y1?#3;#o3dmSQasunStB# zm|Uw9do3*CP!Emtw!9Xy&-A_KkgWwGN`if8K&8fgN#pW2@@%g`fyO{0TvHN5C>FW> z1uD7SZxYtw>rIILKN=@-=8=k&PnY9MoHM0eX~(4lHRs`n#>GjC1;UX){{U5LDw&uc zj@}5`vH_dJcEOC5hpu=(47$9hn3wU<+ z@NZ+5HrNs;tn(BSy3b!w(vlPYDslGWXbb#Cy()S*&R&>t8cv!;lydh_vf+-q1&)rY zmK;i@;b3KJh56@l74If?y~XvEf4V`OoElINSbPcx_NfLBcJ5f zU(SCwsakuDI`oLwsv)3mF+{WLX zwew=@MAGL9s%K^M7~4yp!`LiG1T3m(DEo1;mAQ(KGiFS!Re@z(X|Ni~wep2@Fo~pv zPK;t!HV(r;{nxnHkG|TRK}r>*kpWR8b%E2+cu;=L#w?#pue2UYO!sP5kfXy<7{KD6 z;@EJa#f5rd^)Zp*iv{S{Sut#zK>lpln_#akHC`s_3sb{0GYIx1n%&DN+|9L{n6JJ4 znjPwC7Va%2w3R79f>gaph{S*=q>~e}vWGA2TQ6ZwIdNhfQo>M>rT802GEaxZX9J`G zB_k06j5kO>X1DmMHwv9lW<46 zJVppyeK_4T!`;)b+xQ`{#m2IKgdr(+P-q10SUQFpYb%x8zD^1d#lz_icw8&g63QbL zp({&@Qpv$7N`y?4g&7}6Kk%U6RNkL5eP2a=NOVFO@T`f0RLqt5Wkw+s)$1I@N@0?; zG%~w0v+gc84M%=LIe%k0rbT4)HZLL=N{emXG^F>6Qi*hT%@`nRDoi(y1Foj5zkk@v zShi-(<}MK9fvi=f#03Q?DP;>>^nY_0?Z#@&KMwE5uhPF*I#YpUyjv&dj0#*j2@va26xHFtlq&BnJyu4?KVT4W?8X!=jckwIrnd$G=U#fhm(zMQ) zZ3jxaY#zTBt;DM1p@$H~oPubeTBb&kkwU~xz1zv)E_zwn{_fmvjl0*mf&&h%No};P zNz{~qB&rDjl@eeQbfg|JP(JkLqkr#O8F*W)A)rt~R0@)^3yTR*1ZwahG6CA5gc1yO z`_!*ZDe^Wm){0zr2(QC%=;5QnL>PrPl{IZk2&o{9q?=cKgcGm35);^P0h`{b^)1pS z3?~q091h*8IGXMM0A{t*V1s7y1W7*TVDe)C8X?6 ziD&)wKQrt!olkep=?4U2dJ4D?O{8%&cX~(D5A&CtXlUkW>gK7c+fP8Xp=4;|JDyo7 z*S*O1S%?_`%LS2p``&iBUJ^%mIz7K<+D zO~b(`{iBZ(3KF$qohb0iVCqrmt4j1!>3^!-KFwL5e3#oob?-)8QC= zepVe$&k-wm4di6Mx=oI}=6>{BT<@;%{(Z)li&O+Q&~r*uP=l>XQUN6;#pwVa5dugX zD;&Ey-3yF@-fq#Q#gIslq7pHQ1dL1oIua(89=p0f)*n%MtEF8w%6LJm$(Vj-rp!5} zu+0*nj}HwkB`}HDJcdcale7>!lg2wt{MKcaJz-?ijyrRuxk`KpZbF<=mPiRPf=BT| z@*`d6%P#Ya>sHW$ZQCkw#mJ3k!jTg=CsEi$s8Qd^5XqPF>;`l%IWtteV!*VHO9U6v z=D=~j&$7djWR122EqdG_a8ikZ=l~TppcauaCldpS=pPE#FRpzL^-a>ji*>)On0+=I zLyF>3JdSZXS#333jOc|?$u=5a!rbj1=kG>On2tr1qsNphauZ4W@ z@9yF6HbA#?Yv%N&_m6}v4k)R@Q~*K>lwbplU^dZ3t%~i8M%3Im8h(gksyKyB5)wjPZ`F8Jl)g^+Jtxvw@P(Yjcz~yX|#NO zr@s}UlrRY!dU|NdrWbZotdb%C-~ieC{j^MtcOgCjS7l;l>?%38^aAFN`B? zR_9%_l-SNb?F4~^IC}xy5BO7Ow;-vAZa@D;s1skjmol+GR>^Lt1hs`FI6XMurTEc5HMmBcQVRZA= z)E?iWf-@`qWmd!E!yQ4il^uW*eKDimVU(4tVnHX;wLwyCII4B3rl#!N%($S1+>Kh{IBj+#nYfKM!SM&ha>HZQfaurxcm# zDj)y{kx&(=hfXOeaoJ?VDT z0QLYrRj}`&pIkjV!+LK^>8sR66Ba3f%M_R%E)tu}tIRoWpni!eY8aB(j$Dv=v`*G$ zh?s%6WMHWNk}eeq%4Dgd^*)-eW27=g14VgQ3P zAkh`|ndv_e^q1DT@(o1)0M9bsB}*PHmT}0eVa70ui!~iwZavcK2uX#>4mIz|7j^Tb zZxyh50C5LH$QWr@>e>RfiP&W)6wxMcYO4k5nMo3b4TUFUe8$nR(=Vi)gGJSUQyo0W z5HFb)C77rhbY(x}DVyfyb^icWe7jrXd^jM^NN(9f`cRSTcywVjM`E&7JpiAV&bM|f zYcbb*ZZU%7cJ6QaatB!B*FyI3RCEgC6;x{!m0*^8umi*4_3+)aMJ3h%D&vhJGX+?p zhAPP<*lt*pu86<4UIA(BVs!Q-EC zsj}G1VDyRh)j@tLP}b(G`_tT|M+;22WhN%_jZ~_jIF(%9FlF{Exea_g#~(pHIY~Lsdm|HY)NfM!+_FLfby+Xe+QpT z6rE%1jYfIuOlG$U$k9iLwJV@7)Z#Kq(9o?w?8y(7^91Zlp(57=Gk=;po?orisFJB# z$(@r3KpYY}HbP)=s9SV$t7~@AZpue?$`hmk{73kYN|a?vJXJy;uW!Vs)<>dW#Y5!l za}wemG-H>xWtk}>6!jQgVx)Ca!#G1KS4S~+S$7q>ge$b$l5Lw7*H(*B2fRTdX96G; zkUH`85kec>&HFsVPN_lD;fw%3J~WK=)zi+MFRHBhlJV>sgA$~R5lW~MdQ>eDs)jn3 z2_k^%Lpkii#PcSy>%(M(+3|8Bu7c%TTA(R{5cTTW!6r5wN)?pz2XNK z>3>SPGf2eLXFj7~8{!xD>2PSOF{#Ucsve#z{7B%7cCFKSo>?VB28-7u^mh!aPyU2) z9<_-byXGe@-7D=sd(DOs*0+=ppN%hiB~gZS@;S2>aVZTB2|-a(W|c|u$}X+$jm$1} z09^QM$?Lx+FcALRz%9TJQSqf`9Z6K3k_1H^ zXyAznXw+S-N$yDkz?1ZHIwYO7Iw7>95H|7Y>n5>Q;xu?vYc*_}OpUfA8oZBdgpE79 zk=PDhwu`0!^E?3QCxE24SB=>KTrnmRKZ$CI(uD0&pllp5*+4dQ>X%laQ&*7ks!xZH zai^)BXQ^`}as_CpDcAt8)F4WaHe_T3va48*4=l3FMHqePS3nw4Ac>b0HmN32r6d!9 zB5NLV?d;9jLY%O&)_@=>N(*sHQdI;ng%1K8PKUL+g(7tXr~^e_gA&e9)O^j--1O8l z;uvlnf?`P>4LL+au33bon%am#`-Ml@^9YyH`wW2~ylaD>6=vF$0DN%+?3I z#%A5+#$TDGlCaA!C%8-|T%PbKoJk5Pfr@yf?V=~@6DtZF&GU1OsV$WIx(&Y{9XXIY zyLa9-q;Rf3cBPdsEX+ID`-DVb2-%Ml9||5lDEcYDbN5Hn6!jsJYo^8~#_>A%;>58j zDWP0EKFlsZm85;|OwkSH8Fv@CazOw`JJ-Ih*xi(6@1!6$gpz~>9eZ3llprV^Bp8T@ zB5SZ+mUc0hFDtjWy|7>AAT4WgYHTPJB#CTGg(X_2!j%%32SEa?0|Lq2J?NKDV#=6K zCmvVJ$tzba4G4~&C2EPx^F)f-0dvPaj*75mGK?%=w#7n~zbrAmp?ogkBfXAQNP zDr&=XtV2%S3uY(1(2@t{GtE1Mtf174%vbgS$QZ%;M#BtM! z@~b`T{{Trae_c5yZj@(=`Gy^aADE`E%awG}BGt_qj??PljA(DP5J5NgaGAT6TAfXi z*RbsyIxE&W<m6CZ?{d3Z{!PVKyvfq8rYp_j*(Bi*_Jh{rEPw zc%73yRXF9Hq1azSUnP|v>Een1032cM0-|&))gP#@P1PUEvR*ke(Nq5bmBH~)^U@&H z74qahWGCW`E$rlbp6<1ddJlfwFZyZltbC8CslAK20d1%$Ct(B-M^P1MnGf+r=~q&6 z-YSi!FjyP%sjBf0G)sPSPmoVP%v#Y$e^|zQ%b)d8pI4vL? zbq$1dk7Wu`dK7{bAp5^ctDcSY1Jl1)=zpAb%L>JDD6puhprga6>Q)%z5{8yfnV5U> z${gDF0><|7=1|>c&t;0z$pco?5^(66kMoSq;i8nZK#)n1Ja|!w>CQ3f+o9N|FE$;} z+zSrC@ZyG&s-i<#T~?%Bnn6^hA!KbWs5%gJ;d_@a-w>YpMD4)99?FUCFRz_Xjpc3W zf$oZr>$}&j4oB#QU&Q)jOmdxmXO^Olf}%QleZs zj#x=WU%56TL&Yj`#&pA{!?7Aru^M?JD(qN`k-JvCv?EU*{2#F5UK)~Q z8l2j>Malz>kffc28KWuqVdh7#_0xi3m}Va}U&_#9)rMG9H~FYgJ{}x| z`%$$k$z20#lz<0MifD@N=?o;5kdYusFgEP-HL@i`Wvu6yWWq5BV6LIWQbeexsf}cc zRC|Vscw7)c8d-%dZq2z}X3W5&OGw6$=-juqN zK>nZU@7eV@*+vT`w3-JqUp|pZl3ntZyl*OgegrcKv2M} zM1rmp);8^??Ar*GCuS5|XUXc=@tR1bhFGKXshyA=$Xnl)!*?u4arKT4T)H2Rof#1Z zfDDuAikq%pzdCu*uAwBafaWY}6~z*oQj%?smFDtRO-eH%190pPoElo@=EmE-Y6*~$ zIPEbp>SCkZ=F`4Hlz)U3dVz&(`Go!-{*h`kt!@v~%$bH$WjbmZaO_H{=wN5WYJl>P zQcbilT6MUZP;RSCuY(r8oItyZWucz zJ*I)mJSwV|uvXJmNgUh!!6a|A?(VIp?*p#9kP*AgOyiG1k18boY~prs>h{y2j~*4H z6H3QGblceJSzJRanR2b&XQx?^-!SHP*MzQDw?pa~r6J zD8f`p9v_BJJc$+dfbIpm+u}J6c7T$+uq0zI+u^cd)Ss0dIcRU1b%dQI#+*neU@AcX zo~&wD;%(~dDE=V1-z#T)g_ZFdN&tjFd%qkj4QNO6W~Y)((#q1GEJrhyRR-2Aa^DUQ ze<%iR$4Mjr)taH#?nd<4(Aj7V6Toqf{g%I$~9cJ#pBSjXC#X9r%+f2gOhEF*>`nAN@4)$ODsZ+=3e_fI9qvd$|7T|GlbEX;0>ii{Ll2rc%=vF-HmLvNQGdv5i$g#(G4APhX{ z9d~+_zuhe)a2*7inT^)rrz}+FTDsawyg@4{;s6;V3K}*Jb`Uphupss(_R#Q4dQgis zJ1Hs-AaM~O&L27i*cU%M8-)b-YdFD@4jBBXG>!(hmL-YrsI;SBXgBfXL8q*HYGJ1u zF<(gS97Z-@`FN#%uup*F$WoEf?WUBFszlXCPVZT|oEc`0MTta;0dE1R&@u7ibgTs# z8$kjOJ9=uRsRJKBD%{O~6CS4Eew~&2YwL2Nt3FU*6hjQkG#whDqM}-;DUb|0TuOQ= zJhxjEX^WN6mD0nI3U^uLT!a)Wy3}N)1p*KEJ)Hjp3>ePgm!ZAvFw2-0@ z4xC-UY6!>eI<^xy)f{GgrI~$Db(*)R9YLj^F=tHKSRSTXF-L^UKG2~U#S$b@g%~s3a)BDmsZI$t03VCmLJy z!_!6?ma*z=YcSzBHZM&_Ch4gq&Cng_8{S0$Lbto_g2PLOJdg7$$1W|LZq-GnRD}dM zP^EWjA`-1X#iZjLXjhVM&RdsVHvPjz^dVBF)g&te0Ehs9V8Ot|91U2GQ_dcN@{?B9 zX0J?mCOssyl>#WMI)zMWVI{rUBt?W9s%SK0+}p9{0FA)kRi$WF@D&9oN>mtqwKlvz zYBVYqq{4u0WHxmIsnP{c`G#+8a^8zuYjz~~ifnCxP>3niK`9E_U}1zBkuRxV!|J{m zDDeLPM)@lZsi2Z6U(3(1fjndr5~_+jn2-CQZyh;n&dc|@;R#DS#c6Z|> z02vC}kr`-2qyQ44H2}**s15+F1f$J9!%TU{)W4&w%^f8s9qA*a7+my-RpkD+R03o` zOl@?dMj;#CE4Z^?X+Aug+_Ag5{Lp>H4*o+*WITnioiH?#;YP50M4=6(Tv84-2?cMJm?Y;!g?koU<~@>>aZ=k2>PqZB4%8UF(drf|8~Y-mOYd za0LS5mR6l)%7Rjwl~~DbLq)YT2~h`7NDA`6U?&q0WNoND9_lwo`X|$hoS&IGJ<>eg ziakAAu03Ch*R^MvEb+@6jTnv9ypb4G3Q+B4_m=D$P|_B=mHyf;5|+X>co;xJlCJ7O zQdYGnIHv-FwIw591Ukm=TOdY*wtmqBaRiV|91h+dbPIL&80n8&GtAkaE8+Pkr*LAE zMI+GRSjHyw(8!2Hs|vbD6fsJ`mPAESrorCfJ3}uxy}<80o%4sG#|HDzZXWsz?6(8f-=C9b+eR zZDPpYX5n#b3k|kC

IWX!u&gf^^^~*J!T|(zHTCP?9?0Pp_R~smobY3(55PA#v=6 z^mI6cxQkUohgT(RuQUP&rKzk^Bs7RrJaCbuhj2Z|5&m_+`mRH2l7Nj9`!S@Gs3v~% zII3|FD{9?#3IbFl0#){aNg@a)W;zE>G)etY;Q3OHuK=UM@vJKlMOHID7ZmD*GpaF~ zDwesBDK^{O1H*(~xpWS+X^n#cKJ!s_eU&knDG6w4k&N--HD^Ab`bqdW<#?&6ac-#A zbsegn8hN3vz%eW`3ON{udY?9s7oAD820PhF-F`!vrfHhCbT-Hd2k*cVIwMh^EIMey z!zX3t^^XwQ>*rR{=+CDfh5Cun{{T_=pQn5a1+2mHdgXVZ7?mYis#=Cxh_MLh(-6Gq zWN^FK5TuK3@!=(n-Rs%4vL6RR(h9_QPl$oCV9Y4V5|QapuW0vgZvI%}ZPpqp1cC_H zfgjw?(0XHq2U({r^d?GVq@&1K4K+lIxXB(L7#oW1KI!hg&F!Z$wOMt#%&D}K(nWIp z-SW)UfVp^oo@fWf@~=;5(8UH`!eEv{S|l*Wgn_1}-L5oUIH|0n-FSvjNBDsJw$N$a z?af98@%jG%Z6cVf>2k&$2HK1sg=_+bl9DjRfh1b%VQ&&UeS8pFW$YM|;HD%ci&TNI)*b>W+p-Gg0p6~!vT2X`Hax}*o8!A`qr+BZ|o;KT$DZt_! zZ}!Vt(uqux6DPz{3PFPe&k8-6$MDAWf70*8w>ADC`6s6pn7>Q0e0ws*1uj~anx?j= z490M$r~Y9_O%&*c3FMft0hNKf*jR9zKh7;Tn=G`+E-wOa9JURq*Mq5Hg3^>j4?0p* z7L=p`DbRk@sz4Q&*T*%uzx=YBTjRb>$hvh+XoakR(!6DVu|j|n-YH0uOwg~@Urry0 z?sMr*J%V)yqxj`s3!8FAX25c_1{EzlmG~TW*ex9t6gcuda5Y|QQAF<}DR`tT6ftWY zHpsVP#`7{3io8QkrA5U&`c#`|gKmJZ!q65%rV3D?jZOIe*@15ESmrI}-l$j;?kgMQnaN%al;x2DL)SH#FL_anexA@qyFc&a#`f>{+<50o5;9EYEi1YDe(8rH<_4AO@DbqDY#Uay#6=a_$Ca zZF*l>Lv5*z3mQZnI4C7P6rU2(v*VBwL>eU@@S(1xbt}{NLHZ?0(x;`uI){Q*&xOf3 zqJphyY4H|HXycNh)Wr<79_)&Nyu)HZ0_4s)9!;3HmWFdz6!R-U*6(^!9(^TB2<}gc z8AOiscyR9K2&hjmVRvsknIY0!E@?|;BS}-9BIY>iY$v;z0PB;C3fFt4Sj4$=){j@c zKxaBYF>H%TiBii83pDu5<{T=D7?hK+%)qc+biKI@?<+0a<;~i(a9V^OgaTBedShpu zFU!eO<-#@(e!*5{(%(znOrhz{2h!{!hxw*`%?_qu>?4fgHG|A|mR8YWr&c@I>H?4f zHs&T@U)y9&uJ+`VGKeZMCJ6~bM8K620FnSENdip|kg39bekYu2?y*+OJp`h{a4xNN z2MUqnpo);sMFmA{lg&V)nb*t;vD!9Lg6;0uDc1bu?roZWYUS3f*edaPNh(Pgq?F@F$hp?gUYIihDu77hp|{TvIyTTTU+X`j_@7m92Qgf3()u2wF5YRHqPr=qOS~ldze9V`UKL zcj?lUC_z$y5s00;YhCYJ-j%xP*BoQ5xHm^}dgQ}0jw^>_SjJw8q{9v&4P_`ur-Y%r zm66DvP&4sC@Yw1SW%c56T@sqKMJtV z!f){-%bu#T#u@1Q)k;SXQgGOX9t(`j#u1nyfNWSMwS;)A5w6xB?%{V2d=ODwX|_Pa z!~7~70oamyKccOKKsfDRmpY4uLx5@?lN@~dN3C0yVd*|n%h=pfWz1Eb=Q6`RJCM&C zlp|>U;55_`z&-wG+XKX;jfWKkk&jsvKex6j#UT49-$h@j`4cf?6sD4r16HU)+BIeu z7O@(Ap>2J<3SDRR2^ickBciPB1;QN|`G8oF6hi2xsEa=JLq`Mq7>Rv1}g`!ys`GSt=;1qCllWkXhmjYj!vK?a3b{-#oiIP;IN0RI{-m zX$n3`BopWj0d8#zc!BK4;YI%d1W$IPFwU$^|0tP}i|(Bp&LG1;ILU zQ-0-}5DV){0l;b?Pqv6ql{Nje1S8$E5X6razY>PmWJ5=DC+~o&icay?efmXs!_dKmU1^L zs*_>~vEzr7=9p^D9xTC}d!vb`i~ao`k8;7VKjQUTdI ziQ`4j)EB4B%T?3-53ZT*jyXd-^-(;L%JNGj5e@Z?31ZTDf;-I}&ZTzt90*$PD|go` zv;P2GZ2?Al6|nV*z|rn&-)3n_-z8~8z#9Tj-K8J^2m??6V-#+EJ9<*cc!%>m;h1Yp zQHDGspZTOx50J0IaTx+E(niDGsfJ%JSlap$$}SH8yWzg?#k16@l}qe3X;0N zA!9N+k1dSn=Wr^wU)*G>QlNvT?GGkQj_l^vX}ALt1Dba5!~@3+M@=3o%{CXdcMCu) z+#k!iAVKduO(@P7ENTA$I<8C9l0%=pIAC2sXv5UerWJ~kH9MF67N}|8xhDP`#17K3 z{{Y)5LOf{;>%?hL!(o`3j#ps3y>D8mL21PZ=mAog>Vt)9ed)yyPJa^|UoH7RB$cz` zv7%fs3sVr42)=|8Kch`~Anw)4yU3U`FpVVt0E$TVj4KyzkQvMtB0N$(aifujWQ^(R zCLXfk^msc`V3}Tl>vI)fmVi@71#+5s78y2~HlS^#2CH-1UUe$pc$!s<2~irHZ2==} zsUQgIz;WY+a~CnlE-bIzd9YL)d1^C+B}D8zWSxVCG)np{lrt?pYm2M-IytJ-rnt@( zjJ;jFw-f@jQq%-nkiKMYHy;6Wpd2)Cwx~+Z-JZ-xsHqnzz5JW)m5dZ(Kfc;A>c)i+ zTArJ-o>#`E=%1^evEXsx8hDnF=P7Kd3z-#p|CD==Ofdn4HxZ?kv@HcaFG2POxnoVT@7l z0u{Ima!to8y_>mpV*S0yMm``za$poF!j8$*lo{Ay2&0UbG)>blHUffBQwnkbQ3PV1 ztVn~6G=3u8dFp?qZ&O*X(;q_Xu+Qab)J!j{nNv5=VudQOf9BY6lCun?r*=r%8n%_1 zQhnWBcE0O?U6t!CyW9m5Q2LS-kfI>s091H1g@mYVDn>YMIDO?^HQ$7k>qzjdq(MoA z5})GL2T70sCIK*Lw*DbKLF$L%1=buZ)E7#z2y$LX!Z4UH$R)((^6J`pdp&%UEGoz4 znxV?Y7-kHB78g9p%TCJ0^UAxpEtcFV!9S7Ln`w=e5m`nSXqVl4Ag%ywN_y^>H^IP?%QKZOO2yOkgaR)5?%)$@j+Af6oUz(Jfkvx+U3U` zKy?aax1~!UCBNNS2+Vf}uWQ#eqh6)aa@OtTfKwzIxfV?XDS0 zf$=EXC8fs?5*%?V3Bzg-$RIT!iE`2oB=Sl3Xl>K%GHhu)Bq55Ng<1?o0lw|Weu_4x>9?^_k}H_CrL|M zNK#Z);?xR6__WRh>*YVi{>CH)T-JmXuy&!Vscr7 zU5H}c(Cy@6-scA{KQ(!B>yDJFN=zg#RH4+VQoTq4Dbfm2fgl282=5k)pxA5yx9vFD5y&(xFicL6rOx zRQ&9<6_JMdXr=Q(Kp-1Duz{Gc78sk?5KxDmF6qz$lmz%hA0OVJc8z3|lBkVTw$0~N zZ>HqSpR`hyC0MOQ=uCw85FjVQl5r$sT|?Ad<(9EbM!zrObK#X0vDH!3O-CtHEiFRq zmI+R`5+&7v_pPAs$xP=Ar7+`7Iz}VBKv+rOv`^Zx!23a>>pPb$f`djiB}pa*DOL&| zy;Ok9t3{G?-49rD>;*AQHll{T8ADq1GpvD&jcu`Zlk6lOLD`5GNOUV=kVN_sGxMeP zt2V_1e+dVwf}c@e^Je{FWBJde)hZy%xYagj!QXIHcq%1}6Q(gW!DSv`O%9+Rk2)K= zxx0JmyKMLVKKk6S>_G)U7M4exPn|=#m6Ebt&1z}@N`ljm0}4p%i4|d($KrGNgMJ~{ zjysZiN0(&FP|HhLaOcXD^8-m!JVqLyKNqMa8Y-%0c-}VJg-(Lt9$=a~C*2Ooa=VuE z3y>1}2yu5#r85|yCA7g1V0b|%5O5}@E6npU-b9(MJ?_@CjpmRRXuUO&ynepIcF9LbjGu!yia zI(#;wHQVrKIc#WKtm*HV@m5FYw=S($Df&Ap~{@-FQzTU&^H+$k)w>qKg4 zZ6r2_0<}s5X&?zwuo4Wf8Ow6JP;%QdadH+ASaHz9Yfl&5Ql$W=!XrwSqCiRj8i*%Z z>0|Jc=_Uo6@n2aTbelZqygsU`I!ZX|YO1Q|m?_xCGv>y{pHM!>fxW@tBG>ZvO_ef| zxscjzn$VcwL}J|(Tv5R|t&5|o#K z7?4P%H3zP*Kv`d-_;yzGm+A8xtIhanrm8sAMJy4(Y9NpiER4(x#_R~OVPJNfjs-JS z2b)U@Z3+89b=OLkqBexLAYx;xJUUL=lrsIsUBL>>@1Il33qygImJs3=2-1d#Lr4<^ zASFvoK~kiWJM~l4&*L@fKM2a5Y0F(Z!}>{<=;wkQKOVzy`8?G5vapHTXqmyKlHi@k z$sfIa2MhlIGWF}4%hw7TN)Q-ivd|p?*pmbhKWU_50GX*G*}Rt~Yf4#XQ+Ss>fZ*`}l&cdd*hr-Bs4v5Fuh>UdvetL}Nj*uf84h4AJb8i|<&vJBdL6Y;Q&d7k zZj|nT?UQ$xdx8OBaInjo${g;UWu}zrDh|5p?v|xQ1uOXV8~`Ng0wGvM9l5;sIh#eB zX4FU%q!bh-1Q1*yjY|g*03UEv>L4mD!>ifDD`ZSNEoR!&hUbixkJCq5WTue$b(E)M zU(9KMCD2`i6l;bC*V6pV7dI0q?K0VmoXx)f0Jz1n7PN^_0Yt$`P$f8}Ubu>Z?DvZQ z0CrTXdo_d?1S<)Wo)DoaJ4BEVO)66W$k_)HSaPi;EjAxt8r0IwPfr|W<84$i0{hnX zz4?&YR_MwE+yZ{pV6VoH zcU2#!ICfF4%^9w*3&UvYq4(=6rl+TkkdEeAij4-M=aB*~9zpRH00tnK!;H;jjm^7v z0IiS;jw48u?iH`Da{Na<4D_!SmnmirqR?YiuuNb`@F=In8E)27B$SBpC>|}o!@mG| zwdJ!?qUwBsD%sXB_st3IG8?O;g%s)k02>4B{nQlaKgJWHc{-+QJcWW)V>8o|qNZ8a zI3L6m5r$%-{x zsN6708LOlh_o0D^7aIPOKopa2?ctV{Bkse@(ioa`k3MJW^hj{L9*YmUfLgk!U4aAw z5+KYk?7q7EIdJ+>wEG9+OsN=D!AGAlNY$~t?-m&u_ZmDe4~=YB_e_-pvXt>4Yus?f zyT*AZP1r@AE3YQN{x-nZRs?PY9E0`KUS&kuz%CIp5Tf+~R9k1co{X8&D!q8

A@8Fc8dd}tX-fb4Ij73itYv-H)i8ihV24hODxzb(r=F1*+= zvrs44nWE*`leIv5N%sme`BTyV0OC8Gv z^PV&swrvU;T;NC$V-2I-NJ>tTdVb3uU&>{iKC-AHY z{igCq%kSM^@;-I^@8$FPTlV+gw|8#~_tyL}{?EBT!>glEn5I8GA~BCD|I#HroJGOtrEVQmQOBCrweCB7IC$HdO$Od>MgoNF8x(~VNgDRkPRD{4 zm#TpmEE7TvCLpqlskedF{{UYX3}_yp1J(! z*jS{V_+f6vTH@BziB`~728zEf5UohS^o$7g7}i>9EE;&$TBxIj8bmu-5e!g92BZ*H zIFt_^0Pk>kfk+J}N=5^K9}3ftx(rECQ5$7SQQ$bKN2?x+E_7a#Jqh)T7;GB{!|?3I zTST%|8b_&?s+u>F@x4h|J;r}}z?LHB;4!i0J=|SndCHBut~BO_6Q{h`p@um5?XH_^!w5NZ>y6RY)8+;D=VsDj}4@yBXdKC zVGkQd%hW6DV;qsUm$oQi+QC7RO~sgP=jUnGnZ9i8lfRb>uxZli z9pYPC&$eN*66Oj^XeCJnNgC8;M5Zcr&U;Tz^k}yT64*!l>hAGu3UDM2vuTg-INppj#!f?c~fd)Rfx1>NOBbP)esrFa&~d z7(js&H81Zj=%oD;&7T7@GMU_VVM$&gFe;##wa5V zFlP@aW*1=6*>@E;TL1#u+V|#vc6FX#XBG-_^?Jxz2~i#*BN-zD2LJ$(#%t&E>Q`~{ zJ=4xDo5@*A1#AU8+h$uzf}tcJjY(33l^KO$qzEz)=1k)BRCt9amKls~B0a`|K`u?s zpf0DABaf1jl0S7}g_d33DGHt-5$16B)p=uemH3rZlOXeDtZ=EJB(vBe+uFw5h@M^~ z@cC9@+Ax#=k^Da@-0RcUNx*VW4VJnuL%7uCtRoMKSlLJ>XNg48K9*gil>+`JPGK%* zcwSP;IF%XloGMkYw;F)x9+Sp|&X$D5Fxl}GYl_TM6`6n^ylS2^d;b8cfPGxWY~B9# z!au%0AJV1!1VTj~e1S&0)Y`xRM=4^NGg2+GF{3Gj#2G>jEC&WDO$}QVAN9U9%vgS0 z=*%obXN+Q=j;Cp}E*C}q{Bc=f@#007&K_3&&2TvZv@p+%7X6YC6oO zI_~>uMZ>F{QrKw`u&GcKaKb<;B>Gk?W@UH9qZl~%e7>Y4lAmlQdh1(Wo$jNf2~Qs8 zHUnuR-LJ@hT#~(l1Rr7>3>L%1A!_ql`e<2Y8j&@&E30OQQ)uWlhCdm3hE|<{{X@# zqdBIF*S%&RpRk!Qyi2FJW-TRk6;wrKrmdO93M*U#{xUDzSdRRZGhE5L<{NU|T9Dw> z2-s5?OzbjZFd%{`8*Oe_DoVy6fsdS;+2Uzdl`AK|y)ytw`^~MbwBQILVw9EX)Ou;6 zM`K&L;@<)MICzA?nkri50D8>=U1-G{3Cb9abT7S%!5aGDSInqfWTqa4TlA?IxSt=GJkzrMYI+1d0 zZ*Sqq3w0WBG^LdIO1vgu5Cm-7A~x)){>x3kDbp&QlNEP3WfU+|(qWO0E;wU~G6DM` zPy#M}mOAiorD+mtB2t|o0l)!TZqWY#!lBMi^%IO_k5Qd1!|F2C7Cl>s!HQsR&4|H= zLssy@^HS9kv&gXk=VXhxpLIr@>Am05{nf>bSJoG3b;YuUmR)Qh>rz6rA;3rgObudZ zjYKzF#;bdUBT7h0pvcEa=vK+%Bmg!Znm(S1{cUu~E@h)HywZ#{;`x;bE^K zR>4w$986Y5-96m4wVnx4_5y0Me+b^MIVh`lgM=CVo ziEY42cI(?;9x!r&lB~0&1wu-QpA^aCj18N5YBt>$)o{X;q@f-m0Ua7a6Vh=$l(6;N z=`S($^EY(ss5u@?HjS_>UY;z^J|jy_D*pgiRsL$J(Wg_kNJ?2ON82aEhc=4RNe9Ic zk+x*?bo6* z`j06NX{a!aEnCDi(@Rw9K9xi#>gGIeL#OjCwfz>J6s-b;sRsR57{eE;;r?IZ+@~&OYd6s{KmD5t;G^CICip_7Yk`Cv!H&;)q zV|K`GJxYD)SFVP6n!s+~E|j)1>jZ#9_nMXdD-Ef@f721`6mGLF6@#xtvnx+XwGo^q zxU#fls0eco*c_#LuaNExS zhU2?Zn_B1ZSV&S}aMF{A_tHbpEb!sya z6=HawtQ@h8^+h^8(a1lZ)I`daxT?MADVfgL&`O}Imw#|MAvb8Hj+~6z-3M5;{N>^9 z!No2A0In)Fm@q^PV--dw1q(Ay+u6L$QIlj1erZ~Q9l4YFc8S0Mun1JD5v@fng%pI9 zlK@uD_&rr_J%?iXjUcOniB_#)oav7L_4R2zb94XkuL3R*l6g(0~GUKs*O z3K$JNdpMpuYFy9q=PoZ8xVs2(4FKpu)uAo8(!g4~(}biM6A3U1A$}g{<7VW7B zl&kxxSQ=Cy;F*B5lQ?0d8pT`A+Ixk)mE}!~>!d$$8cP7U*++S;3ewP(XbMwqDMhqM z)vZ&A<&tn7s%H+PS9Nze;8fTgkmZ^@zgE96lFs#%^=(#U3lZ|;fGmU}k>(57k~j*! ze$vj}HjKEZ0ew!S=^-HsNI)3kRU;BSJrsG8vz>1p>zS?fs%;B)Xti-A#@3}ih4+eB zN(l%~lL0F60RYLO3+f7vqOUcq%`cfLa+`aO_Zl5PE@U?DEG3wT5jDi#*O+n4#4lE* z>LNDdv~9!PN6Q1wy-?0rR5e)UCPa@MaWJJtfl8>jUvu6f{{S99cNSK*Yaz5?2|gpM zO?5i(*DQBh z=nuYDBGH{kY;8E7Zr`0#AF1rykTTyvdY_2qYA2|uj|_UMSr#^Uq4^N?Q_nLf{TKyQ z0(+e~EN?)#MWZFN;R}_GgpDUi@|d4W$Bw`iX?dRAB%}7qOKE9aQVDPeOz={K0qa`q zbieRy_21OYotL_gf%NWq=<_BSL03sBo{w~qR6?>vDN`=w-VW_`vDb)l?f%K^m`=X= zU?vGe8q#A749Ul+S6FlAuJ3M^7(pr30EvSbVOvxF2A_vlU%et^ZlXcf3@SXeSC8UY zdL%V0Ws*p#pe3h-K{16?v+TXMlDeB%a};;ad6B&NuYZ@crrB+TG*t6tqT-6wvQUJd z-~=S8Qzrp{Gc4}DO8Od?hJ^_SP&2l0>Z<4bb3H9&-h=wG$(?-6`QEakx2YJCR80w> zU9@jPu~Aa3Ig4`zD<+Kh_mrJ4$rEt%n~Q|p<<0~vyGMSNBoxA2QAUMIm8%rUP}78s zI|-(7WBj#XYLLB3I6;ze*~6pCisd#)n+1{>RD060FEOi~nBx`$O zw1S}qpex+SYf@9Q%d7F(O1dlxzcb@C7)@n$f6LPXz{g!t8A8K*gebz>jfaoI+>r8% z7Ve%XRP3Fng#j}x$@@!msj`qy9SJ;mNFW+xs_A#5jEk7CdY- zO(*X%uni4duBiB6-005SJrS?QNuE#}E|r9~%dL`d2&=>r4PL*J&HHj}2G&9aYQFnZh$vbPZb z07a>*MvjuAIO15AF*-3pDz(TYjlk)CLbn8X?@zPxKv zb?hSpz;zyjN23+!7f!Prv~}~s6)9b2^6lm%#@_147?8{3?Cr>g*EYDe)R~fSorOIy z9BCtrpvDxO%)XcU0o43H44<8{)D`%47h_LO!M(?n?vSO8!GGS@_zq3CJHvaHSy=aO z5T&&1iZ~h6@_>=#ngp?K+wVW9V3j2!ghBy78gj{=fO-{`D5|jDon=|@x_ar1^DQ)z z1Zg&ex$_N$fVP|te{F9`m8~lCAB7~ivbJ8+v#y2Qm+2>~eKe^4bY>thf#)&#a%np%#SVG z?3mqD1Eufq;Rf*UqI0Arv;c&pl4Qv^czuVihS`p8_HM{!)TKCrN=$?EtG|xnbJ>?*iTI+vAlmT0Vz6= zKZRUB#XColkyJhF(aPF8RCsMZ8c0$I1Fm|iUa%$N`tjpCw|mfla8FA}Z2gphuo8nc`fuexyXD;_}j ziKC@7bjazCS_V2%(yD5|#LK4m9dW9pj=vVKN`@)lq@iNZ07S`7UL5 zqVCZlFrg_R@F1wi!h+envu@<=(o+Yo4{dEhiBeF|$sG*@DNj#L6mY`~Yh*~*?5eMT zAKSywAXYsjVL{$bK7Xh@9a~n8s~4B(2?Rkj)wILX>MsV&$6LaVX0AB6mO!I zL$_`20q%a2rkaDmW^~N3zb=0Y6y&adlq39M`@VF`nduzn+DITbA}2kss8R@9_>a5C zn85la#DUO$6_lt}BCH4S`KwGbthtL4lWH6{Am^EemQ`=%4;a66h%ERwaqyxrSU$f>3NgU_jX5n=m&Tj}SOhnF3oe`W$K{ zx^ug{ll!os)~gz<4;DLy#|-W7EZgD**Yt?0MXjZYztnqj63kY+au$FL2vm%I;U4L! z8qL7^apG|HQ#6@^59U>S=+;Q-+Eh}cp*yY-fdrGK@9p4g^8l?_V3J2h-I4R7vX~J~ z=4=lir&fjJp_-luVTu)%nIvB}+gnX7xVE}mk2YGn0trbRA${PHoi5U;c;vo@HV>^`)lEv+Q& z=sgnkztV0_>6|{B^S?!KeB0CtrmOiZ`#wF0!B-ip0pc;yq-_wAjY$DFgl%p`&C63{ z^SA7jIK3f5QbUe}#7vgLyR}ZksU-2>ATZWYSP$R=RlGBTy*>kOr&)Cx#f!3|&3wN2g4~m9Vp( zb8_=)AZY+}@xvd$PywI1RnR;iH|1;-DB=@PDUG4b6*!is4?!_atdM{hghJ-PhPvB> zY`y!3TT}H&MMVWL%xm%yX!5!I>}$tO^Qg zB5Yooks+?BoQT#4Vva_U550S^y|wMargJ5&3O# zL{W0W+V|iIdDDYXAOe#E4X2|M!ia`oqcemUq6L~Vwoat=315-nrNrRNv^7(wlZrOV zu!$YfXE7mlcap?=y^W2p!H<67weKWqB4mBLcu!W^He1KK)yJ!6r5-%{_-*5Ohfrmo zIP{|#qE99%DXF7rX~1`hC0A10&_Ywa+wENFbmlSI_LXgzG9I$JL#UE9gpxca2*d*; zXu=4BBoJr~b8aq*R`PWe{iKo8@5kRo_ayou>fTVtbKXq<05+J+@Kt2YRq&G}4?D++ z`H{^C5&)K|vM@nyM{D1bDc+lFwwrNJAQ0fyjCg#H4!SzBwK@YVq?pvG1QXJte5lv{ z8=1pCbi*rkXD4-bj=u-Yc;+2~ni_YfSiWau&XQGCH)kmk+6}ik)41kFZgul6n}jf+ zptL7uBf_Oj9uXtZn66s=Nn5Gomt3RmY1cxCRDH+=DUad?3F;tF$&O?AlY=Ro3q-1} z_5l^mt#12=iS`R}LUldL6tFdEN|hZtK{4wQ>s;hQ%Zdq@k_7Zg0(~~t$DMYd>A#?S zx0P}aPJK61^-BY+!KrZ^Z!=ZXnue>EUv_Arm1*bwJ%;-+L;;j2waDgnQ)_#^@2O5) zw3oY<-ba3J0CX({#fCeVT5X0HBs5fzw*rA$#BJ(cY*^f8n_|~5Hw|JOaR@?)gQiwg zg{f;_-vorgg!BMI(^pG<4fPZ8HNx96yoUM zT!{Yw+{th(3h-Thm}akKO}BQJ&;#HhOIp&ml5O5sci$sHeYT!J34J7oP^9W5K+sbp z%Cco=id~Rt#4g=SE$IqNYwr+}tqPFYQc08$3RN%w*cWvt)Q?Q#!ExLVHTo&T;G&?Y znj=w99aIbiGPqc{3u z%$S#|tixIUYq0!B3CY+V8%tkPMN1sGl|n?x9JI1UDM;RUqd*u1)QfUf?IV9~ava?^ zjVW$iYiZY)rM0WRc}mjhO46kM$(Gjhi6co&Oqy4?w>LZ96`SVnl_(zNl2){$6QmtU zN`h9Rr6IJfX(t1XCb~(0^=y76)c%D%Q|7!!Hsq=b%vKsaI=c|86Hfxsy=Dtl=ff&U ze7Nj4Z@%?ospOe!zKgc88M{ul#n^kebfKgfeQMC^5RDz%X>@5^gn^`i#)z_?&Rg$V z(DKx>P`47ItP5#QrsXrFl;WHd_X15;Kd8>P^^XASu59U+Z0a6xsKN48b}{{5sKfCK z%?>LCOGk&(R7pFDW~GWCsO7FswkG%HUv_<+)6zQ3tmOUyVWJ~NJDSiUPgH5DhARC#ejLJ~W2&cxYYH-@zIz?vr zm?4qCB~h8za)a)=KJRt7Hpz4Ap3ju#?%fvMwYpLz%_OZ!c=v6(6yaN~EiNT3K7_ba z1r9f+2%w$L@?38|O6}%eRLhO(4z+@kq@)EcC&P#+@gVq2q@;s^s+-2Wbo!XUmajSG z%+WO_G-(!Pt&S!0x5KPKU<8d)X8;Bhz+pJW2ieE1ne!@jV>J4LTrQ4GUmVPk zW0h1gOkR$BMisPDG(km#1eXh_C&PeS%O>-1+d7B{2gM#B37;c7I;dayqi7W20}?Rc zPw7H+FRw3IzN?z6q8Ox<6wzk4rNYb5tgBL9vZY}`44|ou5^hNF2E=fd?$3eW zOTb{P!KvnYd1++%YH{X>%izdm-3Wqfn8{rd_{#oMS-l2TAZFA}6H zOyC20LP!x33_z*aXj5OaP$@`>>mHkWWYuF}wD^7r)=Z0o(6UQWm#8pktE$yOX)7v} z)l>-_YFajsAh{q~!rbjo)0MK=D$JLFe(;9J^jc{5VmbneCxq>&TR*x2>6XXv08g5a z;X${k-mzwXPrj>qjeum@SH!WL=TDWS!SKZgWkw>BR8vJYLjmr=OpIPabg=g8%*yQ^ z+zj0=go3REB#|U)+6SC|I86w%HVfzyVFC*N0)wn;@QuJapPKTwQZW4eQA`S*ZS8_Czm~nH$P7~L($Cfl6Q2Kz#U+nXWbrUbv)L>c1G*=}k z#04!KO?io?KPfd#Zi@oP94t^+6;>K!LL6JjPx{gDnXzu|^};r*+!cNi>BV1@VpkID$%RQ zp7AJ`5X352HAMBTOl?(AT%d+gNFU&IZHub&xXz!PBf~B+F zkW^a$LQs`DzuD=-Njj9HG#h;{XO1|BNeW~gDNe|rw0<->uT`?0PEf@29t&9vkA^8S zDU97oZKzCZ@0D|+k>A6aMQ__SSADxz*|t=sm2+l-uI+5;5>yb;C>m5-aYPM4K&E_J zNFsu3$gUZ==+5#^E$J#@BwL?@h5zXZZpiZN}ASZkLsE3ecngOQbibDm6AzK@y!n z#E#DDu$J{9(pP~@fDlCE;=t_KVkeDF>i$agf9g-uo*ReZvEbD4W*j--#c8Tqu92x# z&eoQnVl#(r?Go;g_bdk!w%~eKZ^$pg4RFaA=yyi)TE+X;8MT5~!_rq)x^=TMq-qO}r4UY@ zx|*_#tpeK7;R@EEms{AT+(L_M1auM%Pe~LNbayM`T}kLRZ1k0Y6A8>wt6S^bI>8O%24e!KVgl{8z(`xOjWA<$&VTBwNbQLQ?`pQC*2HpmOH|TSE@`tQckcA-# z?pz!m`_erf35eim*!n8!4Hv2}Ko}l8#a>GIaSSe|JB`rQd3&A-0Q)3N8Gs%KfxZ6# z%8N|IM|9$wk+7lEg|=!8xy=)wmhW~c=385Xp~3q%2l=ZIN8?)Abxw+WsrZ#-yjrbH zU(RW%M6I}c%p;bTVmv<3{hW;VAzCuG7$56ypZB;|zZ%4x^|ICaN#c?2kZWVQeB;zC z$LYT_bvvo}b_tX61r|%K%kovMqFi4enIm}c_`X>z`&y<#6__)38UcP}rdOM>ZQNV3 zha7cE0RI3*82Fbw00IxjvFkR=9eKx=>XMWZ;ed4>gq|CAA9ZWV(;6)8)Bc?198)j( zcdyI!G?;{IX(5&`El$a_B@9ltRvo+dJj^A&m&dj$E@LC_9c@b!3JL^H27o;KnRBOG zbABcV(B0L8M|2PvJs+R(hq+xs>Prs!-Er zJZ`pl4EVKtK7CW71%@b0ntqNr)lmQdB7g^v39bJCEozM^WwEyqkvN$?bJB6^qqVSw zK_DMV=jBHCBjFiiK45u&E9VKA;W1`vcxs_Z0w|8R^h~!Pkh|3^2-D%g)xG4~&eD|} z4$MXvbWIf9vNRGs)o-0iqssL#Q^QvfkubQ0H7s(1%Mzc^B&7lUBdU$6PM+S}2{7uE zW_Fo19T`l;5?oUjp~)G7JU0b)5Yo*XA{#QY8?jb$Z@w*0fI9MAwtOW3bx|9sD>7U=G0dw6+inD;Q5qGy=n)kXUO#j5b^TDRVj zY^|}F-uqhnuiOs{5qqCu;LUlcCORl2ZAr$lHax9gQqJep5vh&@P@~=#m4P6SW$)v_?apGGe-r9U zf8!_v?Az=W;>uIu81R5G>cWyaFRgiRH)GVDJLskrj`cSk#@VUqu>84(O*%;6Z}P=N zfg&#&f?C9dUwE5x1HIonR-6cHQ;O994+x$R45*HtbFJ(+lIy_#hHCMexAxfp=^QLSz6;){A zR#_PC_lBxXugLQM0Df;(FM1-v_l)cog3@=CVaTKQNSD8B5FrEZCu%`lG(f^iKmc(`!jBPep4>Xx z5}S4rq^&RbuH@iSg@->bTLefXHm(2^8K7FbtA3HPrd!LoyQH3;aeTpuU>FV^f*PFl zipaPOW`W%!siuvbJkiXgKFLWjvGTy!2PK@NJ>GO%oVO`;#+gwn(9$)(E5*Vb(lm+t zKpq@S!4*AZ8DV1FFE`V3aGCw21h*VK0Vu$1NFb;I1!~(&`1j&L>uah95$X0#&r}#5 z6^|&PtIOFl1E-Rj7&duLP6&W3A<&TR8(r;kY&bW|zMStfr6%(=R6=of?c%o-2?{cq z0s#R)9*CnG+~Jngmo#cyK2^=W(bcd-wi0?pf-k$Vtq#q?D=`~Nw z<2krJWppWZnJMC@SweYKip0dbv{u*v?a6mK>>G41tbZq&KXY>0l$SuaP+*0jQj&!w zCOlIZVJC%p!+NgP*ex{MC6ukbf(vW$5u|AVf=)Y0IMMOz7gFWx-=eJJL+h_MO`Og| zoK@D0E@YsodZ@Q7KvPh#jxp~rjA&g!xfdXc_cOD59n8IHTc>1g+<66{^~&71b4Vbs z_U{t7Py}B2w`Q z5EuJ3tHZF41b_&CcK43ud6SG=gsFEZ?tmgdQ6PoEBU00(X&Qu_CmOK$x`p^9`cLc4 z1|`t!xrz0^0;h@Nl8P)jz)F*UePx;$%*HY_2FecMeZX6V%DXS)<8cI}j_{`4DoGm- z0Y)%Ve$cIo*)=?}kJvtp*=b0G_iln&cUUB?3kX=!i~uSGD<8E{B*FAQ*AJ_jjH{pN zJr4S4if*4{Rdtmc^9?gpwjBe+qH1R_lJZ1~H+e)cTY{jDE3{6PFS%(8PfvEY%6353 zBpBcf)J=9QEl?A6bbHk#NhvRAYDr3ir6ou}OiRlE5}xx6O(LJu@8ZYQpGeT>oaNP+ z@ZOVGh>{$!g4ff*Bs5JRx+l$|KG;}aV=y3nkUMeoWw(zqw}>UYNbeocgC`PD07_B_ z!6bvkCTnf)je~b+Wt(*o-uEpn4xvGJ0(6wK-j$NI?RYl{D(`gYl>oD>9*_S341R~# zWt`X4ezvDnJjoF;+&Z$hb5@jLcbKU>xr9+lFSM(I2ebpihplaG0#?)MP$X(Y3<9MI z$4cc|V;{VOjHC)avdr_$;Vv?ZWHREAquwbF+a-mhq=wv6sqWr!X(~!fX;M(Jty0;V z5PI?Ws(u{#SEqOg<*ZX5n7-wg8LX?XkBc)qCn|*3h zMd}&B4TSj!nu$NEti<$h1{aj4k7HdUiZd8r^;cqm6!s&)Y2(7?_jn^~==0>(&FNS0 znzTNSdP&8)^U$2F*4Z-!W(!T2sp>XUnpmX~%LJ^F#LSKyfHl+$c07u6yRnieNe0UmfdKypM z*+1tG!i|beGPmLHiMTV>=Q_E|9mQIVs4cCmsNfAv{*Dn6`RpUxI!g zRiTE=dt)CM@WH$vZuuPPmFk=x+V3{{?aX<+-z?KG z5T}%p(1=f@jAN>-t7P$$&s7{O6DZ_dCW&Zh@Ek50b?q8q^yNjg>`?F`F5htKTZ<&^ zI@OQ9krt3PBzq}ch2Ys^4X9eIKL^7pY5};C3^tZG{{WEEFmG=D-YxGOa6*)$)KsJM zst`IUa50LhO`2A>a-ojfcxl_W6rs4;O=^mjO;*5e2E}}Q2gGp2w#cSRs#&frxsQK` z>-lkFQ8dY2BQr$aeH)`$w*o&d2e0iy(q@&i>>8vWT8UeiFsO6Q31z9vIE6kT8z{L5 z8)U;xMbv_Qmf;5FwpzJ1=VOUdJ$9$qM#_*K0oL)@Mn1SvF#LadKbLy#(r%Ob)LQ8% zaQwwZ4h@Ob!2ys{R#Pv`QdLOGZSQT8I~{$O=V?1IyHj~_Wg=9<^&}ID(C>v~r^2ud z>=P9Y*j;zaQ!9{1AMptu*n?DGLFv;4uft({XFg*1wHqk%g*8Mp=^_;c9UTE;g-(|} z^wVBS!#P+{(#jHe$Rv)UI%r?{P(~^yv&ZS9)9nB?mDCT5$q`-BSJqEZZZxr1a4gG|V4i ztNvjfRsYi^N|M1jX&S&1P0g>bwDYwMJ6|}9AzMFnKS2meaVr~ZsU&E855tE6Txgj} zlN9quIfR0}{g%F`;lsw9fknzoDT;GYU zubj)<3TbOXrwu9~0<0%&$QV$K){~e5%iubgg(YAuBoR1;0ya>sntH{adPkFUUOj>0 zpENM+UJR*&{Ms6*oB3@jwk=w!`m~bNFiq@8za@;feRDj$haB&eppulJFT^HgMC>Gi zvP=rbjqB`Zb$7ihP828II$r0F1~9lY(fCBM{VQYJD3eE#O?h`+_>|(b^WEi z>1d!SY8}!Nr6j3Hgaw5b(*;okNK6w^&Ck=#t5;=NMdQ}NAO%S)Dp|(@l7Rq3&Z8%V z5e~5a1UNQ(#ePPM2+6sUk>L53o@z<3nTR^9Zj|8Pc04R})ierLC+6m_!r{@-{Lv5kkEh7-1R91MZ7lxFLiAeJ%t52$V$MFQ9 z%-FSF1&&hVd4D?M)tHVyhe<;a^Nisqu9|9^W{R+-Ov<$I#w1xDH9L%G))O9c+0DZU zYTC&lTOtsakdRQ?5G1PzS=ORs9ZOMC)JCIIS7*Jn<+%`2-9RrS6W%RL3w29Z+cA5!^atqai8fR!bXNDD4;Qk!i` z8bHEHBN7HCVB}F^Rn*yHnufa&lNG3rFtS$78bJ%;S9WVM*DILAyfFGxkesZwQy4BSl+L!GFNsMrT(n*hm*5ui`{Ju5p=e@ zwV?F=2S^9IHRxur77y`R1Ybr zDZ&`IRk}ciSwPxODlza$C(ekUPeFzSrHwZ{qT4_uTe!Wu6ZG;|iV3Y!O&Tn_g=EIT zDI>0)s$5LXJhc%jDW~!k0gGWmT)BIezLvGTc|wsLe(I`8ld?VY_*Pt9Cdzdb8Rsfu z2KCdtEl#J)sAyu@AemJ^$*Q%yxi5b(TxvL8;|RD(Lcmf?f)2tC1RkO`(&VhC-CI9? z9bI$jPpUjeG65#53j?Lf>Dh{jw%ySWtoK;hCg+Rg#_H{JU#?)=?&34j^P8#o{B8Jbd~9F3Vb%L zOoFzqm^y>rIBzt7p9_K8$C3W{z8JC7{WSsX1xMjZvXm0}CxT@9;a2zP_oIgm>7HE7 z7>tOm6cN;HUly2|h&JtQz2?iDAX6#zH(@l(Ryt76GTO+7%dNyTNW%q^7 zz4_O^((_EkTf*uxr8++>(`is>m;)1v1_x*x4iypQcI~FsJ?KdaQiz^7^qM#ygfFEW zlZJjeIe!AmG>`m;C*d{Ox)f(JnsfZW<>8HHZAuyH0b7%CrOmI#_x}KWE;Am_%I?Zb z&)gx2h>(R9m1)=&r4VDMg(=Fc6K#H_B0x)I#NpzE`o!VJw_^3ZotLNHka~-lMO0K% zOM=y5@J%tYB-P+i#!t{>ztzqnUEHe8vg!ns;s;#eLoDgu>eYQ?OmRAlK%x)$A#?(- zqJEq+HZ4Vo#fsp0j~Iel38E4J&qq!2buta$0~FFp0(FqIn^ZkMTt18vg)yGU?Yfja?#Z zmv+r}M@jw?N3#mq7w~4w4~F_|%vr){S~HI3DZIHD{{WPZikd2Y2YW1=$Hd;;#r@z= za`kEkVJJ_O0;vB0daUB?`J$UODE|NxhC1K@@vC#-N~e0_%oR%>!=A5IKVj)FRKF80 zt>&`+Z7xf~@{UobU@j6xrk5D2LE&*FT88+Ic`oEB{FYejqyAzp4&EtYw6}*=r7F40 z+7o}zcdprhOj=tNE2CTPcu!f-g;j^={0kFKk!A{71v1Sh6_;u))`m9+Sgt9(LdJ23nbdWD@NN>q|S^T!(-u?SQy@_IqN+qm9OmASkt zB)amF&8jqM2s>SV3RDY(2uV;7F&rzK9h)}pb(UMPe+gpl;DMU1VAd+fofR5oB z#F-=al?nd<2_%mlM=`X2l0EwsY9PQ+kSD0%Po5oB(xvIoveI(~d!)FXOKrfFC?vr; zli~>{`UI$_VZ<7%T8x|OsxMb~u2}T(gGZOTe}v|2rCE#BHrSrBmId8aO;0&((nBm{ zyvt^@ZBPc|e4ZD%TC#*Wm^fUyTNep!J3ph zlr-T5EvVvDP-n%ohzDg=R&k?jPd&j;J(+}rlj2SOJj(ke_g3VNiuwB9TXTJzAqvFm zGJ58ZHc-NZ7<4fB1ss9z9@L_1t2?)scT6EYR1x+27&u-DQMSM;mhGsp?l>~t)_d0n zonyaixskB8TyPWR9Tl#>;vb*0R!{Ut)l5GKsA_04W*1F>NC&#I$%$9PPN-PuHmfl| z53iD@{;3UR-)^OYDd`X=4w;QH#%c%pR$=FJS00iZkXAS-peeu)k;HlR*3!Kc%Gqlp zB?Am=+aL4JN0{hpD_QJR5q2@hxGljW>E!v@iSKT62gmd+ znL!&B0ml>p*kGwLct{lyZ&QH|1N{cnPB1aqCx*|R6@IPang0MPXIdH_li+kY_JVXX zwOkm1plDd#c2q%E9`%qDs22mZ`I5Hn-8cj=WD|y<4jfNcL98Tb+c_$A?FXYyph3q1 zJ>b)3O3YnU%T+kmFPOS{Rahj3Um^@Lz6s`OqXYCIPSsVovq(+6cs0qpohSxXS8 z!7%!RLr0Y`^d3|Zz;Cv)qGwb7oIao;c~~Sgj>Al&UtUjV<hDIEEJVkc4cM6sl07CNX-t-c8LZbfe zzRpT5??s+&tr@F2Re%=^qz42IuBQOMF$RN=SzKBV@@Fvqg2~h5lZj8lmwhD8Savmu z;}~#5hF5(1FU!b*H!7kF!ptn|?AmYe;l}&qw-$kgvHMmK!)Xp6U?x;`C+aN$Ou4a18SNlP;uYDv@YJjYa}OA|CSDFTF?7Y^7^sSBvk zpO5VD=F3BkS3y-(M_a!IxAh(C&kyx8Pl?MmR;$FY>|-3Hd8(SZ=A%%pMMy>Cj+$1A zCRP?G1EA3JB=YU^7CBO^Qrx=*2~ZM}llK$X96D&3R;~xN1L2OGLGs&M20_#6$ZCZ6 z$fv{Pl#;7cQ50-_phiyPv|GbYK&Z0`8vyeo^`n8Iqb?9U$P`?<&Fd4>$EO@Ng1a$d zBNl8>?WKoIsIP8=dp^PwNj{hAJs%hxw%q9CXN8Y7|Eltt5+5VBD}wFSw%}2Xn$K-*Gcs zlF>_TNm6^q93=*zV~laxQWop)wqJiNl2D*v1&9jk9bR;r#&YdFE-G+X%E1hn zlr<5oU~OQk3IMC&`*{>MZ1YI(UY$XeAkNu1$*Ji#D0t~d^ns||6f|k;%PeQ4gJ@at z6qT4;%NU?)RXX;$jea`veB5Rf#i(XyOJYw@9|<)cZ*$4+NjMcaBhQbzuFn`k*rQW1 zuq?U{X!!D1I0>jRB55;_^6nThO3tUu%@tJyxWL>Gy3mDf$ivtQ-uxiXa`fC^Tf7Q_ z+i55O9}1GZNKoSk5Jf44{yV=_}>xb7v1D}uFkmD62+ zxE zSW7F8iX7w#Qmz}-{UOiJk$I+?D(uTmzD>5JEw~a`5SIM;i;lJ&SjU0$*;!PTX;mDb zN78>Po2oe0At-3*x^bC+ET-Y6SRe$yV_@FT6Yb<}yloY#*$4hUgY1**LZ%mi@-$cI zOVh;}ic2FZm0(zH4W+`K%co<>0V>3q;(hedG~p$6Iu`kh$+KxB8s!Ea;;=m_ zBZiV$@8zm$C6$!6^JfmA+}i2h#cVt1KQ2|`3Vmt`&QJM4BLjs3v~=-dxq)#JW^~&c z$J~C95xDy-JbVu!tjgUb&i9DIJouk36eP-T%VWFXWY1XW^Q5k0!|^PkkG2ssH-W72 zn_kx*=p=XB-rS5`3bb=fN=_r5u8Ngdc{fPZHtaP63!%sJO?-K02%~zMyiR!O;D$8) zBS^-|vG|hB*m28dp1)XOw91@NN7E@l%udDZ70gG=E{dm z8k-2Mpq`SphPJ9KLTR;Um{~lz0T)9UQZ+oi^}5&|G^sGMl}`nX44+IqsG7p%7c10- zrAbl}q-oip;t1)P;Yi|XmOpW>MZ30y6Q^Oo@qt2^nwLpfu}CSDG>;=%IMqodj+;{5 z&Hny)7^VuK)wcR&{628XtR_yWdaS4z1`A0Ul6*c#5X}m(R)%`w!0d(8?ocndY4j^; zffBK^hR;%ZDjvBdirYA^Y2VE z7C+NkOn)!Y8L2QD{LYoilBAPShr~>j{%m5-5u^VAblbMV$AERicaI@Q60ASIiI_V* zE2S3XA<~6lN?VEJ;l>Who)jH)I=dxgywyG_)JSm&u!W?Y$%oOo+lWYudTKhhMql(t zlm>8aZQs8VW;W}28e4#=+JA&`Bm3ytOD^r!;vu*Sk%`Ah;z#$uY@=h)4^TM=B`r=F zL54joSi-S-%IRxX7^zyZ7tdN67~l$a%*SA7CARGY$C1uulDl&X27F0K02zaUQS#e` z1T!qH+lVtGQa}J1jfF}lqiKvNq56ryIwP81m#W<*$DXqj%uHVp!7(Z+WvQT-%OX%~ zN!rSdWmF^Vi-JdC{!)vEl3IBH1YnhoiXLA-oeXlszL{<0Bn04J_%Ke%NEn|M z!_Ws=*+lmiNo56UYg)>b5;mU^!>A58?4%!EJyms=so36Pz_3hiN^F~s$V6CkM9f7z zNU0jQKKhAv?~wuc9YNvtUy-$GrD_1Uk&3#`-lH1@de0sTHc81+UyduhWv+E#d2mBoAY)pmg#W1C8xyeSzXndo}|kX1c8HXYH}4$ z+bPqwptbux;Vu+5l@%FC!-#{ouNrB~a@bKyW=;dsuiHp&uJwZh#l1pi?zT|SS0)o( zHB_nZL%hZz2@KX|+RtSU5%kwvk!~YzE?Bb`<~0Ptot~Y1r5qlnM+{lNmQ(lxkjT#Y|!(I)-ejgCy$8xNv7{o)ZUx@Fm#U@^#nR{ z*@lw?Y7ttnV)N5fxROy!jIQryG4JljQE`4jR+)pj^~kjW8dV^vLyp+eF@qE%8EaNx zxC)X-^hpK|2N@ei(Zpd?{{Ysmr+P-~4_C6Dee|PC9$0kBwY0eY2~`}__0UvDh{S1O zo)#>u3{KA+s!GV3f=-<2k6~6$ydmpQYvPmOJAfSPS(lT%TG*tzE$R8+^ z;!9XqYs~$%O_p5qh4l-NgsZztN-0auX_owC0+ba%Q8c}`j1xcc#DA_fM2IOdwzfpZ@jqW)m$C*>qx3Obi}h!xc(w&gQG-^?4IUz}PTPOc zYS5VK5}jkQkIRz4UNf|yCzzQQXOL!>i@ME)&R)}wm8}*9!qlr!b%4vLeGNX#l9h!7 z_ut(#jYJNT-B@oX?xnGlzB3DT1ZfYYqO>Fobh?!`rMBSGTP8z56iL97A^eXlOZb5L zdFtMFz~RaLRn2*OGsBoLx;BZ6MHL!J16K%%8>97t%eJI5OC`@DOnZx|ufTcm&rO7tdbPH~5=^D7tDhEV&hye@-gN}-giz^$u8 zZh(+hNz)Kcny5ch--&0hoS~kxmr0vA(@lrb;&|>CIwlQ7+|D8QNwxP2 z_u=kO*_#)+WsT+Q_e(cyCDH}REw98k0+d<5ExU6`H$>24oA92FSFPEX7f z)4EGhN=!9TQT)@#a9%l;qb+?ztFHk+ntLZo?5+|KHx{j}Aw|Tc`)3>O)*K-ursB~+ zrAkODQ&4fC!cx|Kb7`Df%xQHhkOH(gh00U`Fk5sH5`O8~Rk7;Z@R9Y!)ZbE_LC+mF z$+6Fb<2d#sU5C^@D@O@*nolt%*zOo>e|4?(b0T*?dKt;`#&Y|%F10osZCY3=Nl$p> z6suMspok)|^Lo2J%(G0%>&t%VrE3dGE`VkdaS?~3 zaM~m(#vWj$DpCTAZy`xg7}Srwc@nqfhHkCnzGSHjZAu9Mk_(6=;FTd@kO={4P$2A> zy)o#A;YkE)Q)RRx zP{63_DpX7)Vs_OP<{ZUcQ<3UAQyv*fS3yM5Y^aV9D#?g2RcY=^1ARkSY4me8?JZK} z$L9*ysY4W%crnI8b_3U3{!3fS7-b$=>1Jx`ZXpXd@{D?(lt51R zX)Ext=ca1^lC{yQMS6x*{j0iCS#{Ufd2qBL{WX~e@e3^2ZG1u zfm0PIiEHZCL};O}s~%^|$td?(g@V`}2shV@GN#KY?-j;BN>iU^X=y>U@Z{6);q8g^ zcch-F@~2Vy@r%KQ;5an$SIH!;?zL13O(@V3KS*v*U;!rFh`Urx{$-F|+U1B-k2>FW z0(R+F-bDWZd&6m%6koeJyA0nYcS;CAlP9Nu_SV|ovprz+m({AaoV66>jR#YBRpR^BQ%oP6sV>j~4TT6p&n62w%1FhiOvXv!L-|W;} zAuC^iDJMb!6Vo_1omsr|Z8Sh)XCe8k(XRkCuC{xXpWOYmXjemj3{=H?1rW;U~)zQwC}^ z+Yd?h(Y?qrAfRXz6=Y$c>;riGZ~1Tr+j5GB0wGml9-Od=DzY_YH1V)8Pa#ml_ZrqK zrlS47x0p4*)ohob zkS9oi^C4?hGA_bc-GdFb;8!=@^SxcudUTeGh+6f8q!^GwM3SM@Miom-Ps_Nn=AaBf z0~H>lPc>eudX?%6(bU~2>)aUs07CN)TE(HGdibEjt1$|^J~($lQ-sMAPfr~3{h1^` z9ux0XrekMmW0a=d8IyL!#~L6hwh)yhBr^B`3sG%KT82NhNkC8~1e-CEIL*rL zZPKKLrXg66NyO|T2-zUP+rqK_9G;ZA8PL9@<_}QV4_hlRX3i9F(p1uB4Chaa;&m`a zOUEsG)iHtzLl$V&6qxrBb8@^H?z`7J#D?0;Z*4NR*;9?FEVJA=uylpCmWT-~suSaQ zs#b)pEfSQh1@n|X2|;1k)rKlc%0cQQ8S;S~YW4EZSbZksY&{^L&l!JmlFd;*HAeEt z@2k7W(rV6iHnshn&rQs?+)c&+*u8G2u_gBw9k@|f+)IQ=)x;nnKi?plBp4M9ULtCuawdSIsSFn0@{1h^@24`4GTnU6%ez}Bl{&RD zoC!*n5T*BXvQ!da@gRzxa-59jP6mokh=7tmq@#rf{{V;v8r7XrmpKeS$iuN1@LG&I zaJycuDZ-DOb<=A!npo;Ux#mgk?%_X>?%Q_?B0;rrWBxb!r*sCv8+55AdJ3Ymn{|6F zUh_Cq6p2BHG5b_8Df0u}9B`rk0M+hg#50FSa$aqG8R?RzQ7YL@RFl#p%P;^Rvg!f9 zdvL=j?Cm)&bDCx0dRCLKN&f&_T;T+twM6RbI7LjmrMecEH@7x!xD-%H+4gB!NC&1t znu+*zQReK$l5@XFGNjPQ4mndkFGCc{Pw8qYZ&?gZHCAb3kb&CnFW-QU)GsYEZS}Cd zT1VxxizZ$Xu@^0pl?cEBms@csq$mt(KHn^zjm*wnebk=lxQBsBz;}ct$s06>QXJ_4 z!y72c`f&96v*0zDmJr6D6v$6m6B8LpC%`et9q`(VllJiZQ62~OD}n6chiMtF^Bk|a zIF=NYp)mq@np4=26<0J%lwi|KEQQsN}yd!=g_@rKtO zU{)>K-ZcK3hOk5Lg@o`zZreK2ICySbQcsXIOkatfQIjM3t?AZkfjqiuT*Ev8z_p^P zbgGD4Xf$Rb{{WXU3v{lMr!Lq?Ae13}M;IRCK2;3wlLecm*TQ}{{A$E<*Hk?ZK5ohN zUZJJTl{v>MQ@#}j2Z7RgvCk4#n#eIWsgZwJfEqBLUOGsCW5(GnJ&v zZ&4U{D(MVWYD)$ZQp+VY$Sq=9-4_IDalv?ax2K*oGia2@M;c7k^!BZy$9$NKh^1y# z14WI;+D850MXo$8?c;s;RQ1wDTK(SN-Ave34jUB<)6lU{k(Y$(#2bL!``y0d%>_uJ zvXK~3&dbtZ^5RtjoJ}GCS{D|c2->IKiQV=qBA(&J$+I5|0dJ>;sk#jvwHhgaXp!QW#5uPz)z#pOBU8~d zX(YQ2&Dxe{Vn9_@8nNyL#+;LEZUe}jfNduM?KBL#T3c4%Z36kbJoK`s5~`=p8Rco_ zhLzPI!4gbDYpM4^ii9}*At6ro1YY+X2Il$Qm6E?~@EklQdht6pbecfsVBMgVl!^Y4 z2^%_91KBh`!^Tgf`RS#c1tylRTAlSs>={{E5qJCQ zpfa0*Z}+z_yi7FkFoH^0Lf5H8jVV3fc1EE-B`kp$jV5R(Ykit$DsS?(=?HNpVb@kx zfwN0aA)N)c2$?EUl9+-@yfmulzfXS+45ie(k&k+M=oWMJ6`N+m>S?iBZ097i(#=>< zG;fDVSH3OL6=K$k%NY&aXa~7*#S#EXR3v`YX;D(lNG-NCC<7pBom2LR)j^w#n&6Zt zG`DH46>DB?2`W2A6eVR5? z*TF>_<9HjjU5s;?Sy$yKQhl;8P0~ec?n|C5SyB`CskX<2q-kk7)!{LyhY1sgou_89 zAU~Gn`8}&&5m zYIw=oLfjAlA98~FM!YoC=lrL5ZlBUqZDa~{72@(lb< zdRf47mP4idIkFZlkSk}Xj||LtgB!qBdO4~p<5Z9Nbk)1JPP6W9$7v{Z0FGv-Vfj^_ z_h$EY*^(8Zn|}3{%gHNrrDIZ*gh_1)Ngfcd6ylV|ETY+YNI_lNp15)Yh$=$R*Z0lB zP@omEBS-*$6p~)B&VqVNxEcyt4fGK*YC~23^6T5rXeZT{>>2blL_hc+7H?A%96_pO8 zlY%7SqzpJ3O7og=L<}hOb-O5agRh=}F&xi6Gd%f+r?r??U}>V;Lr;j|H6Nr&L+By5av!=17y z4)k}3;L+CgE2o&XWllSV=PWi>t%nVOx(Qw~_mZZ4pv<>7U=6$6@<+_GHC%U3Bm|b# zC@bN>z)sM5I;c08WGGMuNh1RsLD`Auk9`2$8}zZ#?z{BwsNFrw)S^7cgGMC6C@Ca0 z)q1E7c5bw*WD}}F z;#C00M;fSXPIdB&Bf$3mAoem|(%i zwm<5July6!$Ec&7eGmG0qre($B9>`?nAF6WMRXX9G2#NY8gj~lYrA{Nb|p>q=gJdT z_StHb&|$XRwsG5K1+8unS#Y-jA_$O>LeGe#fN-qTyX^kz{Kdt=QY8Wr35sP5|k2wDI`!CojoCS12a`kjQWh~r1YrqlRQ|aF$Nt26}u8>sNPvY z0NVE&XnZ&yMo#s&_hmBPGD6+&RjBcSsuj{sGgG>3ZGyw7XlhDA5~MQQL?j3a3(^!4 z1^`aXC=pWZSz4fMEOevLSDaKl>`_D8eChE-R@&;X4q{>LqPaS*6>=j98wB?-x1(395AaOwRGWa3)bvv4SP5s9jY$MY9T@W-yA#IQ=~Ygv4hXt5~dja+D1z*1Rn;c@ivw$k41%_>WX z(X@iu1df5wX(P*JGBlal_W~(NMT}&);!oySRv|P#N{ftMCijX3EUG|YrL_zDqd|Le z&o=u0#h@AD+1Wpa)5eQsBWOO_7&=jabYD5OW*?hzX3E3e6vj$=it#kT!uc-LcX+Hd z3{P~n4zzu`%aq;$rIB^Jc*8d5VnX)07t zEK-uh09dFhNEfpJZ`+M!d9ttk7?og1DM%yIarC1%EW=pv^CoLxufg{npz1fE>~A8~ z0X=R)$6BI07H3*|z#F;LgYod-3w}_y5aM9qQ0j2%(zuSa$@8e##hv;{`YXVpeNbU7@Hui9}>xdMTh@o==q!g*;5DNHP z+w30BL|5m%RGKkCiWe|<5eO-zi2JJV6vjuvhRIA)RT}MPBSyc& z==wZ)U@0*)(TFDK3W00)98T+cgj0xI8m`||xeAjW!m8;fU-Wv&Wr9Q7NmQvMd@soH zZT>~{x{awRQ1h9oF3o-8aA=`rY?n8v-@;3&-khr;X|b$|8xx?1M{hR{b2tTCz^X9% z8=Y+I()G37B20(1Hmq;~!Qnn(Q5|&zW;(1df`Gw#PoMCS@U2mLQ_;StP+?A)dp2QG zU=qISVdc#<@kZy&L@^r($}X&={Cg41ueo)-f3!i>#t0bf$F8Kbw6m~?p*j6J<~&)& zMrP_QV^c_OO&uLQGVLbKs|Ie~KSAT^yGjHlwED@bi(+=D`cpk;rrwao&n7idienCJ zx2(k^AQNwNMGnA4t=tQfuWl(t>&YG+De_48nX4Og4YGXAK>q+UJpuV|mHw^JZTXG6 z?JezVZSy?OGt9P~?c-~6-D3!*e z6H2;FK}iLc=f~I&hv&z`lSB?PK>lj<&(VIMW~z+mnyD(Pt1DY|Vj8y*R4(0~Td34V zKmdg!O)fj|F>#f#a-}I?`2Os0I7EKxk?c3$Gs)OZvkF2`kFe+xgEJuURO2Rb#)?I6 z;W^N(My|HDlB%L-nv$$R1jrJeD#>2(&O{>d(^DmsLYlq3_t%hH{hL`CAyYE|hyat- zunm9@Q&}Nv+wNwRr3JBqlc`8iDkuXH;*eIeiCVB9!Z5DszY09@m9gv&9+2mH{JVug zRZmr4h{szp;uACx2KksNA}dcE!cbD3Ng)t|?sep8f7!DO2}49C6m_p^l$h8Oa0YgJ z&19BC^%I!bg}g(FQ2@5uRR~IffvHoeLry9u5^w+tf9Zcne-J*Kbjvm6?x^MrMtq-x zPbMQrfJA9A8ti^^C(J=cClPL^f=ZCDR^Z-2by4CYHEs){*{&n9(xknd$!6z1HN%(W(WfuB%XmsyQ%*G z@Sq$oFLdJ#lDDP!{sGin--T64gJE>FR9Kmyb%Z>)omxgg6x2w3$pZrAfQ+u#Wj%e1>(+rI9hC}e3>!BjQg zsOd^u)R3hW8PkVeAWbZKSNQ(=4#hHt5l@-=gw!~mC4|;ge?84uRbCdDg?&1C5J?3T z2`Bn2)9z+s$e;j`?|bdTw|8rL@*7_9`xoDN-u1%jR)@x*3R+5ZEhR`vI(02DNYxM| z%j{<1YEwznrJ*NUh}06e1t~fTfiPuTAZ-Fg98R6*zJmIZpuw?@u;=Wfn6u6W973hC z#x-4q#Y00YEXXS9W~)hKGRQ&wDAv{(~RSZ<9WuT9?tls9dvl6Az2<= zqiBN|=wXL(i7&j!%MuwK{nYos`dr9&l{wYQ?n=;7R#~@cXI_+~C}5Z>1G`E}Lzo2; zqOC-VS7x-`xT}YXTm-MW1SL?ErbtPH{31`DHKhkp`hfW7QgbFg94F1ohFQB!m=I zEN|j1pf~+}yc&{XD}RzZILuHnne#l06tKd|t74!gp6S%sdj|uLLPbedRv?g1zn!!O zW07Ksfkm9_<1yj&a@0XfDO)VhP87-zdn4ST&$QT^@EGaCR}5pWKYleWTc9O<%4bjk zM05ob20bPWM+&k(!FMH6Tl79~&+)e0fH zo|z-nq&{!yT>#Nz7w^myxnW9DO3o+7tO+;?NHH;wi=qWfR_&=r!jeGS0*?+|0~$TF01Fz<6gpr|$~1XSjbo!lwwAx=!JWEvq)^p_z@biD zTMNsWO;%yXq!CeJ&`niP=d#5L86-bagT=tcJrsYeG?Jxk0#BwjSl*&D9yQZn!yh!~ z{6ZK0uxE;FXE4-86-#`^Fnp>tD*6!=GeEXIw&*X#7P7-DbB=`{Rl*0T3j8WD%!m0C zXja$V3RkyQK7b0-Z}BMT$58NL(~JiVi{~ivjsu2KH5D{7PgZO3qa|Vjks}2kDH1i< zgQ!pmy|S*+wAtFSB_KA0q>1qrxKypp zp=Sxmys-2q=-_`GgFjP5|(9(8`$h$duTcfeO&i?(qsZ8;%UGfRtn*>%CGmNeI~+k zx1yYb>O<3>Wy|;%S9)6}BZ$ybR$^4q972$>{$rQ1aPF-#R6-aVf-brQka&%wq)JJHLwkFbSvr-2;lMx=afu^=6M+Y6Nvj3RUaWmPb-$%K zcdc1hGT}HL8JN?~lMJrKsbj6fD&kct`XuLLCbXT1MhCe zDR&YD$kEQD$LZvbhJsTiN&f&$nE22!dYxB=3y<*?KMF0~QuQ(ELpNqjGY*HT8Fgda z%;hmin*M8~KnoH#Y`GTGkmmNc7l~>c`RE8!F(qS5C!5~FjmT3Z93uq6IAG%H$ViSaes1AW5 zdMhXLT;|QicTGByNWm~c@Qh|a8!zRRC=F z^;X26@Sn`z(|XUu$F6jhn6we&beVGn%NPwC1LjrJ;lws2BrR(nC&)s=_p@KH<}Y@` zsg2#r(o+G~ZXP)Q02_l+L~-yH8S0^4SnyTDs0UyIIzoIW*hjvu3-NvRH|f71<*c{R zPPtIx*!(z*pVkV@Hw3JTo^^(ka#A%*$O$pYF7{Lw+*0R3&S|}5_Fy}wDBW1wxKedN1J0$L$P4x^<(F~A8kw-eP9MGLN8sVIFV`rh>Afb{Vy@Sd3EY>`VP zZV=MDs?laSc2v|(0Rl;>Q6rOi>{ZD7M}o|*$)wm}G9n6$o|q@3<1`Jq%uZjJG?d`l z5R{R(?~(cDvXLjQyN0j2LxzTsJK4P6SRW00n$ZJ zk2o1ZmUaY_>;|+`&9zci)>Y%D?Nv=Q<6qs9Mw3sV9%bQ7Bqyj3b#le0d&L!Wl6|C_ z+dJ^%q^8N>GI{Zk3szN2Fng#VE1_0f*zF*ja}h6IO70zUXH$za z!X^M7KvzO{MX_y`v!+3)$o%R#5@haLHVy~URGV=qI<{j{U?E#E z@~%J1>9H#6Z=2l99E!mMSxN9N2in`*1Euxmi0R>4iK?aiJ}_gQa{mBPdj9}3T{?r* z9NCJ~wTLE;3d4s{opra9PA%}{w|e*Gtu1ZN(7!Uf7CP7U-LRR7PL*zhhB*fT=mr?fZV{!$FzMKwZ*PoHR zY2rZAuw?8VXUe60{{YFAo@6(6cIk0SQzt@E_pNCmNdin_pg!XfGlgk6lszSyu z5vrHd(_y)LJy6$HVcBmD!f9Zr!?MLRsy=5J#ic9q^I}pZ#BnzBxcQDsr#nw~yt!BQ zcnrf+mg-1b%36w7a-e)Iwm#&be-eZUz+!8UJFS|!(k-&)8hLj?~gTJ`BX-d;? zZc3ILwP1p$A0#0tL4p)XtH$)J(wwJ?dP>Z=e@7l1)z*sK$y0`A3{qJZs;-u%mlX2q zYov72n8;MQa21<*D|Ap72=}8lb)4CwcP!YYkhWU@r7B9Al%NCm#Kd9*V~NH?vfWf? znFId-mS8`d+&bTcc$H|vodpYRLVJ`QGG3iZB}Y+8d^fv=Wt?u88n4AM++pjYt@&+~ zs|qA=`EaU8p~t-H@&87+mtB@N)e=|RH{iTl1MSI5FlaEHQ2ihlI5F+pSihH zsdu}Ev?VETLupEYSKOqnVN1tmsHJxnP#kB09>WF6$Hk@Dq zk4fjMk~xbP!*LX^%T!fu9b`1=J8bRc$XQf|>_KH9@ZQ~}H>Jf1NhErRC){WOoZhu` zmu%Z`rPQ_-WBMv3DKoHwK?bXWe3^{mT|^Sp)3rg3{?aAxJ~kZ51m7X6Xa*;w*A?E~ zd#l{%QqWhV?Mil!LGhz`f?!yRr<9OA&UUylYu6#kM?hi_?Y~(|lyX zMTcix@0GB)t6j?onv_&kRXePAV3Cc5fEPbUBt7YMyO%9n3W8Qik+C2cS4k7mO8%Ja zUCLXzb!n0U-~tIM5SSRo#c`^-sq1%NYvNq7lCykxRvSwDK6;-Af;!2JYvu1}a^qWR zr^M^RtNqZ+^C73WVn3!>Mzj8RJ$0ED_vYDU#g!Ek_LZFj$VT3|+e7YL#B<#h99Whm znDIPk6Q>HlKZsP5HPLqnkVmyrA$tQ#9FL7)S^F)<_}tLfef63HpM zlckYG{iB5sI#5uA;#5?xLC2y86T+4$vi7wZIzkdK#HfrC2Hi)1+d;>qAI45xt?HEY zBhyw`sn1wlY>)ihMKZ-tEQ#(K*rh5`4=Gn`NOW)%0M@w1p3ri3@00n|Eht)26RltC zqk;@$3H}9QaUwL~S(msB-tN<7E&&QMS=*puqc@zw61WK#t_W);+gof^C5c0C$G72%x4W4bpa zgV>8{;yEGM?wa$)oOK2YG=zx3TyX2FTV93~0ok^E=o`ep5sycGF~`mmn6tGcttnS9 z(ubMicGQB3E)q`S{yzdZ+1yOQ^pX$~K>j5GBZVEinYAMvCxAY+9~k^Y{Ws+7R}tyP zZJ@>RJbsp@TA3;7aN_X(okY=YsCQ8t2*|q+c~5)uATtfwzP7(EH1Bp2+fA4=AuXnL zB=}S(fvAq&^$y#Ft-V^5wF$#&j1YE%9TYM2f7iWcHJ)Y38FwpIR6`{-9MlxJy;ypX z^B{Icl9&9V?I11t9^_w+Il6W^(FMcYIs8g&4((lKAHb>FMiE+O_U_mewnK@;fTDFI z4gp`pIswE{tMviuzo^+mB4xVnjn?6~HZ6%wTDXln;psJ18q-3~@v={Hj2md)K@I!2 zQw5E&z_T6lrbosqzbpmQQx$!x8_9nw#nsGn)5ZR_V$Ah@XW zq028|{-E;)BL*>s<~pC5r9%u-JNc5YpYJ%{;OfD3C)hZC)?I9agD3#)*ajO70bjdH z1nMN?8%gpLN3+w%;gw0&Ji&u!PggiV%-BW?O3>ku&sfpKk%>I`<7i@4c@Laf%Wv9E zuX|g7jMq6%SlX@Z6kAe{iAW?7ftWaqc65r6w_hN;&0b5lAd7I50FaWSz)10F+pvk^ zYT_vRCF$#@lr&f-4V3WeRH>8YX`-j3k9#pjVlUpo6^jyWVXraz@SBv7@|<3+vbB;= zPu+p*!VenA@sefsB|2F^B*I}LNrFy0b^=a2DzAFW_sIdCgj|P#9u+JEsaj{kR04@n1MV@ZI!!0CcQVRf zSwceC1e74ER0M1jvmJ?(!mBsYUq||xnRC`@#rly=O9cp8cyNk}X`QCsMOr2=P?7-3 z%-$pdeS?#IwUb#(V)R+!z3Y7u|AzcJ)>#KUJ zf@-X7&c?gS4{wOM`gvuIDLz!=SkXJA^=FW` zsRJs>7_?t_jYNrpPvOz?q<>fO`s^1s#PlQI@&~x8MudNd+iv5-kk0UC4%jILt*2;- z=dY@yi(r+wQm%=kG3lE=xa`sbQz(M!RTAc`F1D;2Gr;v9Dg*GWlczmOz_X?;NhM@h9w|>>EOe7J6S~6Sl!jmrmd4sQ zYv^=5QNC&F}tun;P(@N6EtFyfJ5 z_#`q^RZi-$pto{tq@KWB^A!NrU`*FUoNzLdrI-V4T31T?X^?#vz*8$gB567 zi_^(NOs=uL zJPhO_%*$xwSjo5-_d&5d6y?vQ`_>E4hQiZ4NKE2L>geH8e(%|gscBFpO4OZ1;0fyX z;&{be-$=6VeZ{>^Rbd?{!6eL>_}N7=WBi9*Pq3=cE3!^$(_X zT~g_PLh}V?4+VPR%NWdfaH(nDGQwEtZFZ-OXk0dyHwMIjmEEQNqrrzj3L{X#06@cO zT||!dqnBIGr^yK*6$VwL5(xm~s#F0pq>hpa0*U8TC~=;f=L|z2XP$`W8eCrtshXOi zBahHLd*B;n2_opozq&_z-{Hs8XL^tfU`7}u`@*7!_Pf~K+7jbRB`Oj;AQ(L$nFpxS z4+h2Y+)>sXxzPN2s-j>-dokKDHm|yMxUttzd!KI>qT28bL60QRDQqS&fe%_&5Qv8rp503=@a1+=-{Yj)#lYU}zZ&J+04f7;gLX^xyKK46Y~2^C?Si6_|EHVKaylb$>?;K{#;Rg(LE>K)T7)T-i2E$=x23s}Z1~ zsKh1{W~wz&1VP!{NV2frL~Io`K0fb$5$748$k_bN+JkKcB|6kll*+J3lBks&5;l_w z5=azlljbew?-niA3V@PS2uQ>L2>`)SASQ6eNdOWfV!o1nM@^ivPfzJOPlLr@)NH-| zY0K?bo~TwCu>Sy;dXV)JEW03_#)oVybtc#EVhjBB8Dmd7aj5}^65EsAh*G}Xb;go0 z8j4lJOsOD|vzadZj^ZHdf}&Fe1{4ShD%wDlg(qp$08th3gLMlLG=ifR$oN((Gs+Pq zs>cjyvJ347DCOI<9?V$Z!16^IP2JQf5CPfZKzJUM6T@@-^VGH@E*^%xDjo=$vX{w;P!@EEv)EV*4aVo`Jlpwu?0x!i92AuRCN_d# z&rUQs!};5%sfU{+|A8&R3GJ0?LxPK$}B~281d~goi>D5H#DU zw=gHRw^ws`+lxp_yQb5D+7j3jcmhb^X!6Ozw^pOaO15-?vWI_Pc%B)7dN9vl>PIhif2Y|duP)$q*ezxrxV2nLi;2%l(7(#XBL0p~k%)nQ z`r7B2x7a@KT<(jH+g#iSyUlAt5=jjV3bx}aQIo@>uw&{*>AcS=Y1WY%9&b{N0%uSI z4vLwX>F54pl+-Z>)RDKiw!4MDdis()JM*KdB<-#!T!=6zU+M3uA5xtk!wy>MZgB#dlZZrhW7{El-y(aN(&m34D&g*ZUg;44Cw2F+!)BV2T< zOkp%Q%J;W3$(jsW+${*igz5z;ow`8>OzpxtX}<~0y==z1n@QA)+{ug5<|?Ua{Me$7MEFt)?nM07Yet1#Og)E?i7Tzq@8-?p6n)kCheDf1Ya3o&zT-)phtMZLT9!}*g|7K|2JX4#}6Bm@?afJjev zFic3}wsypuZpQDtytR3S+of);_cctNWU2!798?qrphyIQFsNAXP5PhIiaLD3p0Vst zF+K@H3}}@#GE3!AhQG_fER1#}W4a3sy7+S(tuwnUm1=2*P|tj_qM`h5e@T3C*fCfJB-K&9d%BY(f|r1=|@6II|oHL;P_HtIXXAWxyu#6DgJRQ4h2bHTB-AauN`jH zD-f1D0wnugwYcGH%rlwYlXYs-swmK2QW8#x{^od*j1D7#0*Y69{$9uVJ;Km61$Sv$ zfY<#o7y>rW8eC-lrRS*k?YeERTSdr0@Rv}MQNj>F1qtd&1I~|8n!RlC ze%Zw^R59+>p*?Do;yr4by#D}7KArOAZ=_sPH}$Zb&z&;{7l>BAC5;&|I@n{DHW4f{ z)fX`$00>z2i~M=W-R{oWw9PIYuvg{M!AEw>K&E@Or&^Rjk`zhBWWY7hJclngd1?*c z?N;JcqPGsRH3I-l#0bDfHLXq;kt!j^tMKZmS}&IyG(uUKl;3^+*5mp2@aNDTS9&ik z+jv0MkglQBJgbm7ntO*7f^h_jt1hZ#JSvMk*5#QiYDOuUaI8-Zpjuj&jZ&tHl4`W5 zWDRF1R48p3Z*D>x{c?Xh`z<9cmRxp3z$7P0JtPogqPo%91-gbr&wC)Oyq5S#lAxj0 zfyRt?s4S>+AK^WhdVzw+vJ-`68tQFcMM-i|9U zJUwJ24M>m5V9cV!RnQOH!8=J_l$9Jv7>>WvjV;sQ2czU@lzLmpxtpw*G#xU`^t&<_ zO!4eoDhU8gYY-KWJv42%K}|vkB~8OUzK%n7Hmke|O8)@4wob{FDo!3=u?9ArG8Zs? zHYBaT?yjVNn3xhrS?6U~*Qvsgdame>Y}5=^mlwiiYifMz63Q%p){nPy%#z;pmxB%; z;zmBnq067Ovj?ajg&O>Y0FJewlEJ;xua3Q~-|zak0cko>jYX;$(5353q5U`OFQmBh zHha(i0MuIioq=XKa0QbQ6cFOo;H>fC=3g-+l0mUVNfzk=eaZ+MPDXAvd}bx?{*kDIHOks3mYQ3XX!Q!G^; z=H!u36$Zet)ZrdkzM0lfo8}g|J+@w}2QDrw!>_XK(&EuhH>|ebc7&nTlPO!|FG^03 zK&-Ou7kzS#&Ak3l&6AEjXtXKEm2~0*tI`UPrrQJdV3LxZMB#~@l#%$QdN9sEhu5jP zew*d&^NZtnT$HqU#vM~th*mSSFEee9t`ksWZIVXH)&M%|VR8mH?#_L8yLZWP)H37N z?l$9V4S?IA1h|E0J|u-~Q)*EuP*Qaf3NvO+Wn0JHMR2l;sfG!EB*vN=v!|L#tf46yAdc1gRh-B}A(jr#J6-n%z~Z z!JBr{3s&kEO9jQ1I5n(>)>PR^Aha}~6acAFCk9VhKZc*9zeW8-=~gt@#x0q0)-jqW z@Eps5&nZV}@hEEMqiSlJNYZ8U{Hr>q=6#^wQ+%}gckQ3^S(EC_e<|AEr)vHIzPjc&OP(qNBknmbuQqq&+3rhSt zQVL=qi|*@|al~+M!(*o1V9V4s(bMEiPX>y=4wfM$W8sigJ`r0-G)_k8TAbK|Lv8`I zVa)8@+l|!DZ!-JKlF76W-7#w7wSHZzmy+SPa!4gDA>=1Qh|&Q}_;IXF$g)ezT;}5} zDsS@+G@ykA%Sv-daRe*~g>42j$;S$rKUC-H3mb{Im9e!h4jwn4MO65f%AmJJ`gCnM^_on%42lT;<;jM_8st7X1X~KY-BnNF4WKWf+HD|bi zYvTiUyIMdy9$-Idce#fAS1awzAS>Bg#t(>w^ml`Q~gTy?);TX3~GYhCYO>$F9SA#s?yShXb5h?F*qnV{@@W0F0TZDL$meg<&GSZBmrHJW) zSSMqg6j?mTSBbT2KrtFhlIV^ymm4Gf)YiD)jo(fxa^_aTvn$5Jr!M1E3o4s}WT32S zNiEoak|4GG4{l>->1nmUQ)-Px3uwnmBocheV01-Id-9QYZq?c`N{UoGlmdscNTQvU zsVniXUX>JCZad3gf??IBBI9snCN?oz`$->ZdMh7E;6xV-Iw?OOUefGQ(ZumPIRt#1$o#r68QTJ_i~I!+WJ&N6Sx zyifrGFrGC~KDl~llk&G;a6A_Tg{h#OXT?-#!TxG*(?$>-*E1<&?7fFA`LeW$;e`{l zjW7=iE;z;;S5Jy!*d`H6JdCmI9#kcaZ?G^7Bi(M^&i(Df7F@zf6shHDo&&A`pzU%_ zACoDXuQ8-lby$>XBvdsrr_MO3aS}-d9A)ZQ$sp5e8-1$_^2^O_?f&(odh~6mnf>F- zt##{tv8Pt4P{5>0f#3)obZ)&n`Z@J=*L=5z<^GfOiyg*|eP$l7Pa?i z4Irs1aHm*rz5e1B6XH@!sUbL;Ix_wpoko){U|654zP0q%q1a_*HYpKmINKM+DRCMP z(MwH;HEhWgS18wL(^eY*yD2d{yUdVusl*_iQj`Tc-~hywAWw+>u%jbnnTXY$>dp6y zyEe9pX}1*M?;j-v1-v2F(hA!yAGE1uAwD8;N>#_FKAgV{9AZj5D+9{?RrM>1V>x=N zDwj063t~lZ=G5soxIL z77om0NdfQ4+`6Q%GQMqt1UlOq1FgDt6sQMFhyWN$(voLVj7kNVbZe!aw;C)qi_%Z0 z{+o1Sn>ytt!&Y2WLp44#6*7lY-9 z{mN3_Dzqy>0nlr05Vz$n-Obpr_L zWo&sj75qefWY@&7m<-KbvNNbxNS;P zV5#kkP)J?Ifd8|G`++qml#O_ryB&p zY!2=8DhPlUu%!rIq{SP_;{0E8Pf9Ur484G5PK9M|nB!@P1=z2R;R1H^p-5_~*hf7i zFiyn2&(cSD#_~4tRkgLs5R#=ip&>w}2ulgntO|*A_r4HtAzfswfB_1QQJ3mA){Z_~ zQe4*HKbUE1#VG}PE(ug&g2+h#N@9z*R{9_5uMf@{&Y#zJtSXG>j@99G*o`;!cNM6s zqQq;!rS^oNXRn&0Ge zt$iLjO&k=nRFam&DQc=jvJ{R*WM?1;R{#ZJ#Ykx83hwlm3X>WgbgU4Zbp$jB5r~37 z7;H2by|@e{s{ZW-DO4%6sZXf86M`5Cbs-{3P(ddWKq6>A^?OP9nRUzX-l@X#=2pu2 zd!)E^Q`S?_(l48gMAUUMOey^79a(-|!$t{R#aC-zxy*jVow?o3;;)0?I!jh5UE08Nx z>_-ZsYK5taC3TeqiluL-_=!6AvC~`H{Q4TWNd_uZLMU(O{P>jv)ZzGWu4@iuOtqLc z)k$kwzNBtuk8M&|#;T0LwgN`&ITv4Li@dmCwoip}b|o-G9C}XAB5Eq$6fKpu>NbS| z(r_T`=!vS~PMhaS9E*l$+{cMkz?GFXSTs21Cs`E}MKvvtk|^o^)z!BJVYrJBY)Ihe zF1QV-AtF?qNsYoY)IP@KqHFO8pW=QE*sCs-4JhfDmmH2yMwea9n z2}TmCN^wmkP^p(}<)kXIg|Q06*xX-*cU!LQ^q>TV5)?b%5Wvsd?((4KZ*-Jecde>) zW8g6&Ab@z`@9UwH2Fh6ntT^^NoiOj5!s=#>hJ~sPO=2aruBcfoUFAP+*C92v_&Typ z##E5gx(EgmQZ%HFh}e=2z%c8qG0bmUyjgLbc!^%4CsD(0(j#f(O$h@x}MFI7rLi$OI=Q>#z%cY{Mh4u|Jkv>Hu^9!EWC%uWjyerHDmkelG zhXL^|PNg7@jUyj#r9P&e7Qr_+J<8BEIJ;K#raH^Iw5B$aMmX%N9qBKrpTu*j*&h(} z$(f~79DA)A88~6g{378 zs1h&=RO{92v!Sn&sxbUlHc@5lwVE>Nd?PU7lvH(em6KG{KHrd}xwZIoPCr$$MYm29WXtb>{Az^7a^|pLop!rdQ z4WT3`C{IKmj>( zt?zKdoJb6fHqk zXq^wZ<|zwa;iEfr9?oF#No=Ex{f*#29uLYRmDWgg;7$=Z>IkM z9vf+qNRAaEEzZM#aogEz@mdi{lwzjGQ04vbEJx??;)tZA)?_SA%UtS3`yZ>838qP| zs$~p@Hn-RPyiilZsWe(?^m8At8Tpa*r7PrTlv)Rqo4JjuS;kF@3#V4Tp?BPHS_F+Mg z=)j=K{{R%>@q=2idc*Yh)?Z8>we#Oh`b&n-i(%MiDN{*25X!5%10blNk;~X1dTCVw z{{U3l-0EIthMyt$gt(NrlONOju>SxU7~w}5P1>)mn{^^dOelYRoDCx}if>ZYFodJP zuzC+L3;gaVWMOOQB7`3iuB2(g^xHBvl6-_w(Nm{@9<+*^BKm>F^u)8C2ZVWn_az=5 zB+X?ToEc=WHXh%j!-p+~)3H9)z+IB%pGLPnM#p*V7aP`8GugJldd+^G0efpjbMSj*wkroOB3{Q zPFdO>b7biT`9-_}QlJiz#!9tMx+)C4+}xiq{_ASVJWhZ;d@)NL6V#8ZER&Wf<;=N` zO3X>4^D0uZlAd%{y}~O52I@36J@3g0j@ff|Tsl%3i#&|w!+(16VgPF!l8V_u)Ou3?n-6fCFv)~ zC{+BV>qpY|ZN#L)aJ<=16-;;E9Yj+^$zx_Oxh$gkT%Jny`{k9~iACE!tI~ZnMMSs# zm2VY_bt=up0sRdt_!&ORHF+yLbhkE6g9yy{O+wsQC42;*g^PyzG~n4c=y^JtS{4q? z3rfG=Ni`8GcP}m1rsbDg{{S7eC*DMR=-K5QiyW|tXtq>_A8A-PI^1ff^5F%|%E#OY z^fWokvc{8wNGHrv#$2a7V5F(#pJDEPKL9uxRn*Y=79lj6#A%Hy5gQOjm+fze=7ZBu zn^cMkb1ii1Er|1;$7w1a-&1)101g~Bty^fN#=9RI6BG{SZh-W^7{PJuGZL1frSnEB4l9jR z%O?7Y_KCNxB-I~mQv+{tNYHyt_)hNWSv=E?C@Deb1Fn)mQp!w(Ngfmqgv5Hy4{bNk zFlpAD5Ics8Or!`)day18>@FO9MsYL3FE2~*T;u8c=jQ1)YQ?bm@hRBPB|axt6MVFq zH6nhN$pR<4w0*AZO@*Vu*-q~y>RpASstyMNmu}HgNHR2?G6HyGiISEUueUmj!{m8zr5dvddnx38bV zgZiv)Ml7+DXKPtaucy)D#49u{ZrBaHI%qJ)G4uv_=L7T?_+k;y{>p4dQ<>BCO$s;7}{F|ElUFx z5k7zcJuo(U*2$lO22R29*QU&4s4Y!xxZ`n<_Gqb zd=1iCk^3}*9Axc2Kt)YCV_`US!1qjgO;z9HOPaH9sDDtyryVB3<;U?{Eu+hLBvc9J z)k{#Z&52_b6yZoHRv1WU{{V{a2QkE`+O(yU8nollv>llEqz_o>sl#`alHt~2Db!Wb zgaps2pD{JE7vT}sfA)a%SCn%s)ooi@gsH;nrIpLf%?KMBXKS-L2E?6ByYeivNeWYB z$x4r~;ysjjwn`m101OZY$g8iwDTdTQGyrl$34uaJlR=lMSn6{YO~Se_g|SM$pklO` zGqU$e5PoM9mrZQ6v9h1|nCFxy!_!D}A>JV@jjkvs{N1Ye3acN+zpJ@p6v*`5B4V_8 zX9CACxN(YsE5i(NQd2e|B|A+WjA)K&qR@iPbsCNgO}bdOY1NqT9m5G48U{(|8jKE- zFsQ#g%!SqYwQK!hv(bx-7yv)LPTr0+s()Mh!RqVNRtHHhN9eIiBag=(Jq}=+gr}85 zQBq-`nJA0M@W&#?Qkq(wvKV(VrIsptjX#-IuGBlMZU?n8T*$LGLPQe(_9$dw> z$x@tO*mRVGJ|HB3r~sKVpqU!5CxsZSf7ExWuUUORpR4@=&p4(DpRxdYK!v~MBukmH zgUDVMrh+|*ieU1xjnOy+vfFSs2VV9~zjE%C1mhTyBg$*g+kbqi2Vn*esOjk*$|p2A zv(*fAbe%-&W^Bc%@Op9vL=OaXByH-X zg%<7u-KA5~qk?+RPmtR|O-HB>zh};=#h9|L3s+N@u>H7nm|Y|_a?_+tqhh+&wv7aIhPaOK4yj##Q4oH30Z11*?XjX*;EXS|e=w}>(U>i~|O zqKKbSLGH*<@c#e`uq17PhSB@QIpbM>Dtgw&=cedCPg5XtvM-yX&De$>a7z5cTQqNE zTn?V4Vw2^VfDGk*yLTIoKEj-RB`P91VI_EQOoaN73}d%tB6%sxq1h#33Q|h+0Cts; zw2ld<3?HXHm--2ssCtdi{LPapf2bHq!?8@8nKG!tt8tnj-e6j~$y#U^5>~q;;Hj0) z*3p3Asi!-M3DY`a3SwgzB*+W?i5q$-h4SUvVbJ1&*Qh8ckdko0A|)LuoHmR_44q;1 zY3bt^=%g6+CQrjM?jh6+BBqN2sLJ(NJ#}R*OAV2E^oQi7!L6sG10yvOmTBHepMio~*F2VZqhV_%C znS(!P>@^#w_>6e0abk@Hb}L6$3wetbNR|;rA~c{d2xN^kxhJ&sl3H658M}QgHn2m1 zO7UzkgRo+D6qBb7u|ZAZ&hBij-G45&Th53rX#h5(A`}KH@a-vDK~^IGX?gg!bqf>E z*hfSCE9Fet7GS~iu3^OUm2CwbH8gb87?vekXsTkR`E>yzc6sLVMb#bLj^f#6+5Nq~ zMspm}-9<@5S`xi_^(86QAdRyFY@9aGk8pEr%Qv-6zF-1M0(>3bg4*0tlu_0a4jMoJ zC;%V`%hjJ>-6Zt!)J)IPOj?e;>o72}Mv&9S^z}6mLLQNP!rP%$EEVp$cOK3|8@JhZ zVZAnN-lc7XK6NWpg#_yHaD&8wu<@+FxXl{1bx6igAV(7u)9FH|{3hG18AGGpRqB7K zPN&dS;~0fyJk(fZR5AIDJ|kG`G|;q-q$uhB=-%jE$5H?@4{kX-ncdBfQ);B83^J!z zsK%5^T1vX(95#~xVKI(*j`-VdQdfI)m8`4=nnFO8xJs9&sF=lE1kB(My4lw(%htcd z52&>LbE%CneAOBn1lmkcMM{lIC~3ELik%AW@oSfDSo53ZgxNZ_5(x=$LQc~dNgaOb zWp^)U77gDnH8_y90B{9Zz&t{J(bE-wJ#6$fQTTxL7o^^&I#p6+%ouJ`hbiNDTFn}K z#5Am9l|wd*Q3UGXt6Oq7wX8W7KW_L?XqX&9@cAfkIB+<0b;<6utk%&NcBx9$r6Ea~ zGMqi2%!)RCq4TC|^uy>ADEf2F7>n2EoJ#|w!Rn-W7D=L`g*H@ABc+285Li{ec--q_ z$s=~M({k`qu}fnUz@8LUzWM3Oa^%~q2cAew1NNpoYV!UO(oa=ub<}!flL(rV4~(p? z3^7=K^q-?e0DDUgWDCpglBJ*F1zx~U%CLQvNP*-lczl7DS0VKO059Z3S|n!jCw`~+9HDfuU6(RoOE|L=X|%0)I~lKf?~Chn&e8gSz@J; zp&^dRbdzm{<8!AI{$ErhQixFrgNZtbOart`$5j(vYP4l;CBihMtHt6N3EP49)~jBJ zzZu;3(%zorze(9=qiLFPJRKszDZW=1nJTdg(&Wg?7n3KyB+SzCci650y2HVRux5R}1Ip&$W)<6Onacgpj35G|0?PXe{6BTJ#eU3E$Tl&L{VB|#%f zC0GC^kDpb47SB{Q*~b_3i$Uq<7Q?!Oied9Z4FxtY^EFT z)>YXqSlcMg)tR=dWGoW3H>D~mIHSa^q~Q=xRS0*3w0z?^V&f@IvRPZHQzRrlr;t{R zbhn`@QnV{lU_k^bbj=ffnf@RhNc=aT#(GDddIeFI@yuRIj6)Bqt*a5rBb`<^mE>rd z>g9PsX&q$Mh+O~!lNMvy{kLe^F75Lay4oQtN>d_1BnXfY0Kft^V_3<$cQ>7yqTwCe zYP@kFA={RmL#!mDNK0taliXn_0ZBA+@Z*xUI^Lar|@n*_iv6(AGP2^)H5g|J@q&7cfvYZfPY!@Cq+7gOFrRYSiw0!(F2_v|GBG`aUpbcxb8^62ZkI~esVGVc zG^iCEaDZ{bpr&`|+-L7*$Yls+%T%zYyWJR}&hR|7mh`41qevSLty6^!IeY#T1?hhP z%`#<-%hL??m+=Gvo(j4uNTgMM&e6*(Z)Wg4xDS8n>o&M&zH08#)Nm^lTBBm=2 z)NOLGUQM_uk|n3mym*7)Pm8FTqeF-OH5~-RFonk`x^L7+rIk0wDrMDp?U%?>}`{PpFT_PtsLZB_jy|-<70k_Au#{9``*z6NIDGP1;We$+CN0fnBmA(11y`f`kZrDL2 zNx4BjUIx@Pbxmub_=WYq5$d;5x_4PmhT@oR1(>sTGnnw297YC)VTV%T6u5moSC-$o zEX^Z^@dHjlo6gVj{NM7fsViN&i)$z{B`HEqlh97AIK@i6k?!!_{Grqh8pu#3D%6mr zy0z)mhN6%X34x4`700Dsk~-(rY@~BBEgF{>o-=t5HbXF(Qm*KTETAOwAP)eOAG%sIYiYO^L?=Q!PCt zOaoL%+N>$JK_h#=8;%t@+7?}Qllcb{;+29<#Ltm}sOTQFAh+FHsU7esjvP;}!RJZ; z09k*D=R;}o9S2JN8fA<#5vqkuM;EQ8A}S<`#i6COrK_3G+IK!(uWOzIY%FgsoKugu zap^Ki;{#%2hqzRLn`T;0m8VDq7*8KFhqn`0y*VDZ^$!LA063V&WTV0*#-OLJ!&e5S zF0_rX`Or^AS14&yKv!duETQh>J93RIbiAdf;|`Wg&>XmZ9DrXOsLCrK&* zg>)TB1dmZg8$5c8^$nHjb2mW!O=Q_)!?UGYp{}N^t;0+)!7~=AhA7%fclnq|B_6>A zz|fJyBwMc4KYD;4atw`8h{j{AjCu_Ytk|>69Ywmu{3oP%bPL{nu>%8OvS>3(7Ef4z4ZlhWc-q)14{ z1Q?#P*HZDylHZ6G0z@CsaOvx!rCHamsAT^DQirA)A2-)QMNwZX{jVw>MgU!p#*Lc3?OJGEZO!46-uO6C3b(f{I ztfZ!`d;Lx(gEL^YN=cguNMn}|nk7_d=8+hmh%2S6Eq*+A z?Jr=S;U^3V5RzwZIMJ1@-J=RpTvEd0!V9G{I}{{hI6>n=mNV-+(-m$%hGYype=Ek@ z4W1{d#%YY}JzLa=itVqL6j5A!N$fb)h5lm5S%0}w3W}QvN_-&jJu`_>;$YCTF}Gs; zq_l?;QUFqlPFa7L>tJqpmrLaIUlu_-n;(*Fz*aw7S1QkNbAJZ?v3xu zh@SEw58+pr0q&~M_3`T$EA_Lf9XshqrmWVOtdrJ5i9uO`REdAc$@+IQz~7^c-Aw$?k6kV5ZUG73kp4W1Pe+f|5gFnJZf)5a5fd_#!c>e&eFH1dZ>Hc8B zx^;!rrY{Z!Uy3ZNOB4bHiZk!D@ip(ezyp3qDcozEy5YA}P&BM2LD~+{5r`v!uF^rQc{os>6Do#<60nkYy3mKTtU^GLp)>MK+G7n6_=@`#Fq`56=sRa zn1n|267B+NW2d*7Ii7Cir*omC1d;&MCTFMHOYCnQ5EQB8R?BofD8O@%Px^!E->A4% zJK~srLXRJ%mCGeXJ|@%>)>BT5jbO00(Qj|S@*BI%7|f8(qR^GCMJ<(S5L*%odZ%m* zC`o9;_6qM>T9SdN>7A-DW;(id){q@a>b51R%ED|KC!~FQe(M82I$J>FY5g~ z%U_In4NWCP?;Yvs_bl6miEFV1Nwutae1}3&Ffl(4G|)&(a~ytOtux^G)xZ{R$R(NhC5lZXl<=#2b@yVS5h_60+!1kP-$PM&Bwnv{+d&&dO4ZnIBO7 zPE%!Blqd)!PLOs? z;XPX>t%D87czSwn$Co5lQJgCeq{5)4lBS>iHDZt`c_i4(izBu7D7dk>=5Ll#&AM7- zjRCZTl_YA?52<3Fu+kGlNS6&;v$Y{v>P`Ddw^u2{!E z&JHaESpGjWAS}3|8DgT}{zgcnEn@Z;RnbA#+VK%o5O%AtVCae}cP>lG?ovt-#3KT( zkWWWm+6Xa>*NawTH5jfbD^FdBnI@K?S#C-9*-?MVi~j(I+^7<%KH5D)DQzJs5E38{ zFO57)K3zRTk_2UO^(rEcs?Bt zCx+qGH1bGU1BqsZtQO?%M^`K1-p1zq6sd-iC%d09R!Y=Ai`iHya}F^>mFRIy4-&cmQzpC(@o-#~*l_3{74YizHG= zDY;6ukkK_p<|%V!J%#<8N!-G=jk_m> zDeq-Gc2ufd8iJ;P+5pexy9YP$CjRK|Pi_~04+^BiD~vkEw1NXM=|b!J|ex?9s~{*_k4QGsEY zys_d{O4HR*E0#hFKq4}!D;lE?zyN$Lz%AGftbhRGU^r$O+iU44UseK9#uqC^1N?POeKm`K3KCWEzpY<{n9PSyMNqM zHujD*N>Ask!nBwwN|r*Bq9RhM#2E*TP5Zqr73;=XU&G@@^YBXP)>qCFW~lRS6G4j6 zH9RxCRdjGvUR}=#QYKTjJ%n5Xsk3-<4*sLF>z&&+Zdy3DlvLn47Ni0&+7dt~qCvu9 zrY+H7FSh7V2kqJc>DlwGw!Ij1_bqh)05Rivb0<_`Qd3st{I_0k{3bxnhU_!b3R>EA z08-0k+^PG@cXr@%=R1FSGJ6|`!x{5LMqi`nHg3xg?6Hl z0PZy>f;_KyZgNMI`w9tKgecBCWYAMK$gOk6!#7Qb5DbKl68s)IYe}E~ z0GJ%#o8K=~&mHN;DH6*Hh<)K32yV?JwmRqsZVB%DUd=5uq%29}Cm%d;iU6mw?2*D% z`Bwh`(ux8z-{D`BuqT@hZ1J0L>gZHdQ_Q%PEXh0#GcT6v@dA=68#8t%P<%KMx$Vz7 zvv8!X1V<8nMwI^mu|7iLVA?hQlu*{+g)UP#l`J?fv5XH zxw>C^v#6b_C&WiYe)TtZB|jx-1dLEjohCMu=Sx$#xpO1J(gfh4q+&Wcs5td~ z=;xIYR5e({bF8$Lb*WEL2~B~EG9PxtSnI)#>+e;@XLy!w zCrY-$h#-Fv2c!*$g#~ks$;&M*%Z*#LsBF}LM45~{>Y6_hZoYN*(s!)v<YZQFgu8*$QvkrLvHfGGwf;zl@3nA%N5 z+rO1r-C4Bz)|TDj1S?BG2?UG;(Ne(w02A+4*iIoPHB(iDR;2J4ep0f9-kv+JmL!f9 zl}_=a5?fZ+;lTR0Qr$oR z{kd7o{)&7~pUi0ni2ltQL2U7m6Xv-s2V8V2^R0I_yEe>D_z4xM|S#$qOti@shSNb zVac6sC){GWdf${`d848EiI|U)&KPtX?sOG9>CU6uyHBRvnDdZcw6l#Hw;q7La{{RvC9-m@AhNL;)sW?pdy$(;# z*j+$^n2|C`T@17_xOD}U7D*7f7SrhDU7P2*-Hn^=WS1(nc&z}fDk;>`kaeL@M1n>D z;WeFIhvv4qPIQ+p&=i$4LP)ykx(3-z5z? z^U84CyrKQfD5WMsiu5T&z?1{3gnQ+?HaXV)W;VI4;%u5X4!B-%DsV!GT2hpzB}xkL z$x1-ta0ZuptN3m8yVfsAI@9XI*5xfmP3o93Rb>hZYSdCgMTgThOHhh%@&Qe?Srn2O zAJVq0cVn{ipkc$-9C^j}h-bYCaCZ#=v7{*&geg)%tk8e7OqX@v z%d!lIMb(N@Q*iQ7d(i8O2}{9npW15DrKSp0KV~okO@e+InePd!^gq&UKLEzz#PB%q z05MvWo;Rafu)b%?%Pm8hg!JUHyi58tvHKt*^OD`BTwd8`nT@C`Z@#$-?sTatT2Km5 zv!DQ`)C{LlIKrT+NXFjM?G4^@cX6l2wWP8@I@E{>E+imn(6TUDI?l{aqfXz62S~c5 z>Tl9UYxM7wvxWzhu?)>n?S}l*Tw*wUD;(`bB$K!>%JPf6u`7UqRDd0sO8Y8ejP0gdelA>T_W*0VacD?A!>iPu z@F5}=jS`TRDGHKQ2`K>6Z~P`RJm<_79;VATSym7-5Nf-2~X($>Z*qYj1V zUoUC`e8h~h{gcjw_WNgSyW1?qlcm=faR3DbEomtWLR>=9qPDd6iCT0?D+n>Frykbw z^gEQ=+>(t=+&gYntHieaD@ko6f>7G^omgltBpg)%YySWWHtDxmGiOZtY1clEV7SMZ zfKOYCV|7?+OKJ%rikWC@Dm=CQ8^BD6j>gD03wO8^unhMu{Qb?P;cW_iv^LruDIvgC z;9G4@kWfNXC`v%UM8wcDa9m&HFKrrHOYJQN+y$jBsWA6?8cLKq!h9u3NKqpkMH!F7 z`>J`b)UW&}gQ!@hJBrj}xr+fgo@%Pu>V9ITdFd)fE9T2B$!Qr){62s=(iP>++GUrv z4WTWf-uA`TkQ1c{ZNqGW0N|0O-kvpzqW=K$`TG|-w!of<1tY2e(f|-50HRIkM=5oe z)9+I%`iYq!rpB^U)6(L2ofLI~P553Zh&3ElaG+0mT33}?LETftskrJ!QQ2;~=_8`Bp3{7Q-b)+zAa|{mFQ9jgkss!$M0A5RbLzTF zPhXNvJI8t70Dx~{bGj%@dvx)?e-2Jr-a%~B4uE!Am4b0FlTm)6ajb%~-<36P`ch}|&$o7g(v4ls!hDq4!9G*Mj<2J< z$enofyO(j?-v~046`TnyB;kevpx%#1#e4;6M}m7?Oo+_g&7ZI+~w5JFYd zeC9YB#@+H*$@4|3*un~e+f?mJfLc$m!Sxgq`oriZ6PS{l8Lg1UnU0C_rF}|n1}d4P zj;8>xV!gbKQW$RD9%Z`|!G>v(DG#)#4iDwCN;76&iwe$|P%3W@HJ9omuXqq0Lo>lG zIUdJh4H{mIaFz*o_Sk^Lc7GPgt$1RBjB}zmXBndiwp71K4 ze;EFVW$#d(7|r>k4K-2F<2V&QZNj916LWd=i8CvPA7^xAn`#d+n>W2iL!atbggm4; zkZ?b@69fiBar!yo z%GAw8gjE@1A_=23VwwjF_Ff}2j2CkiAPbXTT(bFuscvGOB&jW?Oz8m$3UNyWNz)!2 zNcaAw=+lBsGW`e?vQH0A@YxT>bjkYf_Y!(WXHF z4M7UT>u`m4iZ}qYlMrz@&~q-`T%S~THyM)MY)5!kp>8rtl=ZUSQr6pxUMp>)gp~j^ zLP;T)S+j4aD!k8`hpX>Z7?yRYtFFN@M$36A%`FXZof0VoRQPW5Oo>gG z1KnA_G5bfrT6CW6P7f9?6R$%EQWN0>r0L)ZB_kmJ0413I(Z*V}v=0W>;ZOv>h}30q z-M-pV04ijasx=)0!WeYl7WCbbF}K9M7J5s}y+gz>ENVTuk2O=RBy!Nz*EVR9`M)Y|QboYUSo=tW$dpiSWTUx zi_EW53$k5kx-m)r09;#oOs)fgD1osc3iaxq1?Z-NIkNAnk5qZHtGK=cj~L|3*=nw? zYFey1b`n)qVGBS!n5tc*azed}2aQ3vJVK0}r2fz}h=7$SB~Fr&{TH4(Bpr!T4~rEN zOwjFlzHIX(p$#zDUZa9rY>(o3w^gAjJ3*gGS+p2 zKWChU>FX;?neg?-@C*`~C#|EZf0tohM?AzijR1~zXxVo%JA0a`G-oG%&6NdcX#v2X ziA#PhK*|C`gap7K1%kXvL`a|+-y0j3m2GQi{nCq{v_Xd9!~>x}mj!Drv{E&eoG5Jg zyi3A}Z&>B@2}PPSrBA5OP+708S;$F4{HnT!qOPwG!~!TX$5<)Hml%n+#0IpH(@m1Hcrl1mHydpjyM5%bAp_(S|Lcke3#XNLVMt;?2QL<3I!8 z2tw5AlOTj)Q*h5#{+2Q>Va4zdN#2*CI95G|!-mtvnC6XVrKtCkYU)y+WZ=xMF1G;f zRwnlaJ>yMZCrfN?XSuEXt1-S>gpC7Jj;XDhokPIe z9c4mWLejR{2MO6i)SZ9)R{EaUMk9shEH9_@`8JAdGKx$q4p{0wS(PJns;jFp#_r0h zS@c_g)(3-oe5W@2z96Btz>=cXxK0oO?+mDHgn<)`PBb~R?Ee5Lvv5gUi_@V8TD7IQ zB!IhQvZAFDLe{mZN*EFZ&3JVyC}ix(Q&v4sdVn$`O(Cd-F^Q^UGqV!xC@40^xSN-= zo1Jb?0L)vrZ2E2-c`8~I7vT;*sYwcuqC#dzNb`!D*vYLd5bZIAP5Q6 z0dS@^f}&3us+`5CscA79ib^?Qt*51^b*HL`GR094ViIL7?;=Q+BKnK#bI+)Jt2b|W zESbM*biUdhOo%=-$&tW=A~;YP43@knfs8g%&bKji;{?MBWc2bE9=gBPqr6coa5FKBgg1fLAcNfNcFV;BrY zMmx|GZEN3^C=@6iC=#Q>4B^p3H>nPaW?xA?LeBn`@P3_Pc!`4)rp=f(FPU-L{8E)8 zt7ckRFxpL#iQbYH@+C7lyF^Qt((yLuzjt$D%a@nyQSl^}nnD($l_~?PQBt->A_|0b zlSUHGXrBEn7SyC^QXEu}4%pLyoui_9s6y*MqP~=M!>*V&sUED>N0zJbn%uvHbqfi= z>C6~<%{dV!D?;oy(m_(Jq=JQ1hqG8;lvik1Ib&&V(FMY!IHnfy)V~2ILg4tyaf2X~ zz&PVYxo+yV#j@?*RJIj{pXe*hVUFAgnIi*BoN`W*boUXTrLba;i090?iegwTObwo_P-=-yEVPco=d7I4LaLShR5E85JSmOIDxCgov|XZ z&pgPi^2=qAf)tf40e`}yGT9j8go*PUC{gGaPddZae8G!)Eya4a-8+143JiQ>G0!Y? zv3!iinxcWO>O##=Du!Z0ZVGvW-&2`0FWA`T`h#Vc*20vf6gE)$2~T)ajE4|AvPc?? z5+;OQmhTJsYHn?QwJRkqYfL~aG^a|H8%orb zfD?woK{F~CR$V@=mQbittlS%=3%edzML_*L+!MNkL6iQ zdQ_95RVm|-@e_)biBZJS4qw^+RcR@3E%HLrrJYT>@)jV6))srt2OI)`QbI_j-e~++ zzZ=fARZ`~c7XYQn(@;~jD&hrUp_QSOs}WL`9%AlLMaT-*Dh1B~SJw!J=s_ zjrFHE;TeM#%{3BJ<8dxwz#>5ji^y5ZV-)f;Q&VjU@vE^>?*Mh?9B12|ghNh0SV12C=6%oQ#ch6qazU;PfXA?o3z}ZIM|e`NG3<21OgA36kch1oh}1fwGuTbjU-jvlWtv( zF3i?JxF=>F%~bGWa&OIzBUHx1IE{mD6SRBj)V>h}kTK`kO<2EGdQnk9EEHJ|f|6e` z+3KnBO2Z-Cedka`g0a+GY1>X3F_2!RQmdt?KpIriBgplQhaS3lS%V}%XirE|r_6cL zm;5$5!G-j**7r^Gu3V&8WRDtx32GWi6`r1;d2=B~7GN)^`uI=18C&kyxKyvSB|$JF zQdA=mh>?f7ff>1O;@N3RWbFn{(Ob~pz#6^r6=K}a{h07{`Iv!13|z+bA=u$CX}>^+m&D&s;qV+~!AN#evY0WlhPl&ATTdSRN>epLX;BQGLI-hhZEt|~@gH+c zlS;}Fy%;GVTK(_wy}lf5w~aJSKEvDG?d|$~oLZDp6&iVgRXu#r z1A+AXevUp6X(?4?L~Yt0-L>!iym&V>oT{X>Z?Fajh{adQtt8x>PEbdd_F*e^;pY*B`PAQi-{jice7|Mw@V%|^7(JbV6|h%$|W% z(m}?8E{1eR4a_lOS%Wdv$%GoJiDrgcs!447@w zq^Lll>a)`JUByB;$7n0vSh6b4@s&0z3V_-+z5F~i<0CWEu_SvasubSLDVryHB*Zd( zeRTN~4vuN@FsU;N?>WqIn}ksI+NF)i@zY*9{%kG)?@j||5x1tBRlj?m3g#~eY!#S&^?^`yXvnfWxAZv)6CI~(|r8(4~NlL zOqCHND*Gcx^HG4%YBw7n9#6SfYdP{<332qgk%89I74HBU>!3}?XE_V_eq12!J=)fd zzvmGilno!mL)PXEiP7Phody?)!z_eUR8~{QsEKcR!_zn{*BT3QbhPc6^a5XDg^)1P zTx^r*NFH#;)ImTv;T+Zv2N%rQQd2N?WBdQmj^ zoVklGV)#nog_f#RNNSZz5UqBNhL_Uz8T1qKSlW~F~1oz`!1VL`1+CYP6Mu^ z*E=cCtz-**eP~)$?8H){KDG2`9f9S-^FAFd_Yu0KVq;;bB2B+vBny1n%Io``!wUZZ z71Vwrh}_*w*2sYEv&sJeFp=(>WUS3NB?@;&Hq^rq5 z{1391r!IMu4mPwO?~+05+C8*_#Iq$Vv0j~(^k7Px`~a}OZy)I5XBVJQrHeHr-TLZf zFcGaMzQKsN3I@F8&h$R!Z+`c80R?1g#Hf_v07OO;And}VYj)sjJ4~4K+4xl_{u^B} zsLj8NCL`4R!%bIJ4g*1r;tM=->@?>Yf-E+YnxZx~jQMlOf$h1RkZdi;t3Cv1gEB_U zFi65W1e%u{Tw0V4Bqa5jCTEPs&6IY(2JC91(x0k+vwAh^bn|5jN*qe362oZgEJDRB z%+%LV8&`zgejV+=`DrXE4=H*AkpvMQA+VjMV+u7(z2Hj8*dUnVI(=(tyrr6Q<}xB| z4>RGlXhpUOqTEl1W(VrG4x4=rV3!bjr8DvQP?eR1Y+7lv8>PhX?@}3W9+*?sRY#X` z@8s|?D^E)@`EOT<*GzA=20)Om&`z!GpC2w6zr2*j0j zYy!1m>jy~vX!ZX9(+xLSv%O^wC)51LRhe-dBMZW2ifW8|Fbb&>3cP-*v?@{H;HwIF zq7N!9i;cuuUc7qqIJrh$ZEjNAEr6q`BuZeFE=be&7}|E=Ohz@aYj2UZa|@?QRl}-< zk@o8Ql7xvRMmCZJ3?Nk`<=@0Z)MrlO>Ll4xuL#Al?C~uw6PTf>!``Mkcqtd8E~QFR&|r;H7a}}FjsRdm*@nuHn7VGp+_FGRZX!a8MxZBD zfHo3NGeYi5^@G=3)9GV4)vQ#wE^VW#h3Kj<`elk(X{n=4`&=cIyAZA4a`(3c-^v!! zwG_d`X(mMU`E8(Kd5vHN6(H>~A37y+`tJ3MUexs!82xCz&4 z*l_taO8`O#qK-c7D#y4JDn6+gf4yTy-fvtUu6hxddM}P;iD6uK7{f8lZeo12Nn^$; z-wvdbZ!SO4JT#Q-Lx5RB7T`ATDLH~vg{4|`1A?LoaoZS(+Bkz0E6Z-tms}ScPznP` zl+57@fjv7h;a11eUrd?r1<6!&y-ewp9a)x~%ZSTEgJ$Y^=_@NM0BCUB-1$G-nRP^e?p%r6$B0ak@g9EKTGi{pWFf}a zAHt$B^iT)baHIwa>4VaCF;|1rQFVU@$8a^NnyOk1+eHmERFcCRPfHdjQyHhLsikT5 zmW`6#@rLsJGPL6WeXJc((jV4;PDJrmYE#+I2x3QUuN#X#NO!00k&?LWx3 zHSjPl!f^l+RG>Bp36a95Zq1UXT0@Evsn->>suD05l1ck|YLD=h8n0o3ih9awpSCuUScRWtM?cKmSV>XRme3|-hzCkak`h!-CVcRr*VnJ5PK(Xg zY^jHO#C*-r%x^P%?j=QtLe%)2P&F}*8EPVYHb<}Gr9N1DXgzs+tM^N<5V;cRUa0P7!A5OwNKZ>%gBuB%Ty+ zk+vSaWwqc7hy$_=@M6PMZ2S&RDi76S%F4 zo`GXhRhZ8*k^vh1l{ffuP~6)SndcU400>j)nZyK%Q9h6=JKvksW%*O?IA9dS`Tjd9 zjDG+;%js^0yAR43c2%jxI@gZ2V8rokdTLSR;h1D@3=z}MBM_#e%v381hb5cMV4*?i zf7BheY~WMNcp|~R=?%0Mi;fZEDo7aVf@MYk14x;SN9@w`FLL=U_eIN+RSqbEmXMam zi3yT*D9TE-g+jFJ(+R5($GVwK&~BIduKY!)sp69}99s~}_%%$*9a5J7NHBUB(|35A z5Hd>WJ=fa1uWd1^-z_=y&QZI>p6fzgaU%~CP=MAD>mQ~7>4aN9Eb8dYkcD3#?sLxr^}zUd2V=AN`Xd{;1Qu9 zff%huDo@_Ki;TL*F@F7McG*bo+GQ!7I>wLM7z6^Pjby1|DH?{6;i{DX0EGSI%KBcN z^+TwXNR3xnJ{N{j5>CMI)6G&;vg@xT9M>5~)0`V%jw6-L|Qnjn53X+-ggr8c* ze!^_j5qomq-v~lANE(NDagLt`sH;fJ7{{uvn)Gw1Im7V+tIGL@0-?gDo*E3Vg;y7n z1cqOmj-@I~351}cqN-Va=4K1q7Oq*!^Bc=%asc~oDPR>ov;Y)H(o$0q7?MfH00h=R zy>Xb?Wmk^xDp*?~qBJ&Cy+DEpQP7Z(Nl2Vy6%{2SYh0hf{{W#`7cW<5PsGQrh?F@S zq*QpExL2EEhPh#Bs%MLLy2g&3gfUyZ(ha8T&XIP>;AwgI@nj4)s9DFO9*%+U-P$UGz5f7o+l0M==1R+$zsepyD|dCrl%a9d3MbZ-cCvu0 zhO-9Kr59{A=@=gySSm=soenlQ$VM0nzuvfFUbcE4(hP}`eG_EN6E{_1m~=Eal4Et| zk~(yyqlPMB2w9>m(l~AAvwFd?edFcyb{t-?1U1XDL_aGQ_OAg5@lNefiqhF0Dr=gYcf@LM!Gdc)T#_J zm#h_Xikw=X3vV;XqBQ8W>Ae1t>3(GGgvqNAZF>{Wi+wRQaxZfOYNrj5K}%(LOOkuD z8v^v=pq-p*0^fGqMcWT44YhV{*ZH8_Mxszy3nD>KP;jJ@NKU^INd%K`#h#M273&o&1#RxUaG<)8?%!{5&S2#Bw>H=J%DYhow3stG zic;d1wE3w+6SRt%m3q!&VgQ&xXTQ?z6W~%=L`Ik>22w`ZNFhBKVIr@a4aj+KrP*k2e6wxpynUBDMCD^+%I>O`U1~0GePJeiK_!Q%J>?Br!y(5oSU=G5Y%+0=q@d z9?Ej&lWeUEanv`fj+iP?9b^ce6kWTyLm8d-?M9$vs7@T=TN&ZrpM3!J7d%t+a}CKN zs!yIVGcy?wJtGH}H;QL0u@Wp;dkD8V(w+E!Fnn5vUd4K5L`qIR6R{@{Rki_&%#`+g z&5M7VLOZ+xkfS9k;n9fUv{9YQew_U+bniZ%o#c+1Lq#oQ@ubs3c&UOsCUZI|ZKYIu ztPlgZ_B!yv`-Cp%L1{`^DM?YlX(=nzB*K!NhB1>E(ZVu@`@LF>4S=mg$T1y9h@2o( zCTR5i>0d1M7KVog=@kYcSv%C3u>_@!C5^xvgg#*nGflXQf(C>i4jR35r0HNbR*Xr< zVMr0BC+{X;Vj>MBYaq5EPfRFA8kZ(#pump4sGvL5h70Km3YfZMopMbUV6UQD2x;k- zk!F&WDmN8K!;P@IAl#SHygP7FW11TWidw*gq+!shgvU@4I2otEvPjI^)JBxzbrlhc zeR0PFx2~0Q{vUpnLL~H^E5KO_qXzz25hm&gW;WEGuM0N8wSDw@%4s zOJx55p1<&^TZQ^+=tdVq4jDs|aLAy;!>kdlB87om-Tbv0AYv|U--uOurIMl%B*{J6 zB$LGWcGH7(^7HpH51CQfvPn3{4vrKwWgdWfa9ou&UKx|=DY2xQPb#7aQ3c2vTo5c* zy}`Nm@H+F(7i5GKz>%R59bz{1(V*RItw_a$5;hYiJc%?N;a;76K2gmCb(ud3shLPq zHBB5(D;w*%*>AX>_TZUWwZRaTK;QyX1Kmp5-Rl$(JEZ!PkDfKDkE~Bnom9(SraFn! ztU9n@`F=cZr7(%r zD#BnuQ3KsTU!ypB*`A{6U2b=*uFN%9ZW|imjS>o&o>`0QN+Vl2Is!(cu-AjzCz@$W zD^N%YnIr+minCi}B`t)c30^QdxYswj9mgcIvX-(@O59WhBiM15w@`DdZs zTk5P8GrkptZSa-U(OTM;m0(fez-bH+;6i@T*+);e|XH z2nk4-Jrz`bjxl^I2*$BIa~OzKMv&oDzEs+YL&_PVbK6}ne%}$wXD&-;$ovfnnh#bERMEt%)SQQXzf8SVDMIZ299K!6KTJM=Bg455wrANfE9Vz+#mGjWe z^f;YXK*@Mr1tjxHO-WcKQ5hv2r`(~G3yZCY2UFa0peuYR$DINlMxY4m_?nlRsdE&4 z48U^ibQK>kn6@KTEM7})RWZhiBdxDvs0WFzUny)yN&WQlQQ!de{J&aFV02jL`Ig79 zNa*SszONR;WLSKs++&J4OFrKa7>^DD3#w2ti7Fqyj}VXB~dl0^ir z$04@vy_A9p1dDdz--BOxM~h%T-tCF=#;oI7$s7z#E`2{yQsFrhIL(GYBRIxClwue6 zKzFE-os|1_sn@Z&zX+SQOE(2b5vYY8i68?&P3cyPQYZLNxXAa_l63z75~QNe7*#wJ z;yOP&4wjig)PP+l$x4!+J(`kQ6VvZ6c7y#TaNo z@YHL_BQqLqUROLP(vcisbf1+l<9Txe#3ZYxmW~FgtJsSw%8=A=u(%#+5i*57Bp%xE zrTqy~fdgkq2WP&N+lfHujR3Ea@%)j9RO3|d^OSMBM+Hy;kxrpR%5DRL^n=_U0-9x3 z>hA_4f&52ErOGK$D4cpasa4mmq)~MSn+1xxia6Guo|26*1uW0y!h$&@Dz;m*T#p+I za<^Js2@2R_#n2}bI_Qyx*KSEp*(Xl|c7S@Q?$&4gSEn5u%Gey3g!qLvYNTp`B{HJZ zR7FlqP`QbQ@Zo^g_wESfrIc^$WeT@+ElX&WYDh>*gm?@bLDL$K9uFU7D-PFnl}AIwn3^pVquVQP5;3Ymkp#B=+)>i)$CkY&hF z(xr4p98G0yyUA9hCT3)UHVE6#8fVN{9wC~sf9lo?Ii8^1)vf`WZ{A>Z_jIxk@PTd? z5?of0eR}$T4yrZ^4X0AD9|21I>y{s<`38?I<|w0Dis+<}oq?ROWpq_>sMtIBYHz_C zaFju!bUEKIQh0Okq^?-Y_1ROYboqWYjoKL16_5UT)z;Gr&07jp}#9fSqw7P*5bI6GU3>LBF6h3wbV1OpCb8j1s5)S z04IPA{om^z&+O52cy%e)15C6Q+iH2pDk%$erL+W~6%{Crfglwq3Np2{UCALF1e4Gx za_c|f!`07D-7d|Lb;~tjpUyId6^7n)C zPZbUT@adt#)~P9s1Y;N(;13cw^j8c*RTz~FOKUu^*+Xbf@!)TM6~19f^B)@WMh2C6 zXCudpW{OE^F(_oKp1H||7hRE%(jL|A3O7#+$jufQJS$`d>nzDld z!KB2cqFRTOU}6M&i4%Leh1Xu(1izWJY)5#YkW2|NC!kTFV4rn6WqKHJ{B^MGax`Z7 z8iawjcAj9RBthJrY!|hOzXz6%wiKY?2f(17r5JA0Lq@8!Fr@$nYsWV1j&w#w_ ztuE>CDc{RRx4eOrA7{tEB3<=An6gBV?sry;9%*?v`|5PvE0c0mRl&8V{p8WS{08vB z2lcVlLq@dpv8ezZck647FW=+Ne0^Fu0?j|)I(;y#f!whzI(m~=E$TA{s?FHm514Y+ zB~_Cu@N7CfDxvc9vQf*5`7*TeRAO>PV^J)7im2=s;G0+o$Ftr2EM;uiyKdWo6QxB; z8&snuCPu7cK>(xy7*Un>UKX;wY6SEc=)=fH1FX>y&H2x$*?${Zqs%z{OGijxQrU*N zE(>psv|R`f)TCbqcrGr62Q+7u}3fR!@f} zQ`KPrOH7!AnWr$c%Mm+TnGt6m^1ak31d?t$@@});X0L5j^3?ay({!nF7<09V*PgYX^^7JSan+e0KU97pB~4BeN9Upv6_XJ zq*4(tWGuii43LEFJ5>TJ2X~*gt53}STPp6I zT2=d3b*W9JFeywB41W@~2!S-+mAc>4H}y|j&>W%Zt1QV=fF(ckDYGswn58&1H1WBb zx~j6Cq*I_K#G-?|`>NZ6Fk5}tu2XoW+O}N_K}wV+5QITcaZZQ|hzCx?kB9(GIy+Ce zV%axK2q|=}2q`3~#f&r|1nN&86k&%F1qm64EA$hnxGz^TZVl4>HY^(|(_qbl!VxiJG&FRx3qZhskZ}wC~P$}DZcLmNxG~(qPrbH zR?zA0p8^ht+k5HbZW|#}NQk4K(pX>9$ENISuk}%)<}BwZGp!EBA^yKgNrT4hLm_%S+6p|VFw0Fgp#Px2O3ar{b@H}hAe6ONf;DU|xH zlyd_!{{X(sYYM2=+qTD79m|vLAGeaOZqd87c^p*RgW8i66Sh6ms8>Rged4yv^uv~p zE$DlzeKJKyj}6AUmqQs#?O`QE)rbJS_S!+)w<8M`i>#@Kj?-?L>M0+k0khVKySQwB zNXM=JGE2-I{qS!_fByPHzfLx>dIpitT=g~!12jt zne34&Lh(&8Ep4isbv^^(z+IYqtitgp07Fh=!cz)9RVLoARgJRx3y403Xd(5d)hvnC z-%HtRt=%NVqQ>xiJ2GK)bajyK5z1+6<5@Nr0PVOs+TK02P5U~py(YJ>R}CtW@uuu{t^F_kIjWb9Q_Z$1xeHz>qa9M2RImHA=|qGtwbI z@uN7oUDj^)1fFBs`z>n8_gqcW`2A)2YNZR@ws4+ioqiHl?8{Q=zn^Bq_~H!v#bD9@F$XkJm4!x*RL5)z!FsHL~M) zW?`ej+|Z^XkyXz`(X~O}RTLMEWb)#XRmdwQ^tzazcY86*bM!TuT_C3A3%CkW2|AXS zmfoOUE+`;q3PKV>C&WQD819#78IJW?BKFBju|4apsVLI5pt9oHmfUd=6)6fT?#jO8 z0x>4HdQbR2^hd5Ag=8L|vF638u{=J%Fk-lC#a%2ylO3k3s;7ozST-$0A=BMS11Stn z+uFu^v)QeK=~i^KEA#I(wpQU*5ZcND0thGxC9$bdtw}N#l0ivs==P<(`QB3AaNYZ@ zUNBS;ls3?8{#DfhZlr_~^D9yyf}&)|GL(R(%^!xhN&f&7KSSAjsGgCEb2iwMT3RpP|!A;aK|GtE^zWhPlX+o~$Ys(sR5+23RtKJHkT^29jP*9iqmQq;1Q zB}N<4ME7VijRZ(cl$5x2(RHtAdG_#Ss?Th%m1d;(t_B)wO}KHjtt&&Q0ZzQsB~7I& zQk34MEd#tdL2>*ZJr?I~kp3I^?i15o=S7uzlhhFwJAzfzP{m&j82O1X%sf<5mQc`D zNf1U>+VQh62XL?sW}S^>-KH{|%-CytYe6n4wIQ^rLJ8DDgUTf8(I5l>H3bDL$-8gP zcZ0=trUOlPYO}RkR6>yJrKbarHlVbdi;>--Q~Mwitttejtw*BWIKq8x{vLDD^=AQ0 zFEeKRyNKoNdY*$2l9y#ywc8%MQBhGQjp~L zgG9k5t9S5S&z&>tr$>74=|eAMicFDK=I z8m+C8@(hhb#I(9F=yMSt(xV?woG`kYtSXWnx38tB7SLFvYbCAm7t@lB##92(l0N2^ z-&7qZWluKy;N8NQLRE{YTDtWi0e=E$y!B#&udF_wF-*CEgBCL-D5}Dq`%GA!85ML4 z4|TOfOQ`VEvE(UxyUEP5e(8Y@At`Z^oJe(_8Xyjmf|5E36kn8Yg6~->k_)I>6{`W` zNl6Fg*9MVZm9wq|QG!)x9KKO-+}kQtR*T!5>|_ZwiK0^ zE=rRK*}XyKiLpw2z3Ly;)lO`vdGhUaS!bpgDpGEfX`-p7O3XevWv9hpQEX-Bu?AeUn@=1 z_ZO;PdDNT4C;m;DBExd^ zB|McA00a}wOx16^RYahfP$Y{Xu+cBZ?W{}Spd^z$?3E?7m3^S3GLoRQBzT6QB!P}4 zE1Asg+8V5E+aY1Mk}*`T?G84Uk{d(FPA(%-4xX7Ni;1rESDy2Z7lu{ieM$9ATNWpX zLTTt>u3R#rnrIrKswf#nJu1~C#CfsBEu^zEC{Q?N#z^`cBq0e%SdvmCjXnZ}IHkL< zUx@7n2?PvCrTyY~9S&R}I+RY9;iBpYi9#C-c`lW0N|I$G0w)n~F6F;cS$7AK{XKel z$h|efYch>mRn}&jxLSJJYI==ok{WQkD{0le;UO%{cQ%TuA6`PBvEEC{QWdC@rHSIX zaHS}4anc}+Oeal4?&q0$T8Er*`EA8ugpTO%J>Cly&J+@vg~;WkxZ#y19|=d2hy!`MYLI~g8&xDfIa!A~pjC|xBw>7#Ll;&y0m@p|JQpI# z=is!=6u}A!Qpm<}QlMiT00S5p%^f${Yc7zh>z5oo=C}lcoj+qpb;UU8WjHBFaVqZ? zF(E!0D}7Mw_pKb?OPCkbKU`??o*#?Xn%cY~hI%Y6nxdr&r_CbA=1i^(V?Y&w0gt_N z!pplCR)5MJN=Fpx0(!_sJOSGzi85+k%C{3K%LKO0v#Co_a#j|#Osz;dSSx~3liZCd z!7)T^=dVdMxV+fDYsN9W_gD4{MMGI%QqnVD&H1YNb`|*S_phKlFGZ!Dx{899u9B35 z&rGeteWXdLDV9@i+E`&ILKA{ek);V6U?H%SjBzov~k&d@0pB83e6h0k$DA(s-*Lx)yT| z8~A`662BDAIl}_!odzFLw9`RIlo(saOIfxV*{axEQdLQ|quIk(bBp3a3j2^jfR62< z1E~T>wu;*YaS#XNl{6dPRMzQke zi9|LF_DMGc>#rk=_L^F|#}r*$;;kjZk;BHb8oDUSr|%XKp|FIXy(@4dNS&Y{9aGUF zmzZ`T>4v))!SJ6<9-Z?JXR4_&(yGr$l+?BLOt(QzQ0cfc07|EsxY(ZD3>Aeepe0Hq z!UCMyV_{2Tb$@#^94Lw1;IYZd(S3Jr6b`KofL%%?2q+~>QIatT;xNXD2ddnK)f|J@ z9A1m7nJTBJ*v(`xR(~a{k)~+FFP0r7Hx8}0L35}*`QHA(^F`)cw%abGAy&>Ul8_W3 zI4uSjCP+~-2?vKjC$`P4Gt#H*mR5kRDk@5lps)s{sR~L|lLQzk7!X8*G`Q)WU-a>i zF^VkT*9uD5@Wg5gsOW22nxxgx%BCv0UMgqZ<%!5Bgo!{GU`6>Y=TBxANK-aCb@-F4 zNYJolAQcU<_Z(9@DE%!b_`1DlYQVj7^rNJiqYs0n*=nMC3^Icjz}=vhI#!yBYNe~7 zsW*#rOHSjnU4R=ww!DrS-5blL2d*9ged}*Q1wkrGbhw?rYQ*fri4=zUq`uK?4XILi zV>>Qv~a8O_6^8wWkKzXrKZ z=%*tJZPa*F?|6mCg#*Gi$_B&GY7xmZ2d_KE){qJl5()dZLb@lat0UA)b=Rmg2DY}p zFyd6O2=Lm8s+xFUo{}^Z(LA@>B#bK)`c3vXH@79M-z>{=^bgA=l&C0}PLf1`bq%p6 z0};_kvMbB0kf8prv>bR4NGajxO6)f=;(a#7@JTUfIMMMD@ls0B6KtrFUsow5D(x^o>gP$z#cCC8qQsuh{N>l=qi8v4lhyZLn zE2#_Jq^|`ms~DUPBWRg8jw5X!Urqjj>H42Xh+;he>77n*Og+*$CZVB@t{Qm)2NB67 zM4?tzLKrDGwX6?r2mb)J8TRlh7;Rn=D(=$f8G>}Az&c11_YgpnK&$Mc+QmUDat}t* zJ)1pg+cV~Vgk+epK9TiG`BM@?*j_0|B`ri1bdF7m%M@x1QYktuuEy2|@fUSh2-n9-T3Q}~+wLr(5d6#Z2J7;t<=9T%Ia?mX;VbG+!ve+$mAtm<$ zfFTVPB|wATPll2GEc_k)J7$kkxyRFvJJC5ImkYybF*-Wx`RQ<@G&1|D@k3KIuEkst zA<$mHjjRtREQ2Y`U%g$W+t&(~)VB1vh8C3S(iWr?JE#kFNnp;#3c!fW2q*Soo$#$TAU^N%QZDR3*s z+lf~~76D9+DN~w~sl^;?qjnvZXS>^LXPq~nT(X5Fm(8PWpsrWQ9RetygLib*p)RNB~OddQqM1ySx+pILo8sHSA@u+$hL!U1a>#?&Z1>^ADLke zDFw2iB_ser>jMg(b0hgjl+=Ym+LI~tCN^xSRCyAVNelup`duMa+FC+IoG;|aQLZS4w4 z7<;|+)2dNP2Z)OL6Xv{259%LFx_j1KD2XD)u&5(>7hT_@Spg(`Z~YwPhW^@j3qzx6 zl%9@}^PwK-xv4HPco`o9@}%7?3%7E$?l&6_*6{E2YR<5c?!ZoHpl+yn9ck;ek2 ziQGjyQXx~i9Y%uRw~riXp+YHBLX#)}l0FCWx3ii^q^6XHMuka{Zasq9dvAZg;mRmd zdVRy{)LE`c9zBouaWTT0H2#&z4uuH0u-okVIdrNiB8IAWr^MnZy+xF1@cX@-R+S1b zP>OkqpxiS1!G^xyuj%&jdQ2Kds?WSbCzl&p+*!uqaR9?m`{GmPqWNXa_Ub@v!~)W=&vbsg9EI?u#8VB<8jvt>`ob{ zYG9EvvO^RE7IzHMy~tgfi=8>!-p}7&XKu7i=>Zs=NCXt0D8O;7Pjc*T-SdkekgK7 z@ZY7nVGX2tl4&K?4@Q57ucwKmpz7v$s*C+ulB4ahoFQB%Ar0gLWPejl&{c8Lezmop|F8S;?e*1a<0M?4_+xFjg zpKblTHroC?Yq+-l_u4-iHva&IvoNppqv2ow*V)^zABUIW#I#Zz$FqWPF(Fi7)s*LiZ4`Fn@k3Q&#}b?3C9dPc1Pmjq@|g+lJWDDAsOX%eYE-+mE7 zUKQ&*(?$j+%ei~0wfJRKTq_)rS7BIWktif93W+AC44{&2VzvMcN#tX9+4ZXiG$|*c zE-Fu?<3nqG;><1+tOPARBw^@jMbeC4A@wg9s~IM2t%y^{F^-l>+&(B}sW&?g>Pn<4 z%%bFY7E$dy4c+bwY^Fnwqoz)w?-)^#-e+(NKv6vh0aiuQHP4w9;l#0=k4cKhPjYGS zEXjycuuyd+9L$}C^|ghs+zvXec1 zJ#;M@<(0y8tT>N2pL`#7HCuVZ)F0u+h-H|vZa}ZhnQnrDKO&Bo6u=UuHQdD6=SfQ+ zc%97N1A#%i7uKuRmW&cfml90%M0+Bea^bfZsVmihi4lPE_|1%vAtTg+0Ev19gwuJ1gB_M)mr~d#^Fg%T)X)|1K|$MX*)4Vtvuw2laE&px~tBpX1q@h$(Z&` z#OZh9nTr;^JoLxZk1iPMN;hNx8Han?+;$G#y?LJd@nGO@8sAOs%Z+sBd1x2##CymLxZDM>4UpAmzo z$neC@B1H<@ZQFz0woILov~`Yl*4BMw%QrzB=c(g*&wAUaPC4gI}ic4GF7eo zx?#|iNlyBL;qMTsB!LPC$ti;;rh59Tl{QoK6Poc!YOx$4;~2d| zM@I%w>P{6UB^W?_v`F!gl~PG4_no96LD3Wq2)Vw|?^*uo3X|c|Qb3K8OcGBLaNr_{ z+}+m_A+n*T5?pAKsp|lU8vq#bCTTgG{UCZtS+JGM{XxuGVhX0Kdb#nuCl18oh8Q99 zS&~d1t*@y7mKFnBb{rF@wC9=ty3io?5J!{}4LFRY*C$8@2G0JqMsr{$7#X_nOhMdmVspfinZE#Hcs?KPt)4UI)7Vz3j$ z$P^%BD7gY$WkZGrae^=aP8)jqYW6*G`lrcQhe7c!nR;!-usp|CRUB2d(Zz|yJv=y7 z6tTNUSMrWnnz;mY@x;FLq_VDoh{RRgmRA5IlhR~KIGha)Z0yQmPHF&of=>aC*xGni zasCV5qI!+jUspN)gQ$H!{;I{)Ofdz1DOnv%O0rW+Q&Sj%Ns>BvVtM3Q8*wZOCevYV zM_J9n-*vJPDLR6d0<@$7Ad?Uz@jg>hQta5bXSz$NQJe&(M2|U<6ncGG;+V%k{{Rzi zj{3^VDGb!viwjIYFwejAKQT`zps9{>q;4!2NE8y=M(*5gg`sGP@g+%E^7~aB@uGH} z?vzM7VNtilFjV_1XPhSm!E+4lPl#pwKCS@UO=p!(=x(BINcNqURvo*UGDoaP!XkMGO*!>bt5U>Hqx4P`|<(BUSeVX#3FNj=JX zhf0c>(LfHdlHLc8Wwti<&UdP86sN>MBuss~4^LG__bD!b8Gxm%>F5ZUi0Dz0LFlUJ z{C_&q-iP`J(mzOj1*(${q@lsHA4R^2z&g}oEw z65^zl1j$hVoux#&~tgR#_krw3W6CDkbcEFvjC7f04f7!Jyop-rrf>hlc_Qs zGpm{F`iEJF;W)K^2}$w`Son=@A4t>EQdYV+T0>aDp@AIlcfReXZt1T!b$La*7Y!jR zE}0F54)8QED^N`6KhQ#mQ2>$v6aZ$y+m*b9lck_FE)I=nVpFiI7}T%|6C)k5H`BMQ zpH3Mgq=HU?j8b}l$rN~0bX7F9#o}G1mNnXJZV9p0 zirzbRlLafosD3r&?uFBR0(GZ9I9+aSB?$%J7><;Vjz&wleB(*Z&Fq5~hX3m{Qgzcg;YUWWK^|PIF5UvigcxpoV;W0hC~*i=n%#39 zCW@)N^vAk z23c0@+vY{vbvzMp+M+cfO{kJnpczWa(%{m#gr!9w1&C6sH`c%4rR$p^bx``6>E>yq z#&N9YibV`mcw^5+h{I7gmqe7PL1d6`0S=%L2|9BpGA_|F^1-#gY8pWYydV^)DELWj zLvF%gkT_DU-_BQP#k&edhcqZdOAaI{vUQIKh!Uv-3{D3crGHXhjr~k|T+cJ)UcF?j zOD*Gc@WUjqO&ZFi%X`fn@H59Wa>yHNt61xxBHYW3-rrj+^4Tvo<3om!t&!8J44tRX zqK7I<(4v(EVFc<)NfWY13@{%W3-HX(jAcw(I{dv?Q$5Ob6bn{KkT`+>1C9kfQ3ipffaWGP%*RRhpE@+1Da<*)9-_?Ir#9j> z7=>hbe2E=ZT=G;fl4p)MzsLwgE)AA{tJ(Jh!zrj~<1K+=kz$k*DU35nF!>%>l^mVh zL|PvK!uK-ZkUwPlND9VM$ik6CRmzAkt2^;+UEM|*i5+45O()w^wl`zT@s6${W zUuZ%=AtE*aClY;TqJ8E&Qp(AM3toDvD0kLc8*z#2E&vr9S<+ZoBuw_pE*r|GB!{O4BWQ;sY$6$((J1@?y zH-7!=yX6$aD+mE9R-&SUK++5!3<-c_(Yf@i>W|TfsvkpG@1*Zn+0imY<1%7c&0AE| zic^SEPmMk^6GKqy(YE5|8Ke7P3xTLSgEzNxbIsJx8_jZyb8tJ9Hk~Qg-K;VhAxQ>A zMx?9lGq$9S+s?AQ_a^>Zm^@foT@I22>XWHZVEDBa05<)qOu+z2%Kre1_of`j_>t0L z^%#oKbh8A?^;u^I#;1YfrA$V8x_X(bSqgcOQOzAXQzV5(iW&B!Tn8@u7tO7AY{Ck! z7W!Xtpg~`Dlqn$_VM|F-Sx7u!N`@nAUeIh6ya{zcrH0v6yCj3*l9d(df}yKOOh%-q zNl;9zC8MjppgkJ;BlNe`oQcscrhlDm@77#H7Os_+xogZXiNX+lN>i3B9^6C_NE60nZ5dOrL;`U9J?k5BsG z{Z!2P*`uSwDY0C6F*K*Cnj=F4xQ(7VIw-u~I<8k>856~Vf*Ern&U-<>W#_W*$~3?# zS#6ThQc`u0Bm%b#X>A}93FwjqP3IYI>E(A8&0dSwA4x($j_o>IcKb^GD^|0x+n+5 zc_HqfWx1bfm)BXoVB^*#x%)C(P+9)7{i9huqFB2|iG4}| z#+KrY!~>;9K~V&q1G`Tg7dg+=f2ZHXPtZR}x{Z%wIeR7I^cmAFRMubz6{iOcNHK4a zs)R=VT!IFsVIVsKgdp}D4%=?FW!b*)UfQ7#Tp?D^r7s564wW_DB~m16)CzW!J!Xpc zpEI%E9J0?@X|=O-hSb_fNJ~p4qCzH8*g->wXh=!N14|EF{{V?4Pp3a#IU5+tnV0#O zPiQdecylcU6+%=}OqhjKf?A@n76zt{5ge$>L9i%&*CT~{i`kF%lOecEt!TMY$ze(b zD+RQOOrPO#T9Ri8$7rP6+1hKFR`W88XFJPuw1DDJy+~0}Sylj)m4uXO!&HEo0H_*I z{CGM~(#XA5;9YmMo>H-nnr6N-EP8btoSG*rb0dDu|g_Ex_G-0nFCyJ9#d$ z-QT;n%o=f{V22ixv=-&P3Na)JQd9_?u~F{y+FK0O!DiwdZsSYH(4eg@I;{?+P)P)@ zONj>%7Nmd@fCDF?&Yn=_Kg2_;l@UOa!Iq-w{!oBOp@Ovz8x=)P+x9+dl72kpCSP|p zm$!-$siTKLP>?a>(^(Ig+8cFQSdD>2UT{KW`zvJZ*G)|vGGZl1l8-#I7WOWezrYS) zTdV+-;5HeofQ(7&ssiPBD&z(fYiXEsGJiAuo!V9bNAOsI=n#pa|vPH29Bg8=@^+fzlZRwSIJJQUx zSBK^bRHif1R8-Y@%oUit=WrrR?vKlDM!MXFz4?eNWLEadN`Mj+rQ!zFV}UrQNyI_( znXHmk>y9T%mPmjiaDlT8l;I~xa@%Hj^K99L-D&Y}=MPUKtF6WSxKWD}8Y8vEg^1I! z=arKs#RV0pfd2r01`Z-fKs!=^OyRU)u+xI~LP+rankQx*CN`7OX{S5%Pb6l3tYMvF zIO0;`R8b;?c}$f50HZsjl_A^_W&-1J2fw$Ap2`z&`fenGn81k=pS3_pg%416ks_>& z#I(Yg1v*q@oF~e94@D&NM?!i*)I8r?m@(SWxP^R_>KrNCC90MmTxx{eARm>#%BUO17v};=4^vKg$J%$Sza{ zbUlG5upNe+5H_tndn?`8B#m4mi_Uex@^&AGO*LjMBE>x{Nbd3&{{TY?{l){km9gVvLeQ$m?<~ZM!Yl-%c1Z%G3cO0Df)DND@iEQ#4l-nU{PM}1{$7wrw((luEs?NA{*VBhmF>HQn94`^2Ri&q-hYgCB zRc4FJka?v;NbJP^mf9Oy{1gnD)$*m1NrcCUku$(?qAP?bINCrlD%aEi>EVqOe38|B z$yL*j>kmt!!?6mP@hGY>n&|MgpB$&OidJf==4oUhKmbmpuf=p66tdD%Isn230zAHa zD9y&gh$@)a1iQ#{lMlgVlA^KXcWEVdnnz}9o&NC)t3#HzY|MS#Om=Tl-BjXK_UCF5@|b1%_yZS3*n zkChlvJyGp6TYZE_Nu!PE{{YiwKmNvjOQlTxhh*%p)Mcm2j@X(OsWlK6nplu37L$JK zAdlW6!XFiCF_&?I$rZKEdArveTDY(03;G0>mGd#oJ}>qR9WLbDbPp7Cml zV@y*A#q$0qO-i&%`=qR%s-iWDAx^dMmp_P$dOIzJ7yT7n~{q*B*-mOCuRZDaw#gKYqgrm$b%0LknedrXh zxX=T(;{H16+l0!zaO@_OcXU+!R^>d0g>=Rl@LDM7>#8dujZA2^DpiTx)(1}detHfa zWzVhE5ThbJ^s?MS{S8wVam1)oFxAtoLc=U_28{t8@$CCh6IoM9>4!JZS5>ghk7f0cswrXRB+{|XyKQ9)gilb>D z5V4T1zzbb>0xUb93-S)m?aEzIOdVW0AkkBAYFCjWgZeDJ4PR2I7^lsr%%Ef=-DyE! z$`tr%Vn`f}a}}LxS4YN>-5UY6;q+h*h-Ia`wtmUY>#sZNOqh7T-W@ z&JqZnn4Oe!de58k#&5{oHHW88YlaJi*NXV4peN+z`JXk6h@#4fr`~g*2E^&WRfV&b z&%U*Y4m+s^Mj|+LLBc2qgcOwpb#3E^#L!vPtgV~+TZLhmCNECV(c`#%J|~AcTZ0Wq zEhTJ3_Y)hUfuI19!yB8VEhIFcpbnE5=~(-L=vFZtDP~$l!ql@NNhBVzun$eWW|3KY z6`;x3-VL3rB9?l3IYf%E?KgGpechMx;X6tRRSMoudXk-zDSg$vUc0Gjhv(5pEj|$+ zofE#&$s1TOiKOhV;F1Tkg0wFQ;f)hAfXOJFcJe4MgAAd;deXR79?v8Y`9?7MxE@F# zA8yig;j?fbfz|M#0&qK+_QB z1(1mVI$cM82RFNQ?Ki&ETU{k2r0Q+OHkS)ah}M9hKvZGEM;cVxw1p=aP=x?uLE0ox zrR!_g2UmX)y!%bnyn2yxLeB(vMST`t#41fZ@Y5eX9<^!;GwhU>MG8Xvcna*xvz9wJ zw79jmd2fDc^7G3nOJJ%X4GAOwARay}aGF_}INkEvT9BD#B`p;~l!^PasEJOkh9X84 zRHF&WbhL5el$BLpb5AS<50`alkNE(DKzzSOKjCHk`8J`pQ{n|%Na3_?nlDQfueimMix{K&GqpLXfW~Zjc zvAjCCRZmMY!Xb#v?$pk#H{FOMa9-SywLPKCxnTv~^T5 z;j~i7lysCLV;pG^*r<;zYF(H2%WJy#@6O8Z9%$xima^-?&1DH%l;B8Gl%XW}NdkBQ zfEAC~&A4UNB_%LP15Drt41M(7)7;IO@w_^G!ILSfDyia%a$FWGc)(_jl#Q&b+yXQ@ z@^kNS=h;9tH3kh{PfK!za(ZFN*zIoE@jP~#s%MTu5XkYHmt&~Chy|4C?6)B`--oW9 zXZi$Btpc+PO$WT-NdwZVf1=srCiRol9y^*bTz*M$OuK>O_-zdo@3E?6sidia%?d1F zIDp)}>`D-BdvK?FtlUkiQj`*vI?9TM#DqANc)a!vxYWJ7tqXI&N>zsy5|gvbjar}J zCD4r5{Z7sqnpuC7VHglK6HhkrElkl$kfjWFxNj|(d8GId2E4+*sO{QLb7tk~Ad6Z*P zZvDs6&US8-9nu>|Qb)J&nwhSa03`5}?4{>Xe+l1FN7MapSsNF?CZk*&V(kSqlcfGb zz$cMms5e0(DJ36mn1P_aomy9CZskp>^KgZCX)7u2)F((PB6S>KK*JuY!-Q|`#o$BB zveLrz9b)AwT2QhASKaqwNRUcG`amR%b-B#mmvWL;Pmi`>%@s1v3N(`AQU`A>zea@> zHjo9)#fZOhIDKoKIHUj&&=^O6apSjbNpIT(sEJhh)P90`M9AGp>wPvs#j7!>u-c3- z7m|7A#%73uo?FDl(#&@o>813)Bc9MV!smA~rCu$TLQ7#lg%S)7pM@CY_9(i4 zLdv2K5;jns*Pl%tDXHq759#;P6nNfi%@y?N^AXYJI_jAydiAqpo#Bkw`6jQ%B_F1`Bs=T{!p|s(Gik7zz z*waWDxa#%AZ9$MAmiN9ZS|v^{P0gHZXmGt4MpqogsJr#O^^G&EQ}AiR>+ z%O|>aU5Fc$K-cPusemrxsG&?PBq*_>1yxFR(@r0OL`8w6pfq*NY+{uCVx&G<`Z z-m2ub%a}$Z2Dn4c@#46{v-!)3=2>BK1Mc^!=#`mZQWc3l>V@uig~Vz?bgZdblt`4E zXG)Ly=?D5!gyIr5M5mDMwavm(`|do-0yMTYL#iGCY zJE1*A=}u$7vTi+%Ip4DDb>Sk{QcUe6>VB%qbQv#n6;xSyXFnbmU*!rfM_mcFuy8TR2iw zOzTSg6Nb+cK_mO^xKz{FOKCPbLpVNDkO#f&-M3qhh|{-^F;6Rd5`*R|r}xO%q2)oxP5OC_b#Ff59X-K_ zS+Qx>Cy;}(IDs!bj=h4$fRYLNcq@MG7A>je>`0%$dYTV3*?mC+X`x5ecTg}~{{YmO za*jx29#zSd$%El2N!s2}+ce|@ZOeMvu*EQH`Uvab%{@M>hvZp`rBhMVF!C6V;ze+z_yfXKwxnk2N`$3$yAH(^ ztl)g=P)t3Q2**q0f2L2)h+x98Ie!b>;f3NDRW1irhS%2BHW`P+W2d78ETR}xl2v0O z%-1BaB=_W>m8iXwx`l`-aF8M(m@yqk3X=C7-Byk^e}zhqamUt=SEd}7)yX=sLDp`l zRz(&81{RnuRE3ttb*h3YnJSqTcal);4cf{_vbqhB)XS!?>5kGRtCj_T&ty``^z*jPK$EvvjYN|eK8Ohkz%BZK331g^+ znn|FRnn;;m2aZJyjEopC2X`f1&AGeX+xD(d;d6(lJIK!Oq)P$?)lq@_UW2O1l+ z>Mq?&K>#623DP#5UK~#nW{G#<8|!zkd9%{4U+Gs6hUg~bLr3R6hPG>DI_HeCu9LmzKp$pbt5rm z+DwO_ z4Oa`+WA=(z60nd`M2lXF{Y-Up)Xsm;^gT}MRZdD?mSe%2?<1 z{{Ruocp}m@KhM^tKJuD$mkX(j=V7WZADLHD_ESxU>c>JDiR1(2i{9er9fl*k~N z1gM&>-%J^Er1ScJ>kp;gto2{~*7Y+0%$SxLiPuk#OGQbE;nXN=BYOH$#?b>TMv3kiZ!_1-A3ezBWNFhX%{9!5>1?&njj=2=(8-kl_#9TJm zRlDNdC8DAll0=|^AeF2kz+rI#Mqp_!{(ya1bv~1(%a!ncuh(OJLm7-@e2vpHi%c-t zk&xEY)z-9g(#s7Dbp%UIQ5{5X^X*9sF6HE%*`7;c*ixT;DO!-?T1vrnpi%>}S_veT zu0T-Gge5A{r71xmzkIhPyLVi9R;q5!+%%_ML#`#&EpC+-nk}zN5Zb_6z)FIgP+CHM z<9h!9@SQJB9cA?Q*DUANT;G}@%^7#9EsNo^$x{_wHYpx4h1IoA`pSCE&cdPxnS+-u zLaUKy1oMkM&uy$bLUVQ9LeTpyzS@*P4ZO?krR_)oYtxHJAQdYG9}yteRQ~|8)>eD5 zXLo9{mAK0{3S&Y;XiJ4ihMh{K!i9}4g*Jh#sHB)8tA9520+-UyUb=^n@yc12izoF8 zqOqC^t)_e{6BXEO>!Sh9sbwo>^v8@(|;e!rY-r#V@kz0!hL@ zXp}9rs&PtzGy~tCr^_zV?3H_R8Bp-)3rwhY#UW~uh!{Z~Frl)ISEK&`#9JH87=1+s zX@RP0zpB`t88e9p^RXY5Pcowa0P$SaFf;8PjE35CvK!gi)tl%;*2)Aa(+5oHXHuoV zG~%AUBc{27n*A@P(JTCbP)gXkwjxSM?-SwFq4z@22{=s6U5`h-T-0OJVYroR#}rV| z(^rwU-sJR66GjOqQdApv_VWz4n{krM%&7rHrRBHnN{A;7g8@A;TFARA-W;8d{lz6k zC~T!ENty1$PNb94Ac)#WNvT~a^=CC!5G1V(QkM{|rfCK48aczG5!@h22hunL9h*6C zXj@3q>Qr1$35BeHIC#X4fi)pzot0-+$2?=Y7b?{A#9_w2QziJh%&>@7Sp5;*xV#7O$giF zJeLG)3DPi{n|Gge&ERU~j}p{?m6^s+a8cl7Ks|WSfu22E~0J8XhSzh@gx+5AL0o<8SBzu^@CB(zCgU(t)&Gv<0=6_kKtNm zDJO^|97mSgsw~gfdH{*dzi_etqEowHNJTd{2F5#AsbAQ2=^*q?3$@R3IU0MM7J3O=aSXN;GO zAD5_w@cddDP{64hO(jJ{Ogk)~A#i_uU&ox_`pE3at95@g%1X-zypgtBP*F+i4XMaI z6)Wz;2)DZoAV#b-@Wfz8Q6m%6MX&K9&K{B}^M*~wGe1aiezWIFYSSGC7bYe0xJ+uS zrlqSP3n$D((Ofm6a~TTO9N{Nr){O=hg*S2E6@sLdq#?kQ;0Opwa}gl;k+W`+K?ZMU zX1SJKdT!WTR=x9K8ry`aZH4PCxuF5#m0~3>x1^Z_krYqxe^@@HI(u1Bk#de->5oKk z1fhC2jtF6VMp{_vO;s^^nyD1EMJ4v6j}L3M-PX59cXxEV#E_<1WikN@P*aLdtw{AxaZ4V*wBy=HOelVdtEAYD$u&6vm)eu2i$FWoc9f-31HKl%+(U6*J|JShyEc zI=6`B-&6fk&Rtc(>S~RA_#Ra?G_lU}(|I0j6%-ND)2V=ky`4~@Ac9H0LEB|bwc&0S zqT)`a0{~(P#t>C8wlKg!Ggr;`bGD$2S+MN^69dbFNcs;TGS4koA;c3F1VKGsddU97(!B+^&JBNhyu&AtK7*1T->N?KuWY145+J8pFwd*OHPpuz-`9#f})aDq-5&9 zt#4m)PZe)gGrnHwjSeA-QP;(XWlBmz+)JfPJ>YsZcTI;9od{YRU^E+A6M!jL3Np0P3ANo92p{>gwVxBi>O2QHbfH^B(2ZZ+%Gw>&<3Xtho-hmkb$_ zCvF>Dh@Ox!sY@^2{J$woGTT7ld?-LNnT1M0RDwy>t5lMrN{KXu%5=D0P8SXz(XNBn zRALpi4@pZ=iOm%%ywV-fBbbq#7F|M?2II#3DFqEAq^D$`64atR(%4AD&V_H?v=gnu zFc_5>fH?SxFe|Zx`n|2esqt)Q7|Pu@q>`$$50nU?T8O2M$&gh1+?&yW)n3I~+E|_} zUBcQ>0EEhag(*%PCseEOqG5g)DQpt}D*&S)>>$7g%6#Y{t8SbwCq+fp?@*YnM5U#Y zu8Rn%l6Q$!O2cUAg2w46zu9B8Nd4<@w&B9EbvUIDH7IkX)-DN>Y334Zv45xq#KdOBO8!SV`xT3X+w;H3*FA zVkp~XKpfe@1W)H}JNq=d-i=yEcdbE00jm@Qr8+@{P8xv(j4R2`v&U3ZW0tniOJIWY zy1UJxJ=@7iX-P~ZtGrWdAy^3#Lac6^@Hgp(YRtGrMr6+2XQr*d;gbTzDe2}FG+4&j z1kqJRP+*RD!6_oiuz~NTn@g0XZxFE36tW;8N)56n8CEh>fFlB#BoUj9s;G#y_Ui7Q+4#*uW$8v6R^pojIl9w=H7+p>q zi>5Hh*j6rP5!$6AF~(w=IT4u}<@UQq+FOt24qO$Ikjfee(gK3rIV|4xEg4DI4$TsUFC;%H-B_Jh3!VZ+FAb_exX3xZ<*A^$!nEF*FCy_dD zmhik)@oGvjQw)`OeCtxxaHS-$ZmLD5mA^o{>=bNb%clW+ip%vVA_%SMpP7a68eO-h- z=Z>=VLAsxqJcOreuauGl1W9&Ck)!}J1Fe7n5=icO)9lhK#VK;O zh)SVKB+i8a8zDFhC|P@@z>=LKfC&*GaVPkXStRtDReEU5nO`Wwn(8qOI|Ho5RwQT} z7p8iKja^DfBnk%C5w_QT#1Ude#m72LzAZSg){@{(pcES*dZ@@Tw`a1d%Rp`S()Sd| zxgV>Q@%0ZeLtl($TFQEMl@cL_(JXMrNO@bd(PsX&!|_z{M{F!1qB0(X|!hZ1yw0Bqw2 zY3tx8CvFjwN)lRsf|;JEfFm%o+M zQPW}=E-MGjOHURt6lx{|do)*OJJZXO#^ijc+HT#8R>-t{C2O;J+gDpDLI##yGBvak zt$`u6sI6rRB%~HlxwjZLW*hYY23H-Ts%&w|aeT|q{GjY@G-sFS3Q@nB#)2V4-Ml8ywb$?t43(yYrpX`sWp05^`@ zB?wwTN*{XJR?n^A;!4;WNC_)KwO~@X=*}bfu=UfU{Z90;(_Vq$m3R!8rDbL%9y>^C zGX@Z~@-<{pM_pSunysQF$pu3zup?+~091v?ZJ2(^wl!@l9my+3prVwGMJg(R;MN>; z{mD3rRNap4W_Nb?>b|(YxCw2?-eTMH3UzFd(w6g@6!o)f)1l@8@h4UgwQ9WnkbWOu zi;t=PjAaaG)JIt2!43qJ^>`gP!=p;-X%aIMNj&hZawS5g)SbruAnVAL=eLu37-`l5 zQqoiwj`7~<(xl2l&vwyVq)+!nYsAQsXD>2s-pSIk;w_z9VYM{Ze(7og@G#lX~&|G;?1{^X6L4p0j;PRpK~)Cgzh6ucowktpz*o*)(f+l1fne zNEW~XNmIiM?(W**w{EW5b<&`RN>p5Rq>!jkZ(gF<*kLKtGL)T^9@ClHH11nrmRbPd z{J=@?Zkt(bgebU|kezoO+5LzP%CxB-945Z=T{q!l(f+2;bXTr@XU;up=;RcR^ikop zlEV09Pn`O5R;gjo5{BAMqqj{d2Nsce-XV~}#1s;c>Q)K}DJeAV>V17L;N56! zQ_?8KrN|!awCRkpnw8qXv}KT+F58Q-Hy;j8nKFggaV@E9N>vF{iAq<91{J3R20&B- zL~0W>J+igTtnC_3aUYsG^}#`u1)k|j?!a%nEysDFXx0f%2B11&xpNl9xBO}6N`aL~jq-$iQ&^ieBkDVvF^_F0y z>O*DMt4Bn1kBZN!+mFl9&lpr>p}f z+^=>t3EivS<1$l!(m4MBoFozIHc_L)V{(G0%?=2-Hrhcx1P|UG-g8G)Wg>+rY2cd7 z-ra9|{{Vl{#RyzY6S~~fv=K01sz|rC+WTxiKOQa$nj>3rPt=B3fCxz%k=P%n==gE) zVu}`+r3_B9q1|h?x(}}WxyF$Z71cb;0N8bJZM3!ZH~4!vl%}X@)K|`>QGxnx_aD2A z<4h=1j8(2JxM}S=czZbTq)QZ`ps$_d+9WIBbnx~advSAQiY`#6Wu8Dn-0N$0*NcIq zs;4i~m1bgGdryxQV-%j6>m6KbqU3nn==;7rFIm+}P-2P)sGPWQT)gr|PU!AzJOBqn z?fN(wyCt}ezjaA@Ymy?Xi_r&AE3zkAvo}hsCfnz$)KRM&T~zt8fI9El^;*BLuR%j#UDp<2xN}7^crDQBZ?kllIfT$eC3;fwPulGxE6^sHpIKUeu zduyXjs6bAT6T$>Q@}jBzNQ?Tzs}QSqcWDmdZdmKgptH3Nh}m41&$Ff6tddE`r)>aJ8WzMpV;Yyppou1)rc!>) zFvinNezZ~t)5Z5nEi|H$CjbXoAPWaLK)rI;w&s|Eu zDa82y09mtkAq6CIqW+Hx!xYm~O#w@P3_Rv_b~Kt%L~YErbGqg8X)j*E3+TLJ0TLCW<~&`<@c#3wBq87r!7xkOun zg9-o_TPC*DUxzF$6W&P2iQor7>!k?2PJ-Ii2ZBV#%rz0itByPQSMWiTQ(1R6iC4{CIn-E zFa-M4T#4yxuDDYrS#?-@EO+g|5E#0q`3+JZ!q2Et@*QJsT; z>!DjYlS+DZC;$n^1dKGLCyD9Vg$bC?MSVwLcr+i?x+&@14?e8bldR~ z%vk;>Ub&|k`TEqPt;K3z9GMmCWL?p~R7y}sO%S*Wp+|@$4o1kz>~gzCt!&VQ29pp0 z@Z+!(&^DeYZ424nG~V1P>w;7kq7n!b3BytACjbt?5kN*&$iA!dZfLGd$(U+u=;M`< z4D~efgYwkoS)RpicM=p6?IQdjb;KStGgIuPA`t}j9w!fF23T)Oy4j0##}?`zQ7~*S zrRmmHqE|4+#xR`?DI&|r|69LZ7@6^Jr~0BB1a7AEBTpm4hDHD=Z%nJ0ie#UG~Sk@l%wcysAO zU!{*rBQN@(!!z%woFlZg)Z+6&1PePnAhg^Fq zh&r)bjV@fO#eB-Dnt?n%^VCl|Q{DFh##Uv$)CC_6d72hh?6$dSw$X?1Aqn^ZXsN}O zfR(7Lh9sGwn=R617rlY9@FhVR}CK5t8N_QMJ_2pUK|F& zT>e`iPO;5PK@5e#9{94B9m8pH+rx;+S50gc^qLlWTj}o=>TW57WgLx!97{3gI+0IB zMMR%%na6(0sDoJ~W3^Ng-ME20<-?(-!BU98FJ}*^Rk4+S`3dW$olYGReT3Dko+AshI?F|jj zP4^9(Y?CQNR|!g#=~|p13{pu*LWvSU36NwAP8?4oJ5A4Tw}UlVveescrLfs5P*_%w zqOBmpWT*m|B=qpBO3EIWeK*BHONh|qdijDly=4!Ud3Ux)XnE~w^e%PFxE#32Y#mOL)F&JgrKBE!Mxv4j2@pCePs_8c z#f^^4N8E%gj+{zlYU7SOW}5n`_;zLPv-IBr>3(I;8J>K41~QF{8)R zjN9u&DdlWSA>et_2FK~9p;}5RylV)ZYG}$pVO_G(IP-_^lOQ%e!N~gCbwN5+aH5os zEu_ytBq$i^_f*2xeR8B}LJ}tf;y4bh4m}(?Xe!H{H1#ir_2UETmT9KJF^DqV8q;C8 zUKfhgQF$9_1tc<~RYuBODV9fLt2Cz815|mkO^XKApqB~6s}vke#yYq~EVQBwNpC?p3eAVPE!A&(XWqJx4ddS|rYClM0`Lhzr6evh;EWc%)i#6;m zDsF{}RLImLW}poCh9@2{a2yWPK#a-fTU(BQ5m5=B7LkH>_3e?cU@E%$BS?Z%TH8oC=$x~H9LarvPscBujvY9bXZ?L!KG+%uQfI}a zY!YTMG&FRV8_QG~O1~Mw@G3kWTBc<~BRyNP#o3V50u_lm05u$tGQ=T<6s;*ri8!1| zk3F73qCMn8k6fj)wJjhF2ZRExv!uzxi8xiV<chaJHRABovt#%1FSOgIxBx?LRWIb=y?7 z+pHzkcVR(6P?btXq0mH+X{>o;s5qbDu|w33l=Mu|Vl@3q%L#*G*o?Ff4Ait$k_lvv znWB&)OC)iGXK=~^7EQn&LA%G6+wSY=wnUPGm(viCmH3i1ClH~h6p&Iu>LeVI-7V<5 z-s@%EypWAycH}6R2}Go;O0d%^5J3tAPZ%J#<2b+Rp~YnRiem8ZCBTtyA|0woxKIOV zJKM)jM=Cmu^w9D&;41XL;XEBTrs|KcJTEgEXlkO!ST-w)I~7+8P|&U)O6hyquRD;# zUjc3acfn*?B{71W6aHu-_0`X^1)+Sq9_ z?@uXk$_lAxC?TY-#-pi{8j0Q5Dk@7gIcGN5EZPltW02*Fb0K^q?|Mo{_=G?Mi7-GP z#9&db@n+~oe%W-6?UL9eV-Pi{n4h;;QRoRLg=uT*gRHV-KUdvDrNknk%+ldF{v(GR zQjZXr8HF7|fK5qVOv-$=k~Vc=r@UAYb>~K`a>RZ?l$jcvLDHnb5|A{hCu9K{P9lce zv0{eu)|+`KS%oP?r78t$T9j4^26aq@3`m1CHu`P#yVYKnX52rkJwC*-{I@n%p_dhf zlOLN9rGj>I5vXiC5i-Q_qDpqxVsX|P0O{)0>!gL1*j;bERdKH;R?nM((0q%GtUX zqB!ngz^J8Kh|Fi@{NI?7*(TfWJYWz{y2?QY#{7tLln|EMU-7yD>(XTWC?jCtY0HPv zk9NY8HXKw8L~*Ot#d<^2dd$-u7Dma~_E?^-X`zNpx0-4pM^z-NEC!*VLR4I?-)*!U z5w9;oBm}sQv@Q=%10IoBUfyi$pL&q9gohgkZ<=S;XtL+*vm{xPT#-%J+U&WHHA7P_ z2cGHh+Nm9mp=r$V!Se~I)g)_uJO^C3vEdJ`B`3A2aiGtsJynbR$YLEijViIE#&Ho{&%{_4GT?QjI7l72_*sL^@ z%@S0>3@a5!IR0JwENZYoPHU6M-Oi`7>qQ=xlZ034uR$cbJh)1{<@$vDuHhXZ)jwaoa z{%XEUr7v!NSg6pY$>~tp)rA{gl4LH4=ls6eroXS4W?rMCT34+vmvK4Tj!K}+kjoS? zT)5i9ON~3*UK@_q^Q*R2`wUvTmh^>=>ENNL7y?`xwjZ{7O+%NK%-db2(c3o%cop5a zr<*BQK> zmFki&=@>561nYlq12#Rpxat903{YPGUFNdx*mgq4j!?7B`Vu#9b zib|zB4>A0(;Je#k1fLEjzxsoI*`+PJOLb@qBA)W$XIQc$pwYM4Qm6$4t-H( z8EOH3%Go5CN$*@KG9&{bi1q8EgG=~i_2(jWLoeX? zR!Yq{-d9wln=#XE!fEk(DtUJ-twTFYB{f;NVt`nXHn6!IjxIi{?ynHyS7O2)2_+x3 zbx0>2Do{`Gk|2SI^QRf?>n*=?{ISVMLASUP8uf2E{tYihR#nK8YcxGQ`t9m}nflqvRA(H{mtX{BpZFXRg0v)H2e?)NJ>SW(pUT zN9pk5yC^CX*o_EX4xrp~oOcA-6V6&!fR z8!F^FjY0FcAj{>vvs4&618>om+{a(_e~&QQ{%}D4jy}JoOyL-L)d7AdS;r8f^hMIl z3Y@W%Hs|cwiVzR`g(PhRS1bFvfDdhT=2~`8$TvYr;M=N?@syNFJUXf(-lP6Q9V;i< zRUeK=4jnY;Y$ZVaBdM z{u3{hC?Uz+OU9+yRpv*5!e7cL87fvLvy2$L+*xB5Lo$s}wo=ODaLi;uA(u-trg=F*c+YH%O0 zY&e6&Y#v9Zm?y=$i!BTiPn4-*o#-m%k}c>~I@EhpQ|`CCuD2}1w-uxgCyyueq&?&1 zAeMybB#9U-9}0Yk+G#0+;=O8;Y79nPw}&Nj;ZsW@k_sj#=7d^5H&ziC{o?jF`gp%e zc4{#`?w`_-AI4+7$AMvTy_4=7d!{URe1e<%%9 z_dI3*J8+>o9eAS@jaqha)x-nQ&}c2q_~%rnpAy3;aJpKA7*tZy7mXQzm^*%wCj{Io zEsw{7YkuefsYDsZKcmw`cLv~<1f?Ws1vC9Q#2%n39vr=6n<&jB5n+&!s<9ap{nOm@ zOo4Q;_pAqfIH(pi3Dx>=rc^GpmbyHxJM!vtxS!pTEva&`t-4}b6 zUgQD|hjZJCSs<)!iJw7Nds1348nnQH{6s*3=fjT5(z_S@LVEjA>JKqxJfDT(`LcXx z9mJjrbi;8fN}7P~@_>rS%%DUsV{iZ`w*uKt=Ck=GmEJ29m0~!lMOdFR=|YC{735%A zJdg_@Aw-zO0jQpgPR+b1&3cga0qD%;%rhucVpLhb2Fw|A3d9!^qQ>cI=7w6Z#(Ei6 zL>6j!Q)>fewv3~<7vz~XWo|XMtuS^eI8PV{qhyadFMBz)y-7>yMC^b_F^5h#96AhP zg#@%7n!Pwu;@D46y*G6$`ionKPS}f3r^{CvWt{DiU=Yu};6>bCCPq?7xH@uZvd!GK zgx#fI<0T-+_`^^#f4v8;qZ`{$^reJIJQX9@W8X#(3F_}c@Qk&OW$CH#yc)k7rI5Q4%zeaoU_?+rnrzt0#2< zrCt+=nU5uL9{Q)wsAjA#g9yU#wA)`*HB_q!9`H#45&708{{Z5(`}emby94wr}-$Oa>EE+N-#N?uR6TayrsE9Eev=;-9Wr+spE3QwrglJr)Ao&kvYi$fw zQ&KpFkj-GlAqK_R0kkWTV`F_zp59K0b}5x2qh%^w)ri+rOPDaGppH_ij?yflfYGA? zPK61+x@+Ohcd{|BDFHhT3ug+5&$YwGs03qm_NejQVf=Yrb5sJ02dzvVqKBn8OjH3; z=fu)53Ry~(Hza=>8*ojQDC$>`_|nE(@q24t4y@-&d^11FwCNnLNX1~1~3R|4qI zR>30!(IaP_2o<&{z~t_!)Z#Ta^Ho`FTgKwn8h1Axtz+TIF3UA9^im?`lN2|4mB4Y_ zUl+=6g`|QyOe+nZs32>5)gEN4CBMQf;2lqe_zTaPQ?3OKgKzq5N6v|@)*(mx^?WEl z=}uzIi`5)RLHzDBob0gjvA5= zz|?VZnErmzFNBo-(lo1Yfoe~_By}1#9SOx~`Vp8j!HA_DE+f-C%A_nJXsX(_og)!B z{{V6mNEGe|axfM)zX|uFB|!|O2qYzKx(Fu)36&BskMB+gWd*zCT_4&RAz%&$0m3?C zriag5`1W4To|QTon+0muR%Py;cD0(FIB_41PtTakMUqpebd@HWg=*IjXc4z8k_c8SGO72j zKFA~U;H^wJfu~Bkb{a2j=G47X>SAOhKho6_sic(iom+ z8<^~kf~g=e1pSe(al=*)+^8XxlA}L#fdCV<;5K}zHRfq=mp9(Luo4IoJVr?XU@?g} zo)m%0`4bn$G8Hu(*u*$>bv;c*N(h)p&m8cAsdYZuR^Xk9!^fuUjhx9XKCeieGJVLPDV6Ht@hvlB)H`)U30H;@NVe z6{?atoMx&@sG^%2jP-iT0Uj4p$x@VtU-N-W4nlyxl?46cd= z!D7y!Te!ra;a0Lt1IdK8Z+D**cet1^!9*y=wDzi&<-)xM(oAnDyL0gRqIQ$(1H~zMk8hf z9lm>L!zpBfm48Jl_*UEh0EU-M@T{ZhudCTJG&Mys)6A}oWfEo%tnXG0O4l=Tk;Q)ai zB&fj#MC{oFdeVoeu*-;LTuBsy?MGCta0y^xVcXlSuiKok$=L2ndL=(9%lDV4kUGGt z!i&>aMsp9L>PoYQOlONDQcDcKH&hMMjb0@y=WSq)zhsMiEzb1j*@Kr>E}-ctTPjRK ze%|W{F*CCnlha(0%eOkggtvZ_tUlOF!Od&?%f2Z|Q9%=^6zPF705MvSXFL@QQ`bmB z%x^3EyM5OCLqVzf2W{{o=!8#V1y8ntm`QN0RntP1ra}JI*6Sjf>-&t z$q-*5YB+?Yuu7DuBqso1DkD+APBpU+M=E~}{{X>T(|t~4%h-(`an9J|OEj`jG!+=m zJ&8IQS~%1(5JJDc>{cj{YE*r!<6|dXf)i@O7YZp)^qh2z0m1|%NlHXE+GR>IRHM&a zy6MdRWB~qnuPP6>~P$r?(NxaK(vySg_u!FZWfhFQc8(Ut5Br24|<^Er&4WK z(0}2@hk9X>qph8H%@ti!>qcRn@eF4%Vsa$u4P3uzC~3#&p;%M&QSBCu1(Lv?M%jjJ zyM%sO1woXOQV7$x3;+NmMjz5Cz@0uCma^QP4%{a&yY9R6{{VAkwFety%<5XyNw~Nt z6}X~Mm12NM3#&hTe-Mp}Rnr+sI+BdH`o{sH*(YI-QBv{E9G?<(beJNbQR1|i&L2HI zl+O@kl0S9t_LPpyIH7E*g#r`~AnfZDiHo#ewxpC4$WXw}(0Xd4zZHCiPt;Gsb2z|} znu)ONB99S;SwLlyf^i`?9gUES@gDXxU2g3H0n(*y{((!L{XY5(Ze_r;R#S2bI$mK1 z4hsumQh&~`pWRx$H8`3CP)f#Flcn69yIWD%>3{CSeNt<#s|5$jhmMh-M;#}@Kc437 z@rvQOvmd6cr>us90Gg(JG6@F39V?a)Ni45o&v9io@F#$*)y(fRQEJ-VwX%Ye3f%|} zC}ZOgR1!KkoN4w2rJ&TckhKG`B$V|I6W2*hCmQ@MvUvGgESJd#Rc@tyejl%E0(rZ735QHjpZd%veX+ zZjbYcKHAt*((ZDSld5@(quHUU@cFPjH!9S@QHK!(lG4}1BT|V9*felP1aKQ0N1-Q? zZ)Y36jQY{n)b+{-dl1{Dv8x?Kh%%$Z(SG-4#>M8)lr*md%F(FD06GU%SM7IK6+Ja| z_cr1gQz`!dIm&sqpADj=ToRe1vQ_MQy2#v@mTBXCBvPW{y2; ztx$Xsgw%VM@2V8|{L^hE1tzZaf27a85ehvcX4)6t?=Dw#omkAsl1>_o&s7#?H}>Jwmm6Buh?3!f93vPJz(riArbW!S&sJf} zb-0XgPmNJxG!BgjRWDNuM;Ln@Que>JTyk37vi?zi)x*yBfh!mUB?KOjK{(-uT`+DM zSRL9541=ptQ4n^Hv9xi*sz=jzsxMBSvHt)Z`C!bs39@ZHHU}yQRXePnLFd!6=5)voAVFEO}o^j%!I%2wUVa_3M|TN=-L zu$zwUPJ|o**isZ~SI90e?4P>0zIDa;Qrm7VN?K5qt6*7>l`cxq2?~WQ0X1pebLnrO z+@bh@<>@-X21?7=)8P2*_~sLe;#BmoO&+_D5}C{la1prgc{A>a_Sf(Ru+Nr0n?BMJijOjCMK z>mQ`d=bpVIeAa8m=z51qm}~KzkwrUZIv+n8S@BF)4y;F7kXn%{JesiPDUOkXN`Nfv zle7NPU*2S1UKcI9yEV2SzPavg-Fx!N?iyN`1#T(DBU@m1jm)~Fi6qlLAIogmb1}D2 zvwZ-eJ=rZf5J4*dCr$AFv&|m^Hkz8E5>TtVy=y}ysht;@uPWn8-F)pmd14J)^4LQf4yr=$* z05nt;-IQuefSoDDI)`~Bz1H(I>g^$2(L$VAQ*E?{)gb`5;*x}*8Aw8m35_BRRTrTz zRsR5ok3uuYPcW}guSbI7`8%XjY8oVz>JjK?Nol4`sjLX_r7D^`>!hUBK!WNA>H zGJ~`Y(B6FYo2PQEYeV^>Zkbvx5|sW}TL9bXm4KGZl2;I^0YM4^gUnnm!sqg33h$w- zaL@qwhyb)UrAb?bGY7jM>y-nFTkt-@y7lQh@owp!1=cJd8OynUGgW3K!ssz3mMHw3 zQW*t3M0BP`fn?euM`XCM3K@luGcMyj%d<9_%&eVh)!SUzCHEVGK<^UEp-X_Gm~m^mf_1@h9qS zW+9qzjJtwWW=s}_c`E9FsiACsg(suLC8lc$F!?K!<>Vmljo3+Tp@{28(>_6MmsvWy zhF!Q)ZgV2rX;19bhHl9SO2>&e2yBNEKGgxIX%i1Cdy$kjlorCRN>mtFJ!071Hij?q(Q+@U0IM)c3N98NI-j-rf)7KTrHDV43Nvv`Bf z?6v+|m0Mp}u&>KpDN9&TlFHPn4iD)jLXcB95ISjl-Jz=GrZ4T<{fmhSbth^u!B|Y} zAx4cZUiD}?d73e-lZiuy!$pDDWr{jl$6q{GQdCpBRMW`6XV0fLeYUxd>@RC@A9uN9 zHEE~Qtf|D@ET`@6)|CK-gSSe=iQud-nm%)R5q<#;%WDeR!Vcb?W7`q5!D#3gS3O|o zKToZI;W=k9*J8DGQ@uXg86r@tC}=M81XCDLJ>u7}we4<7`^A%FmN}4hZ!nZ4AS=cR zk|9_oOwRx~%>(W;B&j5Vkuwt-qHqz;6foePoqcEGIsX6(%$bu6q@}}fs(SiZ>FTQ! z<`Rn#b5$h^5?H)(Rt@yvpKvn^fO!tC{{VNbLY!r5Q>s65QQ;&&oB)YP8nD~bQSwxT zYSIY=k^v$-U&1;P4kL(@Mkf#S&(w;1HXLge%oNyL%%3kLO!CdEk^#IMzQS z!%Wf18H6ZltbOQaX^A2e*@b~4LB{R(mhZ$+*aXNku{~e`_jDc=PU*q5N6-QI)9pTe z>0d@OWj1>l_8);s84%0`Z8anlQp;tT3_kAtpj}&WDn^4|W4`*iX?d1i+U5@=2N-of zwRaSff(DSKLPC+}WR=R;KT`Tt(_CJ%n+>kP z>l+)#>LQQL3nHUIGzhN38lrZ)yRlsu4s~;KH(u*0VM|q$=#ms4cm#pKgpDJ@so~X) zVP0bRxKJ9#!-9T3VyrT&F?HWB^%6J6^L|0;R5+Fl$Y_>G>LfA6D3Gj1X1ubfV{k^$ zI}OK@Hlt|dT&=e7`#~NkJP0I-8%gpMTFMfn{>Uj^WI@N-G=Rlx`Z=C4YD~YGdcU5! zky~9*l=0zNTMDY%QZ^qjQTak7lAs#|h${vgiO^q&Z|)lkB?#0aM1>L6fhiDtys0(K z!?sPS)hVWskV=-d1cd(pjiekpOw7O-(5cbSN_F`3*nC|k^re}x{8ti-7N&<0&NziO z6AY8msWM3vbI8vXWi_{XOA4CQ;5{B0-+EmL!&SL3TO7NPz3X>gx zq>EiuSp_2q*(v0dBr8`D`$)Im_E1gDqfEUMHAt* z^psgv7-?y-Q8O!6)3K*X1QoRDa0zt^c8y6Zz-n{za!MQ2vmhjdxuHY&i7V2S1ne55 zD3Ec*A!)nbdz62Z+1lHXh(eqzDKoVst3!>J=3z~(E+`lwID*ZNbrbNMz_Gk$PKR{M zI(2^$hZw^vaGXaQHF8HS3~G&ELyAQsZ7U((khwx^%3S-FCv4qZy0M`uNCY1mkPd(c zg+a8CO3tqmN=j3w83ZW>?(Od;U=)`#K+q$@-87Iy&ZM}6Bqd5X0OL-hNCpyAW|JAO z@e3U{dZW-zi)9X&(npyf%(yjPCsRsmFw+{SICzmsl3Gb@+t8|zueEl74;H1Hf~{`4 ziPjc2sHaE)C<{>}wjxRtf)t`mfdDe+Wj2|PqkjF}#-xPlE~o^@1gMp%XxS-rE=od_ zP9lmgQa=@sQ@PH6vQ~bCg@9NKKn%DiEZ(DoMbAN@O4}Nh#En zB!s|BK%$|X{aMAFaSE!u^_a7kaICM9rK>f#n$pEmy)mO5U_KKG=uC~3c!vw9x4LYOKXIDje!jfdBe91M@^<~y7SS6#&*t9u* z2}akC3!$Z@8g~GyG=onK*YUYL+7PDp6OA-iyLfbK9 z+8unPsuTho1QdTx5~2nmZKFq>aX(M^52h@!gHh+av0v02tC_0s*|5A10i0A~G;db$ zny=@~_N$~=_RkZt0^-O$<++(VDO)?So?7NAby~kM-L0i1T6?Dkj`zGC7{&q!1PpjV z$BoWLe0Q05uUcNF%Hfur3%I!OGOp|rKPnTYr*%t9Y$%X?SR~dgmz;A~Omh@D&nQTd z)~q!UD@zherZ*d0v}V^J>F_qcK8Z72v8(hJUIeCR0|ryD*HF^P*+LdW>XsjzD=M(w zu~XIKb@+tQCLJHn3OX31llQ8`VM3s5SPL)ik=u~&ZTH7Jd*`rdz)RndrN_(`G zFTH~!N`BY}g+{rK>)z(hcbRBWRG_X%LU1A$6k#w#r9hl%8=n6F1ixE72kG>ERqNyB ze3gaIC!B*2$D^LAMomeMo+#O+kPTf>xwfaVJjEvdv3E5JK(H5=9r2b_Ey@t+NsjR) zWDtOSB&{jO2&rE4b?$CKK}twS@sOZGCxJM6X^?tono;!s0MnjN>Xdk18(EpUr-at1 zlCFmY!)3#3K5a$9Q%=h-nHo7IilW^`wB>HTr>?J4{!M1vK}rQh$F(W}$4WqeP7ykQ z#{*dLn`9Rj){iL{Hr9@{q$T%?TxAI-66y&~f<_4nJ|aX4J>5O(pQ-%u&^*`atD?S{ z;KwlR9a@!fYWzBCtiglQBO01m>f6gfEmQ@I#=%zh1SPM05zMa_yeqtXu!k3N>2=o; zY)g%mK++sUXz-!|B7Xb`!8qfdeI2YZ#FYy7pduu}3= zl2A&i|T>8GhYLYjjpW!wt7jvNm*VU&~8thdrmkK}v} z^1oAkO5&A%QiPTvndxbxdk*q6AtWr{y=J-b*O-HAy4gjl9cJe`X&T80QUs2g&l0T7@Rt*9009c_k`GiJI03-L5Z_iAEATt&HbJY(dFwM%V;J=j4+T)D z#Ib42%0ViNzE5^rZD0t{n`>?lGIsJTn%o?ncj|pRREuuux5(*Bs6avqIPQCy)F83#p$y?4^|?q z!?D_V<-zfIBvT)k3P`Ox$aFC{MP(!g1lV&dpUf%6btVU~gFI{TyF2B4lTPd=8<8oYe3PO^!yp0XAwwO=~OYN!HC?iQp1w^EN zDLq@u-FBnFGoB0S;Pf@AWQ<7bO;Hk7BZC-LGQkXX8Ug~bCdT8pC+*tIn7Yg%qy__x z5uh)^;*dcKN&*m&QX~?ADh5@sP;+xFZ5Yd+YRdNB@eR1zf-RKeh_(bNDuq1jt^~Yv z$ib~>l=zgXtuvpq1!=&c6wm>L;dS^-(l+N6bhS4-T?rdyfFE?Ju^NGXP449AxOZ9D zQc_2rI2w}?e5RWT8$pnN8co*LW4M(T35Vm-HAGkiAIMRXs;;!`<<%uUn5ibj>H*hY zE@LS}Dhd-IY4aQ>gw-CsTj|oMiILU%R?MI9ot~sqRvxDMbi`y^*1--ZPaf-=GMHts zJ+_;DJchUb04YV~qSCM8PY)uK?urLE>aA{2_~C?fkYszR*|49Qr>UC^sM2bA8Ya`m zHrsMOu5b-#EhwP>00|@5VzXo{Is(SR0Un}haZb+A{J9zpYz~+2e}Ur~sWBA$NKxZ4 zB7*7(xFj0^f3IHrRE5!Fh?<`eMi(O2ztwwOdpNl&nkaF)p8@jDpqpQ|mOlxH@0GzC3&iLaLY_PipC7f8lOAO(%+OssctV#{U2x zj}!gXaA+jz9uzSw5_)~NZG?kuK^>0^E}AM#jubDjcS(w%uBT#e(XUk*U#QWql?>Aw zN~T`S5v~gpp}I2amGZF3g&{{R%D z$dQM?3JAJu>PrB~UY7bVm@>XisLh!xIISKBi`3A@WqcXtPnTw^f;D$4WxBQYfvwv1 z2b-5R$#UlCEm{qIyGg|f%|IY;@7u>Sxy zzEAar`^WpkYkw{Ct^P~rJJYw0G^-az5f9E=h?IPx_tEG=SSL(&JoX~*ZfPQUlYE^<^V>?AWuZ$K9fF_p22434^l%#ECA63;mbE}nl=x=UPF z<+@{+XfWx0)h29Cbv5L*Aej;mQG@NFN{glRIPXjG zY*Jb|Ub`{NB%4-JyHV{L+TUeXFm>P}=Q+AcRiys_yvhC4u{P|q>Q4mo@t|iU`f};5 z23?Y!C`#R=5;IQwnOOV4Hh`01;mD-#Ez}zvka7p zo8DEakym01DHhb+>8AtlZyn|yA^wz5irU!($)_x#>4&3PV>bibIfLp!bxpBo3pmdMujkGsv(LLCaw48Xw5r4$P1?dN-j*a3tCrz-{!*Lu> z3T!kvsFqh)@hYJuOQ36oXNDHs-N-iW$wP8ne>NrigCQ#sgievO4WJW63%5_^kkWPm zsa~IK(5>kI0HnC)LiDqfI(bPzl2ujV$%s}DvQ}F1YMrEG*nsN4K;+eOq<~hqPNH`C z!1oFX-aFsEr3_%ej;tzQtxTy;k$od%zLn1jj;A)}8ti_eA_zY#M;N7~EC#z-x3<39 z^9-_GInMZBU$%8OXK2lu6gGFRD7y4?z=1xMkoHSfTa`A^!B4GDk;h7KN0n=B>jn%5 z3C!7lD$@q1r&y$|tXPG13~ z2&X`_@l3me7bwa#Ao!AdlXHDX0EX$sNh&){CR=#pQz^PxO`dUDT$hlr1jI2+O~eq> z!xpUa8w*(bs<+hpE^oya%XZ;uZ6uW_z#Sy>iQz~tt{ThQQ|}OzBuOWor(hgSY@z9= z(smE%)1+9gDMXM~=Q(iJj<*s-P$|iaWHeN4+N?_{UFx4D}v6&F1Xc($C zo*xPw_I0_5-z?O*aF;ujmAs|50tybM(cUO&Nl}5*>5VCU67>d-uco!QqUQR1;@MLz z&_f1N%ajcBP*BoIED_bs587-?6p(Hd_a0INOI$JFcPGt4m{N<0T3bRuZJ{bkQV7+j z?$+n@3~2xWHky$4^L5L2$x3b1$A0^YRmCwFxyzs8 z&D}Za^-;n)shP0MJV}n`8aFgB&{MQnpUL60O(}@M9B(Z988po*HA3ridP^F(d8-xpgD zd93F>7C-{(QxZx^8k8Ww18DI@C*57tcQqu7cN_{RN>(Hx3e*aUiNK8#2SLV^y*=w> z{WJ7uhx&x;UMVIYUtbkPJWU1{Q9|`h=<5l3I+5qbCD?b^TH39Yj$>A7+7p(RW%R%V zl!Yi1e$oz~3b7y&i5L-x!y3vPJ;rbOfwg360wik+2?iu;7%0KmJhst}=q5RX=Q%M2 z{{TmMFi9||r=BTGG_urT(AUqp2KVX2Z6?H4)quYf?&foIn*|GvI+5K46cdWnfTe;C zDbh?1uPVNCl{c25D+$v&%ya~)N!zf_nZsnoeDVETbt$^V>YJ;*T|cCY6vr`BPVHs{ zHBZUJE_;QEI}HaqH@mF&c7TxwME?MsqaL_c1z)JC)FkaHk~qMX`bmsvrFDvuuMNo* z!JsTL3FG}dl3q=e(FBe=G2LLyNbv1zTZdc2EZYQu_oxzh!bSo-&y_9R*9FDWiC5T@ z;R6X;q?s6O5z|FFsdiZtx{W^T{o|3-Xws48&#h052=qj{&Im4_wt?=j<4xJ?XI z6sHoas13CgF_v=9MwcUKv9`84a$-uY^fuBIm`O~MV~m+RG2`i2wVdUb<;$C(g{Y`6 zKuD9bN?{=4c*m`6lj+0Nf8gt{jVECv5(&VO2Bm$`%hQtO?OLT;^pz`ALGh@mG9Y-MfN&Vj0*k&$ z%0@q>Q)Wc5sc55I$=SM<|%2hSsFUJ*eFq(4|=)Y@&%ZH=EvSe1GUFG3!nC_a@JLn z++~Vs+pOO5%Go+dakOjk+$lUiW)e~d1H!TUC+z;+?B4B*meiJQTXnz>fT(H#uwpPE z%#FJzr&_siI;`DMC1n*{2_;>s87gEEZ)wSS1b5MdY}O!=;o;8dT_`u<20+8khb^Eb zAOQdXBdep*jZaQ#q@c^#?L8!MR3y<*KMO{63n#wnTPXYFR3x`H9Gk830K4Gi~>*H1={f&aaDiiD@uN zX=Gy<#HApd0Z|Z4;WZ3q%!g6p!X(bvz=?r6qi7L~bk@s0sHihf;y?I|=A28?u2=s6 zI@m;VR9Dhr@Zw*~QojPhXlU@2Xse|_(E}kqQiUxeF#_P5cUOKD@fT3Sj9yX5Ouq{N63DL8{8s(^Z|@zg$; z^umuaV7RociRL=V;H93b)h$g&LQ!QDsZ=CL-f7=!xEHeR2UEipG^FFHSnLGI0CWQ} zCv7QdO}t>CAOVaGGEYvJkOsj)w4R~5i_|P)e3PB1@H&|BSeBNev-u4yRiPt0)U8Yk zjI0=5=TC14E=j}~$BvOc&;<&Zv}`0PI)rQ*$xpD;RbETNk}Ah9(8_sn|jj#*X4hjBc}CXg9n3Ft^3 z>coXR`HPnqwpOF*KM11hnO`RiHx8x5u-K%jrjAFbmMPvT=JPHU3})!NMxc&RsU$%j z`Vh9#$t5NM*&;yoqHCIPY>8J4i-XfwK{P<`5=bS4o8I? z*Gkux3cBcWCQYI-mQf(8#Qu7^HX_@U#Hn%H+ss3G1sB%#@D8M7#EDdc90VtCr%h(o zV%WMTx`iYHKv7Xtg+>Gb+<1^Oqr$`|2fD#8#5j`f4uWdrxFCD2w1JN6OcvS>c z`iS*Ai{~iwA;v4dVoJDiI(mpEkt3w2j>4biQ3xo}r@DL_+2O%^yMT+ucTXc*YXekZ zF&M`XM@WM>?WpNH(#uT}mu20z^pL?+LFV1Th!4V0c}1*{z+cDsZ~#(3KJW%{YNF zbf8TfvA$OqZzTmN@hA)jNu!zRuhi#LJxI|E6R7<)$=SkIr)sI)Fy*J2(QF?@R~KzN z5zIEt+;ex^OQH2j$N(uglM}TteWIo1-6h4A`;;ywaDxIU?agR7!6Vq1|)cZI!4$VC_BNuWcpC+zfgzDX6hI6VMN1|5osv=yGQ0q z?z3zgi)m}>2Hze;ImSb?z~tOf<*M}^{th^;XmCktm#js z{PUYLxB3j&mST!IOwumM(vp@qA`0D=1?&fbJi!hAxJAxlRGo=!w9N2=eFi?-&Are) z(<@rkAP^+%#}kR`ioE<|5Wyv_d|o`w6%>Ci@B|eJ<)i96+iv?n`*{t>8){B<)K0GS zBt(6}0qNVell9azm=03@ZI9<^DKN-zujO)AG>dOCNr76wIG^(5or-=o;>%lg+^iv_ zm8i@lVoYLi>iAJ(;Wn)Ij=!Y=8Vbn~B;dVY(kB5)tRAN+VwKR~m=1hwO0J^_dKe6K zUTp5sk|nILCOA}3&z?)cGNy~Vx4!);uJsZEro6bg=? zxp-kCk3}hKu&f&_j6*tROvg0^2*c^9swSF1k;0K13Z3`&Wp*GlcY2jIfQ8!^T z#qYWCQ{Rpy)Pn>J40^=Jvl@9>deju4rNWXi=t#p*J!b-Io;QHyI`B4k*+oIrGt>PVYN?V*r zM$(bMboA539tF~Te<9;^m|ky@MO9Y$rHZvrmm+Nnkt<(i_Iu0izZ9jrn|BkbqcMOf zID^Non^)y-P_mcykt8f&M*-2Z5kc=$Gd5nvvW`7Tl(8CG+Ndzep*toF5?6?%W>Xm@ zZp0I9eVlbx?pY4;gAyzSBahAj6F$$UBTF_ZSN28lfo+<@NU}OEa{L2k+v`sN^a);<-X>n zDQYTFQ3R5Bo|)-1AYmWyobILOnyIm=^QILYRP(J@n*?(v*;IxFcPX&A*Mg+>j_^nb zVJaIjSq41d(E_qE;%x(<1^&<5wYH)QpdvW~jn4^ul8N9v_apROn2sJeaS$_mmL20DGSi+lHeqXk(_63sfEzDf;Es7y)nV z9EocMjS)7JVWp2)%|y~%w2bT+7u}_SJ^*m1 zFkmDlNC}lH2_vVc)`FRXDQY4_$=k;dX4)A#h0>aOze?12P6<6c4TodRBJFD|vK&1G zp>O`NzsI)*S2+F1IJQvyF^`*94Rd0LL6p9yDfNSQ~Ms8M+yVCNm6}HB-^k8h0$H<=8#!n^^Z! zI8Skrp(+Kkq=+~J$A%`F50Y_%M*jdib*Br&@`>o47eHdg>5??7tE*+SkVQ-*Rud0- z7&!q{*k1lT2WD3~R;K3|*mg%u^q-A1)tbM$aGWEg(i^9lOy&I5gJM}qnQ__WmYR*I z(wa#imP(??LsUe-Zj5&Yg^BIRlI&|qNS%XVpMS=LC>nN}9KB=oOQ~Hu%-DW6i(wdt z%};~DMNrQgR7#Yvs1ZX@kdg#o6033GE_h#MZnZb50H|s>fj-em*KiVa6C82F-&N0& zusq#^X4=f#fMJ!!uMUg&?GFcLg=UE#^go1=;gHvJCUg5wA=39G^7!v zDFQ;EeY*xcXJ<`D7fm6T0`WRkgh~6hoH#`TlwAqyMRG+^22#fwRThtRJi2YYmdq>y z>TTG2I7D1q5v2+zZqOsogz=#>X-nXRIFyZ;q~p^B4}A!jccyPp81xZ5c|R0?FflA+ z3!>}1jV!w8e(oE$e5Z^$lAJb`0uQril@`BdmIkI)mE#Z+sUF@3r)1N{J?UfAept%Y z*}ogf^>}_8gvMs5sGf8NIERkS#oGP*cHybbgBYa+T6z`0Vq@nuyIieTD@sa$)rKR9 z>EaJWP%leWCMmrqRgD6I7%|;*^ntG=Jd-&7d#q^C6Bz0T6U@_j)<$w260owVzydHG zGfh~ACFIsig-=U;QA(4yb?sx=*qh$`D$RF|yshHG+a%#IK)~$V#*DIk+;cW>zHMn3 zkS0z(oGDpKUYd!Pp?shRzAxel1d<0bBP?+)TP4K}GLTHh9(5dEG2FackfN0lBW4{G z&q*ajl!ir67gD}r7Tw|$pBwidw~+d`-?`L;wg^dpN`cfm;ChT|ZnfOAbc8ru(o`li zoH{u1^75sf1s2%dOpK)2f&hKfySTrHuzg&}%XNN!z^ux9#+0o)bjUv5p-@g{*W|7g z)(X&~om(b4xKdJlzlO)vIE>X%$yV5fA^BNgdpLch@00AQwavN6Ta-fM%Cf@Q(xwI& zX*kbCATw11*Jr#_2d89v;uQ+1dlGjMsJCv{_;9sNl`BBoF-wr(LIRG+niKOB`Es5t zCZjae#*^Xk2qp<8?=j+Aq-VHwBi*-%`0!S=C9smHz+>kadC+B-6unvjf^hOQX8kaA ziz8rNe9O4jTA}$ThAd3PA*ErqQ-{y9$_LyRa6A3>902btDZR2=Ly1J~0s@5ls7+(3 zw*ftW3cP>AevdNdpGTADY{x80*yb;V;`H!{Je7qef~GlxDL($`Log@6+n8aSUNnv2 zUArLu&fiL;?eT)2aRP>yO)Yi-N{n0tdkCtK&XoOY^y!{4Oi!qoBjS~r!xgKihcMLD znw5_Zl1UTFiFH+dhUn};L3IO}M{#7$`vECZNC7H@9fUyu`t6{treX@Tw}*tJf+KDO zkC(Q#DD(x^_~ps|p|c-QF?w2vvyLZ*LxIl{s1?GNDC0;ej9{daMyAd_)|-x(ARWHh z?q8F$eub<{s3jnu6OJtfARu8Rk_-$$#vl_>rKUxFd3Bem4V^6?83P0*E7dAIFvG5V zg%0_;iQ$S`CzVe4W{HT?R$E_PH1_@67?xJ0$z%}h$+BJu>n6Hd*ljoWv3(*2J*GOhi$ajxwQxu~O0+<=gDX`Yfe?3lu_ zDZS9UX^+cytoLF>>2R+}SyxC-pbT_QJyl3}-33l39OV__r0qhY{+pcO+JtUeey>Y6_*$bms{&wm$1x_JHhr)zW(FAv>sA&Xn#_U)u zYjf{8>@RJ2E=z9Q5Qa2rI}4Mf4krmDjsR`1Td5^}DdYC-JzYbts-GeCAE-TRtjrk# zqbX2f^w^VA*HqVG2$}P-wo!C(q4=lFq2b|Ip zqLKU!gyIlPYD~(b6G1)bVe9rkWQ6NUmcp?Cf6`RoND~-9G&AA77|--wNXqzMPH-B$ zFD+oWf=JGfG;>YnsT0(IyLN9EvL&u9y7%OzzI*YO-dP(AxoQpL5(-L)*iR5P_#I3H!#kSOIL}(h+-7xm;iRc zAL)QCBAbQ--L;L+Al=LFoKbkVy&#dNTD(WE9fF4$&4sPYdKAlK{{Xe4XZl&B{zd## zKM>xUWr{g+{{UQbJ2SLO60Z|ArVXjO?Hx>VSuQM9fh~JqnM$Ohe8W&Z@c(O`i|0vuw8B8dMK@MZ#2s4ki+> z5^$9Q1jN>b^tpyAj1rPL>8fKg(<6f%E~UM|6zZqMclw97oTX*5Kr%R2(UsGKT8CNq z(sHIc969LWIZwS#+6>F5+ZO0BbF6mZtq(bxSZI@F6lJ{6vjS+A>^pIchqOKJvmMo* zX8TD}q@@5xr5Pu$6SvS&4fWf1M^ntUqA>9%5g0_AaOkM(_+0uC#3`{s{%GKT# z05^zkNs86ZgpW3GU*BaQ_u+$^!MxY*rr_qUEl{GDG=N4YTobbpW|6qI+SJ0BY-%G? zU_sduHXWj~DfCD$>^)Okp&6-n{gBNrkwHr07pKQvZL1GScM%e2gt-FsEMYQ)afa- zQUwfH4c}(hw}`hS)7tL++5XJu3e=d?3vHDN`)9&+YQkbjz^DL0B@JXu+yGH%*$R*j zFi6{sh~_G_y;FKz=toDoM~LU1ip}#;=2`0~aT(S|bdpHbq}q1?LnDJ@YY=qjP(GPE zNzXUeGQZ2ShfwhRs$OYGNK7d%1gsGN;uI7xh=LB$Oj_kB${*4j4V8>wlRQTgvXH-q z_orNwn|%y)+dtve?6{c)Xijs720S$EX#XzQ;=bFE%M&)JH$uQFC*6qK~} zsSRaZvMk>tOX%b$ z{XqJG&DhR)&-k5O71fyKTcsmQJv>PSBvMev6)Gach?_!KsIlfjZ-3SPVZ0X2SX$Y& zX=c(C+ji|O)1?YgT8VLMQq-j=lc<@P=%S6 z(88^drW{j?DAu?kX;OaCpP4-{(<0x! z^UUoLaNDVEq^YzahApMe;zMP|k=?01+hC_osRS9s14Vb)gDl*s3JEI`d)-R=(j_uV zr&Oc?(E_aBCjJf{gR-wwa_3pSgJ`H zu~8CmDkPFd)3$3~&&A)TDT{38ahA0(|Po|#^0B#+EHOidiI zfW%z)8UfC}eK7AG)>_tMqTx(1?qKV!py>+=Ky8bF6l5b?tra8*IusP335q?md2CxD zAc@oGfs#HZiUwNrTj?jGc)YpSKG#)aIL$__S&ZX$auq@lutdx5?G`6fZrthyd)wuX zOjqA#7R&{aErq3eU_eR{D$qZOgrrJ|CTOv{2URLUW_IC+rW+}5UF!b;(?3kBs%bJk z1|JL8GH!ZmG;Q*rK2sT|1m5=>w`tgO471OvE!=1TyPKP`fM7J*;ttW{EhpI{jx=!A zNb`vrpmYht-GHFqF#aaF>P@&tSe}k}(k5Wj*EhP$*(87lHaeXN(0e(JFa1tfJE>Ng zTa!2`=a7s#VGXSR0KIzCPh^bSoK%_P(hUUDejuKs^DKs+3dE@CuBx&MXe4G*byZU{ zq5uzx7uUnLA{@)=CpmmYy|t?%OdSq5u8Hw10!R3<)l8da003jsC@9B0Kzf$W*^A}z z4DmfCA1naCV@Tsvk|woOcUAXTn-m1yyfoxy_iLNYbe&4PQVHALp{C|`eW;u~@T4y( zq^cVbBj3c-TuY}oHZhbbv!_-1tra^}8P)0M$0ZW4mG38;P9J@m*1pc#9!D2j(VXT- z_P19qpYNS07B%x)7qGI_HPVi|(u%&Dv8BwhL>3q>@Cz3K*n<2v7;dfdc)Kle-o^hTt=@C!j_*3ri!|F_S6+;eT}?b8PP@3>IJ*QqS1*VXe$Jg zbt*)V0l<@rh6I2N2&U~fcGAaDX{L}?LY8y|DQX|aqP{%Xar^A8uxD=wL87FBc z6GmyWje`#=Lna%H)q__gNW^>2;ec>0-*MFG?Y;P3Zjhf0`C&@GCg2-3b<(#W;5E6E z6{IYe0#1IJ`e%+LRl~|jl=~5&RU=tfXm9zf< zp-iv%KV~n(i$3(*))hS2Z>uv&Sy6@JDM>uCCe+=9oI0YOH$~jzZ9+~|AA3-~@Wvd* z?MZptgs$aJh&JH_78MB^n{@a%WVs_Gr%e zek|RCQPsfpcqK&73Rgvatx9BDnAnmwn-RLef(aa9ZiK>!1Of>XKu`n{2}uM606`$g z21Nolmo2%?a_8-=?iFbA+fZ)dASkk}y5Pis0Sd$rl1LzltErM+t7nX*)gFa(57GrL z7l&i31~~`wJU*gKYc9g@FX`zjY7!|PIc0_AffB+ZUNEdQ=bgCJTvH4{B`zmRZoKO# zOhHSrtTv(~l_yH2LlK2@TGRPvSoMx)nr}I|d7@b*l@+sarq)SGOKVb72wG8aw-T*s z30$P(Q@VfXchshS&6yuAW}F_IDO6|LIcqR{OB}DKhJsHfC7NhNlwZr;0#HQIQF(t-tz;-TP~IoU<-oIKzl( z#@az{6r~hv*6>0*q^%_ja1s)-l#${D|_|Lc=|69BC|VRu(q%fJpWf1QrAvW6o#w0h`~43n;X<3093BH=aHqlHzB;w23Mj z0SXB+LcBB-J+@|9!>DgA${%qqv>a(mS!}IJLYA35+L}v2Ni8j9>D2`(DI!KLm-Kh= zu*v;M#jx(P`i-s3xptC*o}&t{%h)wUF+F1!H57H9D-n4DkgNz`mNvO@%sJm3^3HD_ zTVpZ0SS{e=Xemi5kWi+}i3uAH6Q~?ih=OUC=R5Dbscp~5TiR(+)|CaV#lT5MggUmA zhOtr{bZSsqK|)GRTyIgmbo39S9+bLW*8c!XA2W|rWsFp1NhvX@<-ze)ig>)=HB!$t zbr7&9?g-jN*b&ZTTy|Q|YD})l_4f~@zV+1yBmWx1t@Q;Au}^hTxwveD{j0 zY&87y}u#Fx~SrE6FXB%#H)1IZtoZ91HK zKwYzIR3*Zcg-Hn^c6aHo;{6}0{64#^eQdybUz$3Rf-*ymVYPJB^cbBj3E%Q^#}XuF zsui1ZvjD{lD!qXm$%R{HXuU{zVU@g?3n~dg?xGVdq{_yx1{i{LsEjHJUiEJ4Hfna? zFT1!}+)CHqTp^VP-$sz)-?mbah8*sLOJt=dy$LEzs3?+*FVg-|t;l^w>8DuzSz)DDf$`Oa*F6 z!hpocj_peX0-z@eTGM)#x9xK~ES&+BHriWrx_MWA1r}D@F0#_vN|_1$n~v!Ywo*dU zl5~z;4at9lZbqocy-UoUR<6gf2z;}SWz0_wtf?^#fJ+@EL`fPimj3`@fgzT{+HwKj z8#Egx-ED6;rKzy}yKJSm0)N*uI-}ivNv}I^`_~|ON3h6pqC0CLt&&g zQmH`;L#`$A>M$iuq=gwV1Xa%Tqttic-;_G767+*4V>z=A#M5+i$&)3WBbmS5W2v1k z>cdT>*d0OeBNLQe-Xbn8 zQz=m(jYUfYMwJw5L?q$}0IFc@l4v@g>wBer8o{by>Hh$x%*Tn*;$W zyVSsxGO!aIN7xjj$54aE2^C(xpgn5(%=HJ*ik^>Uo`Ybt!apd`;yA`B1xUU&wzbd2Bk;Ktfi=(_DfomvI+E@eMF|D`Pyj{3?Wl2McRgw<1uKhSH_|pd`4pl#mGV39WcAnI!pg9X7~}@wye-%E(H% zw}S!*J|nig=n63sD;k!PlLrDYBcOu>A0vfN#i5P`T8M?w&Au0~J6h+*zLw*Q5N5QT zYR5ka99UKj zo0jD8Ap7z6R^B~S!4og_OA>()1*t1irq=%eC_UlqHet`7-TbirU79+OATAf`t-kSD zJ-e4bnzBJVQVLI|&vh|TsFM3_a6XgBa)sue;fheVa8A?pkB8IzdAX(tnwby`01QR+ zx5L8s;*={IK;mYUG;XaY>3}yDzr(`T@ZtL^lSEG=3U!_+k=YwSemb{@4b&)uF6K^k$lA~Ms+L*zw~k9nFLXr z3)78JC*md3=ASRs<23%{xNFB>9j{_wAh7xw3H~RCd#JC;-oZb3(d`&}>P%Yu)@P!G zoP(dKI*-xpt(&SmspG4oICX4q?}mC|<@?9?w?@MM0G~U**}isea@4Z3DsKrr8wTDW zk1E1!;?Y)DY6-#)q>;jL2C4f9>!(mZ3NEx_JwC=T>da@P8NRZ!5y2;+brm>lvLE!i zXoR1mo;4(SkT#?Rk~RkX0dG$33#WV3h&&W_D~^>B#D59sz}9Z=-f*1e+$?><1Bv35 zM$kW^t+UgG20!rSSzG<9zt5NQ>c8rD$o~K**|7ZP-!taEXXW=>cbl!ZUvJ&OAM#J~ zPUBaLR=%xK5j_!7kMPe3iS_8O|I*oG9napEC@T_7LoZ`~Y0-*S!`L4ik$z<`X89xg zqkriYTxGb;H)tpoTHQ|=c^^HrOgiRzbJYI;P#reNSz>~wmn_mvK4`^Ku0@h#ONN6s z=h^NAW`}C8avS4rJlS+$wF15xWF}993~~M`C#t<+`4aiLwL;rvDcItIoFzUYd@ztO z01mk{RdWSiJ)EoSvmP+R=5bouyh1|kH+#}E4Mv)iuiQ8jx`$mV8#V#ZkN^YNDCvSj zKr3k_N)zyx>)S#!;4bMxW`ryg5yHB}a{M^J z6HoyhvjKD?+>Bpu)W1#cbQ%lrD&!tCE@gUaq{2oSflq@_JNb1p$1Jb30^Ue(DS$rm z?Pg*=oAEmHXDsd2ZrY(PDpwm+02oh1fMcqa{#6gWm((PrX-`1JnU0)JJ#-&Olqzv7 zO)$C}w6nTKPNaL?$iIcP`gs%s-Y6t-q0$`ECXVF>4?#si^0wUtEjf<%76RLC^pG{- zgR4tmsapU($e`c_N7v^?ula8FXPP3hZY5Jr!1((tdvh5Jfa6no1_FQ_`wY1De1{By zu8;tsMuhFRhx|-|!k1kM#Oxb>bT74FsUQuf_W?#GgDuB5P*Vk^K4e%WG;j+6x6fcV z0DmL(@)CbC3v0d`95O$};Znnv1&4c+`~yjinz+>r{wE*H`uFNjAbNGn1I?(%GZ2EV zU=4(6Dp4#~J=Qpuq4X99$C=r>5oMM(BgRvyU+3aJB5E?XNkz@Y+T%h7lusQvsQDNI zuC4N_V6M<%4jf3SO#&^J$fQRYw}*h!f-LRemT?dfkFaAE6y@%Bj!*QD#L;j3K>A5j zj`gMt7_&;4erVYc+ysn=Tyg%L!*>et>rm|_wRPiC+0xK1! zZ+E+uv98q1KUUrOebEo|1owUV{y|FT5Gs zyVU3d!op0YJv{|oXJ{M;T^(wyfhIeQVHsj5g9`jg7L-^J&{JNbMPuLzRU95!8FU_r zKFSOJTUvrg6GcDQ&q^rzpX$3Nbk{B5wRQQeprWIMnu##_cc+}l)pgL-Q>dO-!wiV* zs^JtX@30{74WFqu*KMQ%SAZCl$TNr|#7YUA3=C$o^Rvf}LzUb-wWTd;Dk1{Z7LYWc zq@5$Z0s)EH6m8(ga_6IeLD>HQT5?7MPb$_mM6@wcLk&FBwQS8nLoByTJ6J}_gfU{) z7cIr+<*b^?Pd1*DgaS&Al%BjG`=|sgAKwh=7SFkdg)*{8N>Gru0LQ~8P>~%cWjcCA z=&w$CaYvSVm71w$8NO+sCt$EuVms3hh6+J0F3{3O5}74=7H6uFA`P`wGy_tb3v}9P zTIX2(k^xZgh?N~85(yziW-t&a??1nK{J6tVTAuyFl*YMKH>qY+Qjw%KlBk(AUmmQo zcTh1OR9Mz<%2+bt7#@F*`4Up$$nj!zbkwaKWp*u%v{1D~DDstH1hG0s6?X*;yn^%R z-BR6oltEfl5|BJ=fjX2Td{}KMAVBG?z1&BwS;A|)LmA^AO%W})PjEFw1K2jUDs`=zcqg7aVY^wN?K0R=^$z0DUcF4ajBgy z#aE%9hu(YjEm4h8Vu_is{C_yYaQrmU#ZN6%QYypd$jwn$e9{6-DY#Iopf3j-jbyW_ zPTG#Q{`kt+N)&?9QpnV;MMnWJFir_?e;?FDCs5@>s)mtb-Nk+jSAM-{&a(GueFHC1vFNdN(*hJ%QOyhpO9hLr-a8gLfU0BjA(zP}Ug zyN(AaaTFII36(vJS0|776qUB-n?`wVXpE%D^!iC>!nDnf=&@VtKag z=DVwwT(qSk$Me~h>zFB)UvU8pv8!gWFe8qlFvg=S!+b2Wmv3KfX$p6`w`D)Zv>>Rs zpq;Ud%wPZp4i&8~0h0Q6n5T&|#xphyq7sWRiJbvR-Oi;P36*p zr6Nr1=aW%@NCOi_&nR@;AZ5;!(m|Ii^7dwj9K>bAcF3|)RT!y)$h8tw(#o`p^-UD5~mbidaMK zE)X!$K|THA3fvtv@za>wy$=_!jQ;=%QjyWpY9_vQCS%#-8*5#as1bB5-Jsm`suEZoWmAeHc8`ArNzDA${75Ti*7FAPAO?nN`eL(Nf;E83C0Hst`Ed=s~o5GYk*`5 zx|wlIM=fO>BA%{!T)j;Ah9kPZwrShOX(}fy-pkvDVY6nIZODSl2tgfjkH%|xAWhYy z_d*BeE|#GJ29$VH?jE~n4)rgCoUx4M?2(1l8kn$L6AuncU4CM4^%Z*u?vFKy0{;NJ z!l#vt4gh{8gqCT*l?|lFkidJWxOCp1GGZCu^rsl>!ev z28n)k&vD}P(qj0k(92TtnHkmBFHoz9R-Fm-B`f zjpqE{9MUfy9j390KQo(M-F{=baXK2*ohefZXIup81S!(cD*%WqaRUJ=7dMr^4!=v4e}zMO zO6cxo#Bh8UtldDH`93$BaO3lI*n~*XP{Luu+{Zt^Oi~wS5t82Zh#beqntt0hd2XRA zUA4MO!(}P}cx6DSAoxPgA8_F!Ybcn_4ri2FT(aaFtI?pig4kLcLx@XD4XWY`g+3)D zl!YjmPXdjX`n%PBf&L%=0OkSmy*?v=VYmh%mT0pz9MZ*4Q8hJ0uuVEd>UVD{>{8*h zxzmunxgX7f5Tva=>`W1~lRHS9c6_R4USR8)Xm#exMaHK}jFgfji5M8^!g>M1sc#3u z=&BMwky*rBRTpv%2AcdY%=<%ig>KwU3AipwmO7A>o@oG+a6tM=(^11zvosoV<4p?H zSOm0KWnAUAD!|EhJ@;v2r^kTZe`!wMJ^{ zn?nS0PE<=Gg(J+76WtyI?Gemk+->%6dH0Op9ZcKXTe+%Wl_adeRFIUF#NuHf878yS zd~%Du+}-!=!%1=Lw;Ku9;0P@cr6?*1lunT!aaI^syIpkjg_%7$b#j{_=bEf18;-pa zs-5VjS%X4Ysx+zvkhxYWJ%gG1l<%fjy#;^DpYM`@C20^LT`))nK?F%SN!lv}FSlnl z$!r_F%vkONt6NDST7sNx1t=$Cpd_T?2H2~x^ml;M<%%?y2@_DfP{liWGBP0=i;aX2 zq;LuOG_08uin_)%7G=+#^tmQ>%#dP(Kg0r`)5P)B^-(DBY4a`{QWFuXh!n))0wpsv z(%1$M9h4GH`(J|n)z3dMfBd1hR1}#dvIs!H8ImFd$%E;ID$ST}Q*zh@sKFv+o{~M% zDf7^etuIBrFZAgqPwED3!|?jdM;5E8n+~Z)ciA~p51SZLwr~Mo1Hs;TyVt3>R5qn- z@g!;o4xWmUH*+(!V$h-T0V*<*CP3*ORAZmlXW_Ml)mFtWZo`^ImwiV1Ss!al*=^;U zE|vgjE$!e$>23jW>3=XEalx{0WL3c#19MH@kPnIFqg{D02Qc@Aw3@ILd(`nl_{q5 zous7!C(jIV_tFQdKZ!r#+ayu+r>a?*sv@d}I{yHXdRn3;gfE#Kl9XLgXuuLR1KH0b zB7Xe=L9(QnI}CLnENMe~&c&j&B&ZafGZ=%>j~Y-z*Iz>!BQHVfI+qH^t6`;hvBj;1 z3hKGHNf4(>vq-mgQ5AtZETdNT@E#tvO7!YFwR9->h92mt0juka$Ym)$ApjjI5w<6W zG$wRQ@c{IP>MEYI)PG9oF$`HU*UZqiH$EFJDyWTo%A|#*1I}20_sRpb>EDJ9=c%+p ztjmiDFtsB>pq?IQ3_#h0(M|qPY;Mr?!vntwDMGa*s3k@Sz~Lu>q?Q5rhk6vxeI%c& zoj=14IhHH46+T@Rv{WAF^E%m9o;#~-k)dgv12_dm{+>8@kGX{@*G7;ADO7-VKs-FQ zajU(M7S>r^vOXr z>;Pg-30YS%`a;j0E5SbyjAEjz4a?Y87gvc;R@ToXQPNNX(N9n)P_o*g6M3*_WU;U} z9D@=WOMjYBT6BU+WRf(J2nYrVF(hJ6&J-~GqR`>DiBV7*L>W-n0rm2u$5;;OY)`D+D$CT_f=bM0Hf*acH9jp22_)0g zPg1DV&@?eAc9vz43L*kn9S0n_&uwi3g=@v4khFlMC@EiRLO>--RQN(Ad~ze3W*=BYIFFd^a~~QJJY^J z#j;j67AK10nD#qCiqv89d9*NyXi&Z#OEZ7H0vQ`=n0=#r5pHIWXIIx(-Q(A7mZw-k zRre{h#5ke+C1lJPAPtlR?F)F7om{5PvnXUGTB9EEcpP|*BWA%pHBMbJ>Mv3HCDYn$ z{n8A}h~=D02t39VwJ#b4)PF>Junu{5uBf_FtyXl~{cYVoJye!s^yKfRe~mLwKH4 zwwDS$yv6*-vPNZJm3eL82nQIQpb$c%hT5KOxBF56xM(U>q{MLJ1V_THinrIFrcYmf zpQiNH*Zl2Ul9w5lmV7d&8-XH_R76CS?-hF9nxrXhrDQ8`55V#cxXW|h%z3r4(Yk2> zm63@fpb_F2aDzjeJDjUDDpD32S=bH{Jw(N8!PJUeL#I7=%-s{qnXz*WS$ejvl`%*m zRfeuAa=!W%E#Gjl4PqBVZgdxSN;7L#?g|vyaTeTK2;Hq5SUZWhX13QAP~ zz{Gldu%;YO2I>V=4FxVb@yO!)1YgImw^q^}uQ1!0} zgjGe3y+lnSLa!WYeZ=hwEISMMTpREqeV1G{i%XuU6GEFTNi<3{cMcTOhE4L~s)P+br5NU?4n!Bko$yu4}-k?x~ zKcr*syD?HxMuR{*aCL8H-SU5Fj*t%CGx$&)_uO@OsQ#2X=7?lIn=+0XE1ebb%x$+T z5?m}%MpcOeL9NN{!CP#H8VQs4s~(&M6PL8QOvEG)eF2lyVo^gPQdG+!8+9h^6?9F0 z$X4XYAC?+YWt~7Pi z)zs6~Q%G!QVR+kZyma=C`X1Ky9#_0QG|5O5u9>lkD)RB7-7eVdt z;$@ky3?`JHF;>n9W(>}kHzW{AB|?+l`jhY)@fkI!rB+{gnm8GW+C|B^8@=w^hyz<| zf2Y~P=P{)S6w~S^mF4u|pQUm_wh>m~?gMpzAdmqj-qYKUvV!5#HjqcOQpVmE>r0B* zk_nBl4QoZ0%HH=}kRm1tMVh_@jupLgCDFpWT59r`?I>;__cf0sV1VEFCf?(|S3J~u8@Y&?e z7FJYD>cJug0|}pPDX1Et(LEHBD4AnAGLQi`7B~A>(^1Ti-Phk+3Tfb!DG3Qo843{+ zXQc3`gEvjTdL3a(SXnAmr%6dBV`-S%J1c`yv=Kc$Dof>gXg^3--UMwuv?LvL>^T6P z(Ypyz1u{mhGaE^f(IahSLp$$ef|Nqwcy$;!06au(#-G)&=vF34nrIae5#<%N&Dt@$ zR69>*dbRzUy zE@065iOU$?Vi;mmL7F5r;^MEM%2~a=OHL>N3YJC@p*um60P8b=1dfV|v;F0{$g-7P+pxFXmfK1Z_mw!UI)sBE zJ7O^~DXXA;IK?p^Q@9ROq;VZ2l(iUyE zw3Rjx+rAQ15{DELnLA=m-i@^_Zl-RG&8Ew$(z3O(bpVwq!~#?R*)g;ZgB5;0fN)%E z8vHymo^Yv@$4uCqI8_U>gXU4eEao#%SNyDu%)@vB;@9UbZmyEO^Siaee=3JhOp=tJ zKqIbeB5%?E01De9`f=%vSGTWTvUK8;Hdk~H1F5Mwj+V9wQUe2sRieDDX`9`)(rh&b zTz4?jVsxZRT7oaK0N8>#$o@tpGQ*l<31=YrzkiEeNOIt&yAe3&+`b_sKk0b2{D@wm(`eWNbUMHWj zWlBjy6s`@)AzClq(?h?*gC;Ud#?GSBqsY-(?;0Wkg&=WU^Ou2PMNKq}FYX|Xn1S}R z-G8&M)7Wr&)?WHXC?n9&UB}!0kfQ7A2MRq#=niSf`EHu2>#+(K`4v=4G|1~DN>1%J z5CH!1!|O)Y+leF`54(*p-NIW?REP$PAEeJtSf8hy+gG0R#v*F*9A^%Onpz4fYb`(N z7D7a&ti&I5*joG=(sW5R1N>Un-&%xK~@ zIC`e_mS<;F3=Zu{+zyFCnqYaSGIf8Z)YVx>GeHgmT}fSE4&n2%EP|}1F_GN?I}V|QmIM#A z!G8JnlalAHn=N`72?mu^y*p?wjSxnQAdipNdoA2MC)IBN3~TauS{@ zDmMmcS7n?qTLt?>cjpZn7uHsfU3cvpc2=bK%3Ekc;bj3x)InaTlNgBv*U|mXZI+=; z_sCOfbs>5@N+^_qQnDl@q?jEsg)Fd-PkyQKY(lRpW&Ep+O^s4SEkz9(s%JoUG>G)u z_9S<^6KfBm+ybL}oNcc8$J#B)0HsMPQ36OxKqXiWqr=3IF{<2Vd1EF5R(ilxR@9!5 zJt%b}(m$s`>2IiYbhWvY4Mwb*wuR&rb$>e}&W#6}7DTwbP6!rdxFj&=A%38jb8);a zIeLPHcL-8aN=zX`Qb8gCAd(IP#0bVDjdE<(-6e;Bge6N!oM4~g^pI%RK}nRRg>yC= z9UUxm@U=BnJxn$+F(XeXcbR_3xc9Gcd5M;;C8Ma693bmXp^p>+w1KdlhZ6^2^$y)O zvuyEN%9X9Ppx~tR6>v`zLS|lqpA5+8xa^bCMG$Fy$(lK%P2|HC@pHPw4ZjdMBIW9B zi*jAm0F`)DP@##?Cmc-d>jtAN&F=pE_W>&;1epOzCOk@wm~_{=KS_z;l>Y$AGfU36 zi_KDDNora|XvCLwRqf|QPrc(~e%u@GvQ4UkYYrvSr3A{(gQS4wlnEW;6(q@$41s~F z?;3;NHbP1OPNEYE1~4S;(xJ145lvO|V$f7WmPRKasjJ^ylijYavAT$kyNO`8zhQ3N zj-GPmtrp?+6|Qcz%B3sNwCE>pq7VU4FbM)9V8yW7!FND}!ZhKCBpK*|J1QqxD{+iZ zEn_q}W~b$=s&JK>NggQ*ltLzz5@j0_XNWe|CrwSXCh;o;c&(HvX(2~e$0A3D zW5i?`2`P|Bpte$g+EP>`CB*>*b*4z$0Pymv-t{9%iC6k2qmLSy>Z)-3XsgRC@zetp z+l+0#B6}k(@2%`_&V+p_-wR#wX{nC(((w@>iH4oQ;k?a=l=u?$kh#PN4uDfCGjmgE#H~){_PlU`dgVCN>enY}02{#urVLzD6vOif6dw zsh=xX;}~r&T|**NOw$}9YHWTo(Hasqn#x|`fnrF~M#wWa^I(Og#I>cQx)7zUCIH1+ zl9d%EFoPW&DP7bB3`Bve?bWBR1q^t>nz8J?O1&e_)V*WQyK??jg9)p_>ndw1mPDeK zm0_t^DkKNqF~$z*K-$*0Hs&d0DREX;51gK>}t0BoG5z zw4-%$yHsL)f`Hl;r7HxJ;~;DBl4DAfAi|_l zD;)CUDMH(1fEGa}B#51!bB#XIQY12DmHc)YyJx25o zC&r)7GgSt!Ck=eGM_U|4rp+ryFd_h}oslMO1nLiC8yZiP7s7(mdF*httsKvRw7 z7grdBA2Wx>fg1k+#0R1)nCLQAPg!w%XB4Q8mX4dwh7&B(Fj&&Xnb&bW%G%oUJ-6-J z*5%~ebNmXGFrSh7q5;*NwBp==+-8iZzMAwQ6n)urd5S7fRyYA2 zCYx*hKXls&&5+e*o}_fHlO2*s(k#1`aO#?wYSyG{Nl%IsBF4;5y3RtMZljW>OcJ+} z)G29M(n&aDgv1CUh%O1!IEcoBj)vfvJh^>x?QI88vn56mQ(r?hEj+DFOCOgjs>d9P zR5A;9Ctqfql`Jh1qynTUs7N|+7#Q2r(kMH4qLr8+4Y=*+u7(*pKZ@n)<%*xCxD68G zMoHtBG2&ii<8`bq2{%wI+WkHp6O;+ zJ7>)0Ousi%=G5hUuVcD31hj84fAVDerb0m%(^11~oVk#NDcAf&7)k_?Opr+?B7Wma zEpOJPfE$q_RIDUUJ2;WDh>X6TI-`no+Y{>@1$7lZ1x31e;gX_RrSjf$7^eqgM$*JB zzU|mv=YbY1mb*XAtV$E5B~W2YCLm!09C0HGkXW`Cmw%N(2~m;)j>PTtAV$fc#!P|L z2EnGp=yyj1Xq6xcUhPiC&sQ653h_qzI|J_AaFL~@a7t7G*&+d>oZBj1S0PJ6h>Q|s z`TB9=P%!?U;#E$=6PfEwx`0V-cJ~9@e%u&-U&A#TBICp;$I@lEYyCK;Yo&l0aQsUT zN1L-M)I~KjBU-T$m@N(;eSFro2Fv?DkQabk3xM*tDMPa*gcwXJK2FJDd zolYc*V4+jSge(qn-V3$~C`g+JwZ#Rhl7Dnf#< zBOzCjR^h<|y}(i7!rQan+pKg6z#bgqPTKy>^d7j{IMKh#{$3AA@Km>yE~z48VL5g?%zX?itZkIZSPS*jcm0>>K>{{RwF zY^PtV!aT1>nVa!&;VR$Ma;ABXHfsw>U(Zpd_>xX7K{CgYe z&r|x@>qerEk2K&j;kb=%2+~E0;7}^8$%kT4QXS7vEW44Vl{cAGXhfF-hVERtTSfbl z0+3L(B)YY>nA8xzu#lwy3@J&RV5DlUNB;mWHpsiN%ePsymM$d;d%Sh05vaCaZv_7U z0SZe^IHaki84`dAZ?3_=4csTDSV#5OsX50z;`w(mwIyB&9W7LNWo`nsE{3}YdBUv& zyai@h%%O{ih^p=k2~f*PN>rsNkl{*_lqDdv7lM$bNl8+CKqwr1BoDf#W|h8|FTQPT z>}*5qg4)U(E;jCjn7CM3E)d{TWwOGO5>V{QR0^I>uKpD`4NiT_c_*Y9n=|2f%`_j? z97_I?=smRQzy4^Fd%mK|Bm-ZvX;INjK_{itOwVvrhA+|Z`XVsxWZYXwGp zK%F8mCsiBU?$-NWC5LWvBs8|w4m5(E?Zkxw7UElEw&K)@Y@~N!X-a~mk_^{ReQb2A zDC2n}HuQ_q?gbuV%eZS$V(9fUJ|B&5RR(D&#XsoeS5ncv+C{liNWJ46!uf=TR8ek{ z%$M2F^9Ib^z}v2zf?J4ahxxy{dULd4ARQDg$xx`)N4~B zv5rQPI7=js{9o1JMxg|LMwI#uCH zq>w^EBCcnu88h(;&Y3!s1i-S7PH;;6LO*rqf~u-GT&N{lK~7RL{t|ngFUQ{8{o#7; zti9_tEt2-AcGk|-2tYv94!)lIx+;iB7^vV48a2GuRxN&Qrk`+#(uZy|l@)Bj2=kKz zja95(o4*tcXRG*!M7o{VEUVL+=&07RmTEi{H6>hRo2+v@sH-ewd&od-rsF_)D&>2O zEH92)`qa~f9pZJ|4KAiiVF3wABtaxAN`M4}kS2o{ovhsk!;D)rgr#M-l>3D!WqLx; zp79~XE4)D^C&B?qN`|Neqhelwa89k`d7B6IRqB>}2Q}a_vP1K7(;PPthiGW(sooh8 zUN$Fd18ETJZ)}&l`BNR^tT^jTy4gBGQFXT>AwktG8bqHGLQ2vxAmRaTZQ3?gBGjRi0kguxPpme!Y2LXtLtt4~(?etJpOoW;`g#3=E#!Ru#+JVu5_ zXe#1j9cNic8A%FU;U0F=Q1k|ib#5& z1q~_zX$#V%@KR?=hXM^EstVR&k|C2w#(-EGU$_TdJ*MY^#hDaF1R9ysobife9PxnX z>Q}Vcdl06rh}e)eNTsX>w%ec{+md(`y8-r;g>34;;Rgf2;e{$vBpBik!oGw3MaC&} z{z}PRT*Hmw#&Gzz9^r(METdm(H|HIDZp%{D!*>YSRHV#*3cN|4y`qOZjdLN^Pf~}N z!2GB`ryB?gZZy~7Yxf%K%oeHK)7(!RF>93<_Ub>kl{C?*yA@~s4e#I%m-_i+?WD>S z^+@a_45LxswZF56tej|>(Mod@lt(}a9tU5j@K94Ch!mQ}4#_u5ZAia}`nZuoDLEAG zkf_y8?Z1%kue9-E6G&VYA;Ja>2Vr~oTjRwl6j-57^wP7bC4KEJZa5P(g+eND7X>}z z_h0Gbp}C}HvCbWn%edQXSPd`qcyi^cV46(VDzrr3aRcoBzR$mmsW?)m%~!{(e5D2{ zf=FFF$mc?`4ZDLYDOLn{=uZeVsh3jfOhKP!H6&%L?@~}|s=W_p30Ej)?up`~boqL$ z)l-IR5Rf^FQ*ZFJY!B7W!FFw$4)lrex`e4cWm`v~_EZbK_MO{^bIm8y5k@Ph8AGSN zS;}(c9;sne`0ib;{{Sll!GVrt(I%&wGO|N7VEdBBLj&I8NHtZT@YUX(f3CiN^{X}fkI#I+^1D;{`z`i|)KlO~02v)&jLUtX>Hk%%rWhGcxE^_0hNogt^3 zqR3p?1e*Y63Zt| z5(!W%PcsPK-dt=HFj7s)zMv=_$);XBStP;}{*+XiZq~uoPu`z!>|z|{QHf)@hNTjin4vS*Np0?J zxT$-UMf&ynIBSzO%ZpOflmIwFaXz$@cv@3zr452gjxab6Dmpz$$oLX;lM~0W4x?01 zQr2##ilPRaYYxjCWVWp!8hC}=eVkdH=1sM1q=u0u0Kqef+A!#vj&f@kRd#~~T5&1I zhfkFde1D`JF2FJ+erZmvV$Sq*wRL3xsSM&M?-D6y(dK`2dlyr$F_m|wboU921i<6Q zdaEZIY1ODoJ*0HhZ^A#OIg|RAjdia#)Kym2W7wpx8`e)Gg=whC3$RGUBDCb*-RwL$ zi@l)VHmi@ypa2q#U;&EpAjc4&WYntp?g9ungCnXoMPF}7GR#=djoY#zX6RtQSp_?8x7+pNi5qTb5 zPNbO(du#y_fsh&HA<(M850V|s@3q(IS)q=>;g zNhh_>Yn@Mk;ho)zH26sq$DOpdEw)lkhdedc#SEw%?Y+u<7OwY&TR- zD2Oe)-^)UHN{dw6q?y}>B84`BE_BD*l6^^!fT8;~<=Sk=h2kcM$fm|CaO%7^8uJKg zsp6?pj)^6=s_VF_kQjk`+lVxv;$viW$3Qzo)PpKXl=Oof2^$F;40~yogDT-zH68(z zaM~oSrOWAuv;tJPj!IP!(#i&_zAy{l!0X>$Fj9gs00A0DL~QjODymzGaKw_SD>#YN zaTsto$mqh5xqH(8075b!T=5T5xjQPzx$h7)SF4`3S)xN#wQD7(r7qAxEkY<+9anP= zFW-QV<+kGB-9hg$$5Nn3f27%EOn!3@~2*>dTq;naL@Ib!v?E|DOBRPL(*c^ z*lrm~J|S5hTY&Kzs<_-nzbdN|I*rN;Z3Djnd5%tt#|waj6#|tgB`R8hiA<;v2A>SX ziNd5jn|Rk^&}5{zl$5P0Qq&ts7^LY*8ji0K1i`{;y?+=4Z%Y3Fgw8M0tPe0^xXhTv zej9+&*J70kC2^){gz`h?q9O!_2*hdbizoox@#}%uwa<*ijB9w zHeKR_q$LVk^^kxB7ZeX&=01ipjh#z+|8Izm=_dr8v&7+2`z7$Qms`={1Q4*Xwlv@bC=5?kCAve?%o{bvYjYHD z^71>!6UM-M>0-e9G(6~cW!r~myo@<RC#N>mpA&ESrDP7Vm9ILqd)1B0?Z4YFkZQ087m3TS$hSkrNwKooKqNzo}RXx zF#;OEFSaQdYAoHXRg{oO zfsT}bndvg(i6VCS2-!^eZ}6h^gPQY|MpVKwh8)s&Olx>?0K}KJ6#~sFBAA6vOKK z{i3}pdKaJ4)_%hv!*CqkooVrA-GWa^S3O1-M8JbvRc4Z&C);S$9j~~8128#Ny7n!i zewz5W*2-E5jn(G4X=lYNvFfF)o<^pN$c8A!z>&m?O_UBs8CApCjp$R( zDQ-BiDpUi|5;TA`jvHrf2{Q|HW%dhEN_3&35|EJzOll$w$(%_wqR(1!YVN6iA-zP- zIAnh`Va6sab^~|F!q2wjPu$RUu=sN#vn!~$bo47o{{S}#_hV4DL1?D3%VyP&fUKAp z_l7~k4mfpCC7SYXaO);y!_x$Tg-F9G5_u2VMgW$UM(lg)2E2}!bPgvBBBbQ78U}Vr zfz#DO=3MCg2Tbz(w6GMOSs0lrorrgHrM8RyjDGFMw}^$}A}Q?(aLp;YYk}erbxQ_@ zYKROl)hx{7+rLD+%Cnsb-KW4>{9Bi}m!CifjQcU9nS*5(>oLRQRso+gW+8~gvQ83H z?vPqQ);bMa_r3sq9GDjABB2&7!VVM!=1fY3g;Z+=9Z3iU(%YAFXisl=aRQG}p%ZQO znn=9S;uK{KKbEogD8Ma-orazDBa~9L3Nu4`4LV0nM3DT%NZUeybW?kt;1TufuQr;h zu%L%K;IugZ0GWzmiz8Ke1}LFJqc{asRZh2dHWt?Ua9w24bimq19&`-M97+?ZMgTaI zunr{o4W^E_s%+otAMpFm{Upl0E5$3icb{_3Rm=E%wNR{d^C_>TYKo}p5>t`Da&je zVM`z|ogkS}B`FCLFiAK`>62RI3YCJdWPIM z^w9l;QcDbA!zIseuskh$`0!GJQLD-{<4s3uy#USqXr<|PNShF+p~EoxY&qJsC!R{<5oDzK zVuCqRS!G$CO~YsfNH!eiR#R*@O?kUk3@K@42xuw7R&hXqp(s#rtxgq@fJ#Q3b{?;9 z25R2*TV<|hF9a#qlwLqjg$=1&_&A|(xKd_ZIVeF2cI6QGW`;!#4xOvnX*PD zP$b7Q%_S}ug<*m-=2wX%-#Vix*ct^J_18jm7v?qgj;kb=ec+gVapUu96D{9_Sj}H$4?yD30NpYOp2Tq{II$v8Y243iH z8BK=bc#Kt&(!p7c;#7$gm}^S|DV91~RVHNwubU#F9r=WrdV90oHxNE;|Wn%!HA@TUf#k&h1$*(dmi4uR7} zWAO9I^c`pF>(O-kD&rWA7n1Y77Y;v}s_WPJZAKr1%~Oa6ih;y$4kuGnBwl1O#1TU7 zxV^Y#c%o1N1cRp@goSF1ag|}!9dtC#?msHjtw1Slt4d?VDiOD4kS7{+>nB(G{m{R} zw>81k3=<5;G0vvau3Dy=80U_T8VcyeE(~BqSzdfZDS0NNZ(x{NLE^hNKP-^$1hz_u zBkqv^X&VU}2GVh)R<>;4WylCpk{deDOr*+$@Ds{0AQZCVa4Ra*Q{e?lFq}+xn2`iy zv_YW0Qn8v|m$hgrG5|g!JO@zY?4`HhU5s@{FZ5Fz>epT8#Gg3Ty+zN@|$E}4LBdSyKdg?#iWF?l%*~#uR}>t#1a;t+ATzs7ZSKg zgpq{{x2U!sOKj=z2!xDrIEe-#XTuYTCW9RN)cCs9__N_yW?;T(GY~L(VHmBm$y|#{)29X^(tS{q=s|=Lf01SHl+!#Ipq?xpygL^rFIQ z1vJ&qU0BtRNhNK^%F{~j$OR&TluS%DaF30)?8US*QwG0S4IipheZeXrrEKX zy4xu!4fjb2BWH$v37P7ued-<&g<)QgYcTvm80D&>!Q&y!KJv@@KXqQ)w7su;505g1 zm&#p`OhkEzprg$Nq6i&cb4#zV3D+YC`#%709G?DVaR#oK2+gR z#r;vks46Mx+DQSO>Z=x*sIu;5P)i$V2M!aP70-tdBnjGQ5maL>NkWyXB0c0|OuZ@U zmNVDBso-5HTq2hT6_rt+JtdLMURB(CtzoNMwT<{#yyS!8Kmj@t)+@;Xi-Fg7|3E)l*n$yi6ubP4K?7`b}o^cDQig5Fa&jj z`qXW`OLs15C_;{Kg|1|V$XP|kCo+~rp`?4>%8>Qmk;YWU21sGN1Dq8XE?cs+I? z^pM3#3qxgB1(dahtOd^Vt-B3)B)eB~f|4NVLtE}Sj2{4490}}+9;kON)6*$|X*hDO-l*|a(_{}(1 z;2l@#=5nWe)Uwn+m{r!AM??}Z_eY-v%D$kjzq5en?rvIGQq`;wWC=+2jfbH7Xt=*^ zc7>(0p+YfK6VotoBc`rD(_zom-8ZGl*tG^AF^UPN6VgusYN(b*^C4-~Q9#}?faA`+At@|pGD&>3|vff%md{lnjT`vy->s}qQbEJ3c5+9_Yx5S-po#$ z2|8=7kJIeoE19jbaV{b}=}^sWhx+1a=LzZdf1-lEwyOfJ5MV{*#7o1nN_fGrylwC7 zBgV&0+%6f#s*aHACx$zJeKM@cg9BKTvXFIsedyK`i%{YCy?BC3_=M4qB1^Pq+*SlF zwlOwRZK&nfn_IW{DmaV{2$({y0Vxv(J!r&LVN)dyK02_Oso!ELNue^_-)fZJ8{!EZ zWjTvV*k_2q?D$bRyg)HO8cRu?DKO>3mRvfm#a7^|j*Ypu?QP1ft*xlm$G>hNe=$QT zDj=B00ZN*>ONU6N?zD9$BvE9nZ>9Ls)=_E)}HmVceyW`Cbm&8EACT}WH1LX=h)ZkBD$XU}e=8P*TW;&Q7!=$P5o_MNZW&qqX23wYJJO;lG z7mfJLQjmp|5T2}0ndza^+plVkPA5=N>jZl!$!6|>jH{gKI&;&kNvm;b>13>d@g_)> zqznXcrkh`K+>mu0&wgorrDjYZp|vF-f(R+qfy0jo_E2ff-L_n*dZPeh2g;=4R9>O- z;zda1Z+x)Pjc&*515X_C6T z)E=!=;dHrXJk^X(L0nA@34vz$V4%k=``c(pAIAH&0_1UD^Ja44-drguPQXqZb`CVT zt0i0wEP{CXbeffzJso%6?#<3%(PXJj;*}+0B`Qe@5GQ649R`?cI#bsy zos30`=SV1MzCxKW*@SgbfFg-YY?o>O04Ovhp86ggxxY%yMvW3<~j1p zlJ9l|o7mjzr-|ZweDd+Mgr()c00B4vFdo4{mvZ(Al7z|XptBR`w@PVi7%l+>aj*zL zEHtqs0tv9bns7>t^7cQvtKCJav1UHeUZd$3N+5^HiwKAjrGX?1{gZRpdrvm3=IO!W zaGzx$HZ1=DL{p@l8tIlHP}NYnWDFuHMMu&e zo0^EJen}NY#{HLIpaZzEH}CD?A-;7+N~!S56T+RM>4r+6jg37#X>}~JI&PIfx%U*E zy7%sWt|K>YD`~6fNE<0>k-9IBb(mB1ucT>BLyzV*Fj7@b5=R;s)X36E_9TT>X0n1$ zU^r)KaKg~ct-&9$5 zld0E@&SP`kr8tJ#R)PL<&y3GPLMYjE^AYq}=tm??(*FQWRdiS!b4ybs(liFHStL88 zK_u@YJc2UBC}P$cUy{|HO?iCVXt~s+HX$;g3==9a1Oj-F2Em0wuI~<2yAC|N2X#L3 zrPo%D^+pHm)2dP6M8ZTJq>@P{sf+QK^!XpUjU`)XhW7&65;$?0?%kVK>RE4DOb~^tQlJzGCk>!%5MO6Y6xYJ4(!Sg`tylGWNpimXoM5k9ZV8Z3;Eg zT)!bg+Cq}27UPchWoPY1z(GnuQk1C&3<7WxNsBc6EB!}ezN$S%^`AK6S$8aD+HAD= zW*J8gU#4c2zG7ObY9+74B#tvtGqg!yiX%`i2`zp|dy}~KnPUxSDQyUL<+%;E*lng# ztt%;MGF2+Wyip@j7$FG(G+VqD=P18bidGy-QzbwVsX;{`!NfqEI8nyyg>7wDRVTov ztx1xeHIg_>?r21+r}T^vY*rxbOSOP4aeH%?e^}WH{{S(S-5CgVFQ6?)!L2GrpbjJe z3Q6HJfW}Pn2MW;OQJ7c}&1we!@rtT?IclM}NsD{IK=%n9n1k4x z*lIb;mNL|wN|`Wr_nadPHWNHg3~{N2tj)$5EG5N+o)}@$0onv~c~aVf11lJ+w$xrl zHboMP?iO|p{ub8$9r!!StYyN0u(?ntNDgDG1rTHHID^A&29k_?3e({-Nslliq;TU( zn5gM#C6TE;_7gn&iiTk$*gMC4RG){1`73@&7VA)DT8dmQ5=Nt~aj9sWQc1%DFitd) zWpBbsj|fiK1tVZRG}~8{vh{U$n^8|H)zVYV3^N8Q@hqi_l_No^J6m2X{zYo@s$ikS zsiufZq=JB@EU5HADprLZLI?z5M{VXWpy>)ul2S;F2@nUsNWzgd`8x%A(Twe=ink7> zG}QG%LI8=PD`f`p%1V+6WjgR0_D+iyoOL>an?MO(z)`0Fld)bBK`;dH6ydpXgb}F< z3QH1_t4Lkoa@o*YIveiLR0Ow z4vrD9QC9T*__Tf;ew;cHgY+&e?~G$G;Pcf=wHSU{s)}-4X@wY!I0`X&8}Z%f&JmPx>3uxmIgc=5 zbQ984Vs%v+dC_QOsbd5WB(qGQMJX2C%52shj}cvDyUDxEi!>>VWW2KKb*T=mP9Zvc z5vUIi&_Os#yT+*DSA*@b01FSVlPxT*MeFPlvrbOHQPp zdP;h2tiV{E8&48D@-(rt&$p4~*twf8T7Q5oY@u5)1sX@RW7kHCw6(HFcv~t5paMsn zlZ6z&Pd|#3p0NE$WsZvBG&sg5n6W%+3aWUk>gk}u>#({w%}r$mOH9*DwN*Q96DPVZ zM25qX3tfyGG>fanrR4%ATGmP0Pm4@|Uw|GwsnWpW;N8FuJo59;5k<&=QhOh#Wq~bRW-PkMhNt^1`51Fj6lmx6+xXDkx-b^ zK%}U#Z+IBWw_@#WBHb!0Nm5}cP;D+~T0$INmo=abA;khhRJ7>CLzZ_deF>GQ=r|ol zPx## z8@2{sM@;ATt;2*omlCuV!gLmbK~Y&z!N9bV6yBc^NU#b7K@?j+017SkM_1#q-K_WP)`e zAQCVH#B2ZzA~;a7i&WbuN(6PzHC)x5NX^-E)b<;O`mw-k>T(pdv<;c5aC!Dt)nR}K zb)xeMpF9v7M@_^LxDq)u*9AdH2SkJwp=nBrN|Hb{p6czy z5}Y<|+wQAv>Gn?O)?(^5JDPd{hhj;VGerb-ctn_@Ml0H$CRI=79#JXhfpz;wL9N>S ze|2tyE4X3hE4yXIgcZc;DkVQ}gqVW89vwu)CIt_&rcK+(4Z&NDc!1)ddiG({Pu`~J zaom%XdU=^6#j{oiRYQrk7bo>M4T})OY9pYp^s?i5YaQgIp>RMGfsiIA&V%X>lH{DtlqqWQZjg0fsQATb zt0u2E=8=S9WK$io&s6}O1TiOVS7~9cx8SzkQh*9VPCGVj;e_~j$r$mhTXiZ_omhEE z{4wE$2S=b%o!U0mX zLBt609+Cp5*|LgDec^#3c=UUyK&|RlEtK;E;MtR@og(S|E+UU4l-X}BEp)L{lkU+< zM0=tSV5>MA{q5u1!HtGsmo5o2AXjq(R#w*Y&43VWW{sOdRM( zyxM>dytnW_-NcGghREk(r8-h}&$gebRK6t0I*IiySgVBLO3B03P64&F%U-^IA%hMiN0A1blfkhXkk`a3Jlg z5zAOa*vr9HPf1r%bcK`Ns*xK10A<%|T#`GFySFjH_q(D*q+)072g_|_s%%Thkd+(< z^pB{4S@4=FnR5+Z7g>h2LNRf&b*TX#?QPk)cMEE7asdYZ95HQR1gIzsM##tG6^l8` z1*a5(4jnW4Qx;O7qJycEVAa$RQ^PZ~L?nBHGpPyXtI6*T*0uEJMmDW&B|ww2os|Tr zX;~3K4_9#6a7=n!IBD5BP~#r8u&ONs8N({A2hCH& zBL_g>5((Grsnj0cJT?~21A<_>S)Y)b6=GG1MoSX_V<0$pr{rNo{o z(g+F|%5@oo1i_4++`O|c-^{r=jfK&L2q6 z$;a@))IO^8!wbS_>(VSrmjtO=s+nVrfu5aeDCwm6YKMy86Mrn7*5n(XcHv-JU*#-s z%ZfoQt;7T+C0}aFTu|14cn`Z|)W2c4>ujX0#H|5Pu-aBt189{5!Gq~nPttEeeuDa; z&>4MMbZawbjLnvCsPP#pu!YQ1(oZ47WRg0_0{KwQ9ZXFV`Foi+>3tX;VMXU^+sl+@ z2+OlkXoow-K~HxDNOws}khJ%S(6p))pcGJKfONq@agelD8w*+jfzskcf<%FWgy5kB z96^w1(^GZ3($`GAI%mv3)2>>~xn_JCiz-%DOOD4{WX5o8URc!3MO(Ve@T<6KLaT;e z=Tc_ezdFnBZy0S_+j;BNw3icdmjdn3N}jg54d`h-($a;qr2r`b1yHn-q@T%dGNdVI z_PS7K3DV>el9=LB6chl!$WYlw-_mX~Nrd6B(9y6~SsFQ6Y<$K;qaR=^Yj72C7rWW> zr|k-IWPcKNr_kfFg;%W$t3;i!J)JZYdaCrz(fmIh%>87l>E$+Yo&i23HW=>l8n%)x z?C?r2vTY5B0B-xi7FWI>*-i9ah26L2?XFBTz$!r<_)3zbcWF|Nl1S5~QZ+yd2_iDh zcXsc4Y}jKix;D27UJBNfx}nE^?#J}*FdqHm6iGg=jE$k z62fy%A&1KrHH4~E8R`7$ifE-0no>Nn^Atx#DIm7%_Aeye%;6UI8GBi1bxbUkDWolL zF{}27ONvqwwUC@rk_M!I0Zsx8&ATL9_es0FzV6iMN?#5kXz#oo+s(2K!deZynZZn~ zp=7N%>C-bkek9(yYH^&Q>eD84i!bE)@Kt;gEZK(T$y*P_MMJ7J6?E%*X#|oWWDdh) zgSCMq9I?tbM|k&uTV7gQpebkyLYrGbYD18nPPSbuLobImse!Ai zDJyVFEISXxSTB_=Kxy7eGb^YFY~kG45J^jp?fW3!AIv#;ySsKm(<@tRO~XZK0BO*M zopCP&_=<`lNeWR>2r#bCBHh!Lt>#PD4K_<}IMFF^rNt6jai-gC9nwirKuc*2g)2&- zMuz^2!}yzK3>O~hy?0wEdUgFos{a5^z!tKCjig08AkYIEZwtcl_l6xTuKz6 z2!w?xm8b&b07(eeuewQ-SN)W_G1V@hdRU~!vA(V63flSU!IGLxQw*V<$sRQVHjQpQ z;0e>Q?aoqW`<_l-NBJW^QPy<}t(mVFmbA(I;|{3Aoog`0Uwwy| z?r3TqfGUEssA)@xOG!=3YH4LEbqj3% z$Sfs6VIf<~e?02lV&SuDKt0<0A*U5P6ode*c9jW%w-H5#y9xXqGFMS(MRqfqGnP?E z(prhCA$mMfBxA9bCYooZs0w}Sgp3h%-XCimff+{ZWRE4z^3~?u1p&0U>*%*of|pjN zlH0+x32dQS)`ddAQgtOFduvOVEmz(-+};BX_=?+cBZ`s~N+)0>sBACA0{Rw0Jg2;qqb-R+9Gl8RDV>>iFysvE>!Kg*am+Wt_S%Pnz2C9e?DIH1T1 z9Xd`XlkWY`_AJIn&k2EFqX!=ugr{ow>)LsTGx^Q|x500jv%0r#5Lh zr)qJ1T-|@eZ3pyn=@gk%_fH@!2=DOF`!)7(@v}v16tRYJH7QRO_zvU3{1~=%rij*< zuOts3Do6pWLDuK{ejInX)kq1am?=@8-L>u8OM5S;w~Cu)i`+Eh{JYE^V0|uh8te3M z*jZ~Driv8j3hI&*1f^s*@V9Tj`Z$y|-Iz3;MrqCAR*qR|q>>qL0_^78iDnWbn%SM4|uw9 z>c{26v2h1b2d0?6nPOYNm+x!u^6hWZZMFQZ{q21_-rhVC{$OdI6s9Zx)Ud3*>ig4X zUCeRkJWCj_tT=3Q)j>v>MMBFhNLKlH)W5i@B(Y~FXaku8cfJ{WjSz=1Fg6*EF^1UT zTw=@nFU{Mz3wa6BH5m&@@j=r#?9~!@4iizK%`nyUyDq}3Br@WyQJ8Ac^nW(Bwo|K< z-IARY_S13YE-w-gkTxi4AL8)#l5nBJS#sK0LZJ6&OpYo76h~ADp1MV1_^hbwhQ@}? z?r1D5HQK&EUn7jp{I>~C!?uQYS$IA*dQmmcy+FXROvjAUW=uXhx>`DDgs70Ynolvx zM*__rpvi3qfWNbV#`l5W2v3K^V1v=p4izX{WZ|@e4kxEz>-4O+R2e_|wewgG7h8Z+ z!iHJ=>7tex?P0ggYZofFwXQxVjve84<;^NmNS+uUUPT-;Xj(8xJs4688P8b?qLyqQ z2gE33#N>39lV}qKEBZ8Ie#OVUR{MzVHR5$&6nKorF*`cwZ*6U-0*-f=_g77y(h{?z0I~q(qn=LvOVEYO(t5h+`OjM*gm0?DEy(lEng> zox50ozUrHM%v4|L@Z?lp0Qj~HPmmI7aI|C}7e>!Iz3zbYu0E3Vn=f?Q0H9&?RPf2P zSiGvc<|pZqkJHX^?;daYx81p%RHZ6&~6uIHbOY#KKcPsxm!v zf$gYAcw<0s3_e&@`1&Eqt%+w`Yc$n3RHLL6vAFv}N|SfD(HQUX}DtKt+s%ZojZtaUSm4v6o)l+$2d#iw&wmhJ=4~ zT2v%zQspu@Cr;U;oaZvQ-urgkQ9av)y`*?T5BKQd`1 zjKv`UlvNFVNw6A(@9+NrEZ(32AjUszb(t8>&wUKCD-Y&(rrkB~l3F(lsSUfsAAIl9&k zw4l!jBhv%xQ!6{6YQnXpPionytP{t9OkfO9?}Gj+Uy61SFnZ+aeqB-fT3=e@p}A9@RU@hBMoj$!oG9enoM8wbp(CfNJg zmRQLQ4|Dl&JT3?EC)iKUm8U9nVwVvy7@+)>`qG0I{B*WqRk?$!o|p4(8x$1MEmdS# zy$LbW*l+jQQp!e#-XBjBes@U-L}GSNA7wV~Ot&#}yDB40jYGnAiN+}JdO`eRvcIds zqov&!%=miGK`txi;uww>1ZI*ajs%r|NL`Gq;6%GYYZG8K;T_wC&A#dc?Hi0LH zq*3$N3b!RXLX;vvCkfe!6i9#JLpiTJb-o;@=_4cHbyPKZMJn@tXsnV*nwFlFQ+ZVI zM<653n3Bb`+O`K?4>CKF!z#HTqz{Px8Q5_&5zJmg*CD3_6pb2YWlMuNZ~#YH>aA|` z4@de1m-@TXo|tsvyBNgtrfaLh>hVZ17^7HVpu`@XaH!)*hrLlWW?7}wh|nO=lgZ;J z&fC0Ff8&Ki0Xqf&Vm|NUkW3A+QI=_z+%ktYcL5{XWLBf(vXIlY$z1~ zr4S6C5j#h-=T+-e@3mcl15z#s`?&k6AOdHO+L@3B$~@gCpryllU4~(3MAfy1N%jp) zVn!#-U^@$2Q{T5c8QImB^6ZM$lN!{5v(hz^sXl~l+gP`sx~H$)b7B(-o|qd4ud=!I zUV{?A`g>Vb^RFzH^3V`3xyP2e+fqw%yZqyseob)dTqQ|C2_`nEXdbxLG6zw0c$DY> zZ9YR2@T(K_^@7o5u9M@LN}e#)wNT)gY;lFZxR;h<#QVQ!0qwtTaR;|2Q?-6 zq^DNWl9(x;F}A6z*MfSX^?Mc%m9fm&F-$)oj8Mjy?kg)wCaRrO#YnP-?-~MbK<;_k z9Hq9(Q2nDx0rVwGDG5x-1QkXY3<314Hr*WV-*gvp-SVAM!h>!7&S`B5R-~p*8k{9+ z003iApu;VG5$-z)~aly7At|~dMKqxuyWV>s zw;NjY7KsZah!NM!)=Xu4_hoeA087Cy5*t#QAqpaRf=JkLAZ((O);_08S6dudwicAQ z#S1nZ@mHlhk;mnGl~8+uTY9+K4`40<yHrTFf|Bfsxqz}F+=O1kz;JDMcGa^=a4iHSB=}a75GHUZ zWd>H}wGwciksg9;Vb4T84~DDNuSPmoO%;S#l_o7-i~j%}t5vXKM(e7gjlG4n*PlOm zmC?CD3Y8aJNIgC!>LmIMO$nC|uWlG5d2E4OvUN4-vhPH5CUnME%cjEc+WOgB*dc+K z9ez9)WS5F&^`bweK7${X2y@$1y_dX&3=3po)*yUqNDhR0WWf5l={~@mpP}W{)@3p zEBcR_IssdS;*^C}dfYalT$WuPgS^GNw`iTn3h<;b3RMgh`6!I-?x5G^`~eH;EU`F|Y-O zpbq?{mi@V6>^g+V$B5$+ct;4ME8X5+Z)`&f?^3Br{fnqLj6{OCBpeMv^*PtfGp)JD z8|qhFa;Hf;^eB>wEJqlH@w^VY7>azo8q6hTNPNJjYK8ZSCsD!1Uvp~P2^R0Al*uS< zK$9xOkW>z?0(Fc838<-d*_LaVIJ>s)!-gg1+ySx>0z@UHx1`}FSu&$1s;BV|o^-pa z-C)b|^jj-Sl47F7BgJYkL6{#F!^Cj1vrQ6C5yAHWb_!Ufh3q&R-!0>`vC3Rggt{A2 zbtK^Ag8(NTCQR)DCbGY>ZOhEx&e>++(EDm}DoImGORc3RQiF?32ND3o06`>?IGxFT zVC9NDnfOh|fi$v2n1u!h5hY4Ity564vMP-%*Ea*eYsf#c>wnu>wYC!{)D;uyH81w8 z=tZU5ql>ZUCx4eGy&Xu)ju&EQ#vblWy+7_K8 z4{Zv#WO%$XY^lED!%K%zBmrQ1!!SaTFRWxu@3tXVcq2VE`_lqNLjZ0zG%71?%P zx9%QNM#LpLjsR*heD)72HQhe-sY~e^iK+T@ljh!(narED1*F|*Zu;RF?82?m7!09M=CeyfW+T%j#G%5A(W?-CnITnTXn0bUjN ziHRhFnS^aL4f1?rsk=TH?zl zv%PhBecD_>5E7*c0Kp8IiU0GDuA#&Y^%xIQ7UgfL=& zm17x^R`cCh+y&cld+Eumck?{L^<^n|C;=c$@s0vP_f%_lYut@aG@uEIA}X0_`iItR z;p=v{p;BhAm&=%D9F>&g6{Ud8mx4K#2_0Eg*t^>Izq7X|I~U$@ooZGxcudDd2JbDI zW9&}R!0hMQNk7E5H1%hvw7oOS6u7KOm}{n~#VG2qhmtC&3!IdDT4k>K3P|KA^Cwyl)1V z39YXc*pL#_RN`$>4LvPzo%PO5|`s z0yuS4yPf5kV+{|>w%A%u)Qm(4`OR$CoO%K2&#M*Kbp1-ou;P*7@y!xZwDl3tIi62C zX=*59kzuHr-sHTB$Cno>4o^gZU=7!!vHIDynKp!X8%&*7=i zbj=={qsA~Cfjw}i{&k1Y*UN@Z8Pd>5CXItdFpLW{YzP(yn_h=?7{yT}NSMS)97jzm zZLGrcO~#cuA88;cMD!h^dTJj*dY$+}^hY-iqI7#4%J@b;5_D`ya~}GszGZgQJxk9} zMDj=gCFE9XfI%Entt6#N#HV30NRbB~GuKP5)tTKVL+M#g5HyGpvLIm;XEM$a_-Oi# ztD7RjUxen2OBOFsqL&|8@g=KKbBa;C6B**Jh+5SN?;_bnmrhZXTk6q_s1f%WB<)b0 ztN!@Ofg35N?yoFiWGNtFihLx0M1mlL(00+c=vP#IEp;~t&0dB2eVj3@<%rN>)%1A1 zMlU>=ja)HQ6GI}&Uo>JlU0I68H6q7bsp94XMGCWNPfF6@4k(ooJ_Dskpq~hcnWbwE zv{Q1V1O*UN03|Xp5Rh;jO;`pr`7@TlWGSZ6C6Q4MJOll#rnWf&}oIP=_Ry6NxiCWaBjk4uRwvEUuUa zO0BHRmCudRWAoyeYos-GHL$wx`K^j0ni-%UF7Yyy5Rj?{)gYwgEe6V4TGF!OT`q+k zWl16d*piJB*ls(tpukQ7l_g>X_@EFc7@m%UIF7oc?^gYK=-yS%-D1Hr)n#5GUzzjH zSinOg$~)cWZqsruSYb}!q@ogFD64Gj1t5Fos-N*^%v*g!KWR4puD9o*H z?XPYXdf8G`>q;?BC{bMeMY=E4jK$Gh zuhbm5PLACW=g}7Z+Cr-*8Vo)Ym1X?*;;>v zB>YZ1%?vEq{K-RPkt&1h0=5G5-RXL4jfF&TN?cDD`T1q@PCD?f%0UdQDPsx}`=nbI zxHcxkOCCed?`v+#R_kevkgR8q93rH(c&cqi3>;PhNc_(|Tjgm{+MBlQt`i z<`>7KYV0~H5miqLRF`R47M%p8W3T{`Yaee0c`oy>Ik_#lq@zh8N!msOrU{H_DSwkU zZr^y+>YayYPeoY{U+Yg!aLNj5jCP>mo@{Da>ZxXohmdaC#Hj3hc0S#BPkVaBva~J0 z4*+^8hOAzAYC;JeT{KAjMD=!}PP=9LKAPe68KMkonu?S?6f(B@*=s_<1U~3rHc&!@ z9z2luQ+lnk;-rNoWkvuB0L+Nn!=%)2yxXkyV9{~I-6f%^N>K2G0Cf}594X42_2;Dh z48uBGg<&{_1|^!ac45M5C}xLrlTSre4NYwvqqh2JP`m#CtE!SYHQ8M#wi1XcTIWs# z!Bms}lpJ`)W436`j$~wzuI;3)D@h^}p$Sku1n}uN(Yy5v_i5D)Y}VMq#a-ZGsA)Cjh!`+c6O;@^d&H%-IJ>f zaog**jL%B?Kh+#suMWqsYSQ$P$xSOYngE+XWWQ%1NIm9+-*{F~edA!d>271C=JcY` zVI^c4jDFM9N%(Zo_2w+!ZEd=QjYv=%1~I_!F@Wo>fxQTIAJjjo4C|Y54y@5(b79m1 z3TiA<4vkRMx;aVW1x?;H3%FkPZrX68I6@m}cXCxbIy(I;4=-4^vQko#WNin4{vT2{ z)t?TNRbi4PUKI-Ys>>h`+&?;1oJ_fv3u#gP3Wb!V&9m`qKJ z;Iz_BO;J>vg-DNP>+Scvrnz0C!(J}Qt(A9h8dRk!AWj%{kH(C@I)@5MPQn58_?p&l zs8VF!pyymN3^N3$!)oE7pdZVYQYjXit)*;c7U>ce63 z<5TwOIByzLhhSM4?U6{#dogr}EavLS^M!T|Ly2M)u~o|yn5>9Ql#(*jY=kM=mi^0( zeZBZ~WTsVal2nr*6XN1FVZ*FZb=B>{TrDAo)DtNLHz^?PgE)@8wCS2Ml@CukOx~li z#T61^coel5brvNKB`s8IQHT>GCzQ&e$&&UL_eYNcF6Vh^xjA@s9r;3*8%m0mqlwwl zc5R9@uvOLfh_vcZRFI;y1c^?}XQSIuIsuA$k?N*gt-~_zF!VII4OJ6jRpOo)XsK}O z#09FpVnt?YMCQR1A9QQs$WJp}zF4HCLUjYBBNC;K5#`3Gn|o1m3V_+Rc1FoG4fSs) z>}MdL?7{H2jYCFZuBwgbJKsPzN}Vfzg5^JPf`+^fxnhOku>j1iL8ptJ8xjJ zUO#jj-E||q`7~Imrk+aOFcL7*fUIN?LU2rsV4a5=#|`)0+{1Y+e=T4>^?uPM#WWm5 z5v5B^uSDXcCN&HuFed*1@q+wSI$!E{JY?M4(R>!G6>J*{o`(>QXdWomDwU7Qi+e_w zWFY&yboP_O*PXUtC8ihNiCT%$q+-1|c(Eiw)fi60MB9UrXEt{iS9zl!mhT(4VYb4O zzY76=IY0>sI`p6)6n)i1o|IT(KBIEp2Z~`uXt4}nPN8EX%4Q8_4Ql|st@n#?HF&KJ zEkg*BD+%&|@^eco;$`dHM5$Sgt^rwXkOFZIuE^Ln! zifY&XVA9T%q1p+kmKVH!Qve+a)P4Mgoqp{(ilGFvqyYd#?bWMn@Qt3dI&8FULa^^O zVmh`&d*+R{RP>$cgyC7PUrjmIj!egm;i5Px{$M<`klr?uS$wzonE)zoE)?#u7T_Ov zGq)|9Y1@{FN?a4xOn?O8*N>$SGOKpbwRdaPBWFOQwkhZgVqF=*GG=jnW zS&T0gO;^mL)ze7ZyuhK6Txv8I+sOEDk_)A6H-h>|3IqtijvRfoELE(5CuIY@dFd8S z>ozTzXz?1uMLZRah(vJgG2=0-M6|^#*L9|q>@6krLT#@Hxn1eEN-&ubiS?B94yq!2 zVraQw{+z{bHAkK>^DGtEL4q4pK_qYrc$6`UB;B}s{_?)IJ^j3sKQt5Z=jTC3NrF0P zto6&S*tb;rxl5Zf%ylwI!j_sS)JZa=bZp4-F$3HLHs(F8sXjcN5f>yWw!&~86ekXn zqaO3XRAFYo%UM%uaH>>DQplM*5)RIwHj_eV_0yX=8`Fq7XVY98)i}$I#zW)F%m?gup30V=qtHRV>Nc&ACGm8_ihmVH=xsPX=a#RvK z#25zx2*+gY{Ak+GJAKepttt~89&{(+pN)=j!{k_VK1Rc<(Sq%KHojPz_wBM|BL35U z0Pg!bX(|1Sq@EHm_hUk)a}eqACr?)1X09iv{cirV<$NbLO;rs9n1pLAm}Io`$ttvh z>lc_5DJ1yzu;wn@+mw=yf=9E?gfJ%$Z5`aLO&%#h478S(>btCL>Q8V~>!I*G3n=Im z*`X$%Ej>hvf(3VvP)OIcuXEbxL&7z`rk)Mb2R_ha88;|4V!cZxoQY zkxIJRf{S<`ZysXvN|JgABhZ8Ih@?*0i-1seC=u6)B1c%-4+BZhP@jmVZ|asLu;JL4 zmZK5*RE`vy#iWv++Z8XVC$Jj(IoQV-YSomfghF(sQyT(=;(d76E^bBMWb*$2I^kB5 zLC5+YAAqX7>Nlu-?@yYf!*N%5D=Fq8SY?n0-ihx6uG@=Tf#Jku=bBMUfdp`fB8+S@ zi&vWtAwfw{kU_wS+Bw@uzN_`3qc?hW$MA`zS*Cht6!Dh;%Ic?sVGW@sR2qKCqvDt=}>Twr*Fath;IkF~0!a+OIGRL%h)et~ul zz>o(zE^?JvZth&8j3r2%c7U8bSoGp?J5Du=Io1CF=JUq@{{W4X!~QwcNaI$A>JKra zb@vU)jM1|U9jo>lfbsf}#8y}_2$rpt30G+XrD0gmI#q!ueRM9|blLpIqYOF;5O`(b^*YDEqDMJ?gn4o3GEb}u*rb%Y!h zB+7P4`<1I1!Zvi8H5V31ak8WfT@K4kgk&(S_y=Lkg^dN(qgi zrmKoTP;a_}bz(>w8*?kW6urxGP4CLCnsLHYcF>5OTF!yA06y$bMI7e083V2V0F$EO zwTXgM6baxDK%J+esmJiGsmv5zeCw`G!6c(ZsBFKAm8vuAc;=^KoqW4Q++)3z`C-yF)a$rqNwUGP?d7BeM*A&ss` z1aqVxOd06Q^M~y<4(--8s|b`LBC4%jLPxUAW_DQae6TO{{T%CdcfOW+Lo0E3l%$y1JpdDglfsN` zt)IJsgutDr;}x*aNdEu~ynoWSrEa2sFvqa$Qlm6rQ$<+N(MZt`l$B~A1I;&LyGonb zYjNA0z1}|2PV(Keaowyog{Qj&j1HvgnAs=RDr>XLO{;1WB|{VGg%-T6h*weM7%Awf z)uF>7Sp1<$B$1XOT&jDlwpBJg^fuR#-SQIc(v+hG#S=P!fr#k`ZqBhZEn#|42SAE0 zT^;BaRO#=pzLWLGCeu%YQ7&VrTu%-Z^Q|%(^pZ8Hrk7w5gkmlYl!8FFGRJoJx!bE{ z*xe{OfbQJXoqh!;!l5LbIE-+|3W)csFG6jcc^()NM-MU4Rtu7_EaQ!JS30&SR%u>* z@0wC*=#?pJKRW$NGu5KK)<(xTYG!OAuH~j2vT(< zttC2v;+gxC)+8Entmf3HAh;*t>$0n>*9T2T0iUpV^HmhIwR7PMDT=LGBr)r;!dvVz zo2l{deoFhC?Zu-`G_X)Zg9wkf0yf6c2cUz729Mn+cm*JW4B|FnMwimZMe}|K(43*w zY8q*4a9mP6Mw%~{ft?|WmQqXa0>v&)yq@jzi(7S}54?mpw-${nP)drRVT=hnlLM?y z(L){AO4z<>z%ZEfGCy@W`njUTaW7BUg?0+rgXVDRoIb5nD%A)vS$w*bCORpIuy#{x zc)N zWUIt8MtMqG#sh7nsis*1ks%|_BwKg9+UvMU;wpsl5oE>OEr*NC0zq^!77(KPl1A+Q%3SaNr@csNd#5)=}k zM-dS|u`~;H2S||+R6X-bTrVSGc)k*c3(8r$GE}jeK`nJ;kU$rG!C>yTYa2C(w%zzL zwrD9hAxb@JAW`jUr@}>+WbKJ4fr8pE;K*6 zw4XEhlSJdzJ}Wn%nL~?7;_dWk|U|xT!rI`NNUMRDcncy?kdM%Z*{G52O7Em0Ex;% z!sS?=dZ?aZQbw5BT8wpbr})oK`oEg`c(hW)l!k)SsAayoA1 zDo!V62h3qZw-{1SzuQJP(jHvHac;I}9EmvsTzZQScw&%kh<`Gon+~6P>USiLmLps9 z54%cHwsnWb$z1;co26h+TpH+SW5pLNTwAJSr6dleYHZ=gH43f#PJ*ir#h`+)znWq4 zTe8|nh({I|0?Y^_!-IC54j_@TXVBt3#85%T%WeR6#Cn4tBU7pcQLB_5((7;ym|Mcu z?ZoMgBdVTU$?LCF0Ft9h3MN`l6GvmEIlnu9DWk=3`s$U8#Ts2EV4$mQ0RVdocE5*yL0P?{ zDO!+HnUZ#6(~cgsl6fud%GyfMwE+NNNEl&;K9#~;!->V5np*hQc@^yH*C$d#0$uKO z@8j(!h8C78>myJ-xih z9I?GkfM;c6P1>Qu9W?{1G|^%aE;&S#5cYQe04eS%?hfw(^mvXRrLOM^N|!ZJ46e)Q znZ|l#-SW&Hz#XKK?^t;2*q#hqT%b)OaAQYj(=L9`G&w&tbb)%8Q`3B(h*HT~^ffDr zwi$}mDus@UaYl?HnqUA9=wl=e-(((6`uP=WnxJHDjNJ~zS7NtAhI@%PL zh)kdo;Yx~-4w5PZ-fXJT>y|GQmoKhZx85b}n3pOu=wPIipR$-Ks7|fVePx@?L zOCYsjqnUP8D;{oLU%<2dGpLmlkkf3!c1lCX9 zrrFSfWSx;JB_x7%=`v0*7BLYRQHJy#n)+GQj1Q@JW=^Vy7{W0ec5GG(lpwUU81)=g zXtU{cnOw}0D+_`R{iZVQ63+7`a?Nj~w&EELl%0XgWvK+Gfk^=cBw#_P%QuPGzQc zrZ22)Gb<9cGu$P!sZzA9uer6D5~LYSz>o$N66NYs$Z@9x88~%f2VCKd<1<6&;srla z52op}M@A)jJkZfKHXmOc(nPd%Oh3_TXObYyki{Vk?X|3`ZV0&Gzw=AW^W2ws7+M=G ztTd&lAdd>QAu8`Y1TD2KBrXzDs2nJhB)+%G5qPV#7h7$ITrDL!l;8+Dl7JwU9vVm^ zXdr-Uh;jb_L|=n`_pcK`q&bSmJkFj=F+zkU0M?rqQ8Joq`c!vE@i3D__lDt&gf~SGQ3m6BrefBb0Uy| zqj19ERfUK*91d>oVmm-_+xu+M*BR0Vq?IP|3sfC90np(s6yl5kazRgr5-7}{-aN5L zY3EvH!6m{N)R$6Vprk3ophV71=s(6Q!@Lr6H*iC0Xd| zWQiw<7(7$KP$Tmr-R{X7SnGRWb;oHr=IC4|+`rxelq{4l_G(Jfm1!u`C{kxbfGA=N zM1xZnbGhnyr7@_WyxM|Y#5jPdPOM3VB;pJo;X4dbCG{)nchM(Bdh>+z>!&`R7LTYI zb*Y%t(qPQE9y3imM|@I7krgGs!+$b29_b^$S1tF^jq1zovwKT+t%?>D>J@MtY?KqJ zwXmQyp+w45NLG^tN`Pt%-M-9!l{D^8oZThVIK-(bdG#+)Afn`Vg!e!ckn$4ZkU`Q+ z6q>Iu#ow*HH1$D{Ff3mI=yUX&Fkp4iO0_;*u|ru;Kj>wRki!Ie9@1EmrR}FOyK^_G zi~Q1CWwtxkh*)jFQsR>uPj(Q12*d)ANd$tU0)uGXi+rCbd|TdIUAEh;sUq1*UvNyN zdWxKLPk0~{h)$&H5~(#tFy(sqF$KbF=_HAmuHxuJs=f6h)&k%V-*%^&h;9T(sDvm) z)6|(ttLB))8mh<(CgE$k`>wXrcD>2_BG<4yEjLR$t{TmUl)vq`$cWP{%TPoUxDL?5+9}3M@-4CHI4T=E!MAOA1oyA(; zcE3^L5nfe2s{6rI*nUS&-wScUNfl0!v+PSB57gU+X;cb8p-NmTe=xEVY(TSL#@)WI z3~bjpQ8VHx#ChIkz}6~!2i?H{6ih`uQB?U!?`l&+?6+^I@$?-uk!jUW6m?O%T#y&G zx_*8fJY{o4jyDy?vP1JL<#!qz`#-acKen3!MM@4`4!}i+eLMdEM;A6EQF_Ew2_9o| z!??ZtKJHO;%u_7RBx0?vhtPN(a7m}oC_Bxx@z+pIM{UK_gYiDwp4?$c)RH=l9os8P zrnRyBL9(?@UB;-h{SXUNgH@yNOX#u?rv0=hX+F+KJCSl*d3NVvNP*Uze;SZ)S`IZQ z$oU*9)+DlQluZG8_jrzUFc z-`fYsO!!;U3VP(6cI=AAM(vtp78IFMNfYq*S6}8Aryn`|(U zv(3ND?eOz2+xIWYYx%9;cineM)jxi(*~d(M)BWsv(|^m6GpNTzV?Tv||J5yc_FJZ< z&AEFbP$5QVdxcfkO*ja&v|Y=|Z%#5MaDYe~ zK2?v7T?90zl0gYcRL&RL%(&$>UTc*p_eDofvI=z{yBr82jX`gMjed?wS>9q1 za8o7|;Stq^K(#MH5ENIOYeG26)A&rIw!>Pne^Z%2=e9D5Nobgqxx=9j~3WG36nDYZ~T}Z01UISqDBg>t%uNg-i>JC}2%y^zE5|)xWWtG7R zNU_Uu-b@jVdj$lsB!WQUVy@cDh{AZ`_hHgc9;!34${x%Qf&iGtcJt{@S+^(Q7;j3b z@`B;?6?8a6jV(1zJvd5=s+L{h;}_o21AQF#1K>H2nTCGt&C82I)PU>=D!?bBpbnA- z%E}z8B5KVkD@an(F)@Vnfzo(QB>EYe^Zs?OYP#$ur!U|Xi!;?rUGLP(FPpNS7!bCy zmAQLsxRS*{yGkN2q^ zCk!YvtjDItbKX6N^%{iv^Hoh9ACn@nP^)O8lWEvWY34SnJUC&0pRLp1C3CA2h8UfL zsy1}cF^s%gq&7c?13PDrzl9f^k&-F;nd;LB%6OG%bjj{2aSCYEv}Q<%k}xC|QW>ld z0-5f2-C8Ya5#9|5JrlIYl@2Xa-Qsv-_*TJPI-r*v%rw-8LFXv;uBUW|x3f!go}15i z`8J8__2?e@HOkxXoGLvr_|QZ6%ymwKr{0^m$|@40X`sX?*U5;Z7)rc!6wOLOOkeA8V4OFdu0K6G9E7362>ho#(+lCk(&3b^o; zuB}8{vsGd)Yo^efSz2AE$4`ekh~7?zobQ3vDkcuiA`+3;fUHc-^K$*eiHHE{9VR%M zw!VemF60weM&B0LjA+1NEpQH@;gQ6d3T%9duec z-P0(2NP3>>Z$fLK6*yL2dYt2l!Y^qi5Aqmnau9R?iKP06x02RnnKiqaZN_tO;AuAK z(Atk1m%(b?DU5Y%Sb#AnPeH79xewkJ^4mm}J9^+`$MD;u_O}Z@Xh=lxlhaqHSCZ)s zMN-kI+eaL9$P{QcAW{dg0683P?V@r!CT$adZ3$1XVtUGzB%UObS*>?ummE<>#DI|- z1OOm)0kVR)QwYSXYH27cBdC)PsA_6}j2p?FR2GH&1d0vH_;O8Jlz<5YNRie$M^ykD z?%q;@6ckXRl}0*L1}QyYZ56IZ;(+})&3>Vx%iUX{uFSYOf?t)Ppr@8)r8Mfa=}|YA zpkVIiAlDnN);tvDEZW_rNxErn0k9+!1dJ45h>jg}LvMENvexSkw$Um8DQXGSk+lh# zk%lBy661Xp^yijwD!L3-Ov6pIlK^@dL%I|0wzTHP-L8H-3_q7;*2^hSc|BTB;aP2A zn5zAxxP`X47?hAi@faSOk4w@YOMfrqCUe9oBw$$iw1rONsodUD+yUY3@#WK(<*teE z7N0bqnrQ33c{~C3el;#Wj&xL&7&lZViGvSy_om%EPnrknIYX1!uk5%!qCX0vuAEQs z14`TjCgFHA!lN#AdE%&M3XUqIj>HmF*h^x5pX0{SyLO8)`J{UQ{{Tfu)q3Fn09xnS zN{+18^^+`gM>FHJ9a(H)X>i)7@+O^SX&9}%q>4pwUP3~ujc#<;iL))$wYOlrmyqV1 zV~?a0Cx8^D*6D9J5~OMC=Y?%&_&WMjqUfJVa-U5rDE3z2cy3+8@dtSJ$n|x9@7oaF zyWSyo1R$L)ZrXDdFZH;zA<$B1R1py>GCbgTz4U_7Nz5)3;#3q0l8{Eo82kXDE%>Qt z3A3MBI=wa$OqDq8W*d|!$vcSN$xpEdfc-1AhmN}PVDC+)T9m6DY9=}XGl#lrCky=c zYU8{Tr5{B2N5cx&d!!OCS^oeQEK3%{gmThhc-*nlI8uDNd=ijh^noq*K#=YrcVWTi z>!f~Zv%xaIRHxucrMuAKV=7+BPy#>4RG(M^mtT!;1(&*ii)0R&;yE%(NBy3jAm_Q$mLVJZ}-Msz5+7g5gIH;8v^Z**9jKhiId6v4K zl4&=pEO0=oplu95w$X2L9zr2!KvRPm0pRzsI? z3_mR4anj)EB6NvE$TefM3xZqQZ9l)A$70F6v81qpf)bSZ=@D3Ad3L+!3Y;N)frY@{ji=VI*sQIMIe8ljg zd+g|Ly_46|r$b~<_{1g$S(p`ZJrwje)?tVVDI<t~n9k&f+SKK}r^J=FsJ``w<0RZvG6WmQod?iNr~o!%vYz5FlEZe(4wWDVJ^4k^U!34{|dGZ9k0 zXL;Sd2}+gM9~uF3ccp((7~lNecE+ z;$A|AtVful0qSSc_oy5Lsdca%y--FhwDO|?;X0zTU%B`1uRfDIC%;B%yY|neKn(-{ zOdTMYBpg8_fv!*Q#(S6L`OC<8z?Dc`5JbvkM@S|_ji$CF^>dBWbU&iGQzuc`4he=( zK&rj>QPG28@h*niclvpOnZu_sb3y@8xw=XMQ}-%YI!6;J8!IUHZqQiwL2y4UYFtrP z0VhPs=!Fv}g?#q<$QdKxvZU)FTBfBu7c$dMH`Dd&g+htGo*?xEfB3Wk^P&vjK)a%CaBA{{Yk7XHW4= z@zos7OtMKuhh@qz3h(mXzDaA$Y)IM|#S$NFk1_Jtw8o^j7^NXt?Zli0*y#~Ro6C4_ zlG<_m)<+G1Cm(5w*w^rd%Juz4_5F?KY*L)b9#_ltwNCFCx6D^al(DF|(5mjWyN*X$ zqv%tKL;`$D*@)Pg^^!fYM_aRHt>hjFlj;T@^H*>9sbjTyJMhu!zB`x5ingx=d_I(| zwU)YMq(DBB{0FM#HgM?af&O=fee+YEZrT@bpzKnR50;>QR7JlIk3yL%9q9Hi&}>fy zj|Ri3@XQ*66Wab|MD7Oi-frWxkfy*N8=nq97p>lB_bxQTySXVPO2mW(KqD9mBoI1w z@SsLZW-}tU95MkB=Q1Os2%00kar`NI-HY`jI^x|T$S&DW3a&=OB#i<2nre3f5k?Wb z$*xrH@zY-X9cBHoHJI>uU>Qy&EGDaa(xb`uIRALnr)Y8?!l)y+J zF;ye7x=gZ?cH8$(yzNFoy?IXhTcO(@wZ@e4RG>ggBqLD@@gVCY1ds{RsRApDIri^g zZhD-1FbUGr=x4)Qoy z$s$QC9&Xk%ObeT84&4Q>a(Ril{&uEw7p<6D3ux0Czy(C45}`0iJ7Zw3gYM2jm7J>H z>iG*p&jqN4%E$mJ0Px|4!_!I}Z}AEIV)_}HFwBRa@hZ9ua~z1thEdf_v$bB?QUK8s zBm{Y`p@AT4rwUVk)yW{Cxk^dFL~QBWAd^G?0OdA~HePM_LILp{a1c~*FiC)5bk(Bu zv(j%|`cu<7?x%H|62@>`V;u6!R81@ll@-+<^pw#&Y#e!)Vyj_mX=`v5nq@XuH)Sj@ zyb4fBkTFuQC$AX;q){GGnq1jiHoLYI$kL^xEhKmn3WpPpm{O;Sims1SKA$>+(#(;D zW~R;=s83fL`KtA`kP2#K0!Y~#%_}QNKEVUO0onfQ<(V>&+X1DO%%mWAV8NVB5~9-)Oo#Gio2Aw&xvn50tP-JRHG0$MkLnW zokjd4I`!0y(MgST`kx5GGMz5dM~BwpFHJa8?@Cq};dQ2tX+7o&L%0KVhMdQo+@m_o zLyFX!ctTWD8k7JsLNEZ%7@T&{^L8?<=ON1!+f5-)616s6asbs4ssfG}k&YWF2h{%n z!7tS(R`86$faAEH2|*5Fufl3(mX{MIMW@4{VFfS`O=6yNT;Ic848k6dB9+LprcR+=h##AO!b{2r4SnvZJO(7zh+!GN<5c)Za~cy!8`5 z=ES9Mj!~p z>^M|w+pVLyavHU?I>Mb>4YnF-wwrNDF1n#42s=!PIFKT;-?3iL z>`v*if0+itmgCMizU>NHQL9QDNF&6eMgssbCkokb(jVac)2@|e@ln=n%Zg|0!0|ds zTUS4k3_;Uq5WxzC^Ah)0wZYez(Yq_&ZRl6$uJ2s8ZAc+3A!|}bpm8NiB~AcjD`H64 zO$;-g>97GTSXkSo2q5currdc@c&H^QN)Ez=h>6CFKdn!}y0bWBe8XGNT;*F&is10Q zL|9%bvDLvkEM?e7P(sNYvI0Jz6MjZ{PG_C&&F#xKZ@GE-H6vE17cMgDd&D}GD3FH| z0SiF|Dk<=)2%)vE^5y%)+jbAyv1naXCH5LhKv^&YjqyzX01^}knS&LojTc`%QRg0o z(?wC2pBc)@Jfa$w5l1U69HyQx!o)7@Ohg(RU+paOt9518_x z1KpR~+%g~hx7?+G=#&-dQAvz;NIrD+lr#2v>Hh#ntG!1{fnvB85tFfq9!k1;vlPo! zG6?S)MC&QqqLUM(d84iO|AHg!}(o%TDFl$Y1Xp420AU4 z?rnZ!hV}N?_TpTAQOjF>DgC0CAqh&Cw30+>RCuwKVN#usVVkwRCU1@ky9LDLsZ3i7tjRP75Q$!tM)T8DF2fVDqOeip z_C?Pj>tCu}-_7BhhTCllP(oG~l?_Ut3ZURlF{lzmK`;dn=RZt&BW|ntPH2@rKq&mf ziA!rTFqFs&!X^?uq>_%lv^rDi}coRyT zyZDKEBE+*Z=RC#J9K}glC~+s14Gtw2=~rvH`Feo+i17ma1YB-a>xeC-C|XY6+7E#f z@7qGfZ+eg*5(wFZ96I(#RVZ_3;u-i*Nk=AB#j$_ths_W4n6YdEy*FHYgK&yOQm0Ty zW5#m5(t9XTQ*ApWNhu{!ALn87qHM!Hz0MMlr3C>ofXC9PKcl@+$+?Ty272ly1uZUa zp{tJ&XsaYbAX+%l77CcW#RlhXfh(u8nKhTPq*^5;5U463?HK%OKFr=d;l~UU(Trj! zRQyKM5b7V|Uy(X*Q-&rXSB2o&W}aG1C2bQVl<6T@>?{#c?;~~ql6etYr9xW($xsor znN*xSj>;Eh*9lFLaF`mDK|MkSJu_DIh-bW4Fy_qHfpp^sj~K#Xro!+dxqJnt!6cw2 zc;my0#?aJM7Wb-e?*8rWIn2+f#}{p$+Fc~~Zd<6Wq^TsO#HArJ;1HyVGJ-K35kQ-4 z=w$YdHbHSq3tG(MB=nvfDARPKFLk>xVi;t(iw@3})OA3&lSPEm31(0=WRp;~Hq`0N zOC7229oYiSrd-r;DQ(vY6ONDp)Oy5;qM^L$c)($2{8>9T#t>u9j>cZ}J<@#fg|=bO zv^e%1iPsI)aN?PJ3#h6=AL!$1r)W>Tv}kYJlD1vF+t9RXfA%W`>QCerpc0*mI+le1 zq0*7Cks}%s+Gpcp!|j1MLBMpFR0*hf&*59?s~4aX;MkrRCuf#p z-|fzJgllQ*S5Nd-!;Jzs_>$t_^k78|(Vp9^0+-w#WnYP;jbEW0BhzLBi1oLkF=aa3 z-GER{B^+30RHmk@sFmC!Qb!~#vLeYJ+P8DxLBy6Frsihp0{yFGHK{t>Y`C>Isai+? zj7Uk=RS~Ddwvpx;!)RekHyY9)loCwhKZj`}ZC1ut^^HmCAE@~LHHdUD;Te}T(M;I1 za8FpWRlsFwNsbWAP?=fCC`P3C>&}Dj_E^U9va6d5hTcL#kVp$qB;%q11qAK*P<#7Q zGZvC{rD#ckhyf-e#7r58+rpNaFa8uQ>7Svv1h{4y(+aE(lisP4hK{Y|mvC_#Ka)`9 zgBCvax}8qC@M~?kmsUWb2yF)mNiHOU2NbSIFm_?mdT9AMf}A>p8RIe!kr)w18y5cn zg)RDJ$ur@toAO3tr#ON~BtjI5O&x-*{o!Iyhu6cwx*3<;14sPwK2@*guwn&Muc=?e z6Q&qvSMgs_xuXTdr=qLGW@>1njt@1(PRTv-BLbxrHn1e$xZ{Z23#}2U8jhl@Oi9P1 zhRVu4&FwA#7M-&LVMx7$=+-K0L-B!Af+h*M;J*n zvUr)HpEl>p43~#tv>5!}L)79F)R7T#1k(_ap|CqaJ;=}-@I;1+Qp<&l(v0Ael)w!Fyw%gWMOJ}o3H1dTgJ(>)zk z5^r{9yq&peAd;Dr!yU25uCScRnmWhoKRooCsJL3;G#OU5qLz-1mPx84tXOIZrm3s* zN~C4twUtfDxv}rS{{U!cZzZ*E;}Y zF;dv%mDO0o;}wH}yPfNNkk=$EKJOh1E-SFDVq*X-qkQ(@F8H6~cY zr*Vfz1elk~JvBTxX`^RXX0&Vu>)3M}b0;i@Zo7AFn^7lAju3SyjfMe(=mM2ElS-{p z_2rsh3sO=}l(q_hgMx~PAQ80UG{+e=KpkS}PgimuN^riXWXz8iZl|yEswR&NqLwMC z$3Y_#*m^9tv7*7tmSo8OWR=3>|Yp-ry!DPOK5H!=6QQ8%Y+1g9C z%?uM7Q4)BAAH<{8!i86MYj9`+NSPZ9ju3c`AmR;e2hh(>nZqDtJU6P@HiC{{>l9R2 zl{IV=(oQ~7r+jEuht7?hj`|Hr?rp*y&vAD-asX7V1whEups6~BCQNh_ScSbd>#?{c z;ei4m;n11ew1dMAF-Oy(T_Ec(Q)nw|^T$wf?h0wDj1=@!U{6n2in~HoOtMs1EY~GK z7O)zdkONufc-~2LE$%LD8&Z+2D0Rdk(k3+q%E8kzHXL}X4ItVf`Ck$g?Hr-G3S(~wrielM9uc#43F$!R3crdzkbus>yMWbhSUG5gi zy&A_-4{ju0@ml4`{M(l-2I4^~Z7GP83o6oZ**I}EB){2SZ*IX`PqyOHH7T#ltb$XC zN(ggN)%J-49laGx`G@em^rhF@n0m{MXAHxbs$s)$^{2%tDyUJ}*K&N5#TrBe)W+*5 zDmJzIcI2Y0#@jeT6mFVKfe^OT0#r36TEQt+pkzdYeVy*mTS20L5{C*6xeE@g z4NR#HDJx3a`&Ymnk|>o>8NhzDAMfdG*ZV}=K&ie6ODeNXi#kIB+pwzA_OB62inOF4rXZ-3 zf@tFUWc)UIA(6Vjlr!&8t0u(qjU_}CShgPw45oPGTW#FzNd((KMa9O1--4a|cKYis zdfvfB4yd4NK?!p}aXsj5O7Nw^&`@nh0Jx#Gw&bSCLDa8OfFvbTq^dC0)D9=`rFY_E z=zpS}Tk8%pj`~l}WgzTNk45DSY+R!58_J`zE|;R0d-j5;YX_wit0u_*AqN5Tz0zhZTTQ!POH7q7-{`22RtC8;4!i=CBq=fGCM=1VIQK6T_yh z6aEx6=!4P^r(aB2C#XFz>GmChHAZWL46LZ9GeZP%*V9QF&r(sY&m4%pRn4~_5J=%x z>Nd@WY|WTjzsg&91i0gl6&8|}_%*3oNKT?+2}mgd^xLYCJLEjocXaqHtnL(}i5yqoD))a^%F^L`0aE*mZrUx&#_K=CxE&fDe4rOwt; z$*s?how*2hjk{{ze82LnsVyum3YAG73Bm>-ncGv2?A#j{b*@M$BcpGfUru`UdC|H0 zcZKF0yN?MmjLC;m;!#iu9wqkxiPWc>J1%EBB$a({M{686t7cI^#LOuVyZ>3yF2c%U@XLIZ8;*?=BzxY1FJ#|gbX@nJ@jooC;k~Yw??{sU+Oc|7C#P2#Vat3cuj-iw9&MO4y=J#sz6(R zoCzwyt$Pa)Z_KX9E}VTq@Rgyo%4JC@Qne(BNdAf8stNv#8LTSbEcplgnSzHTrC{oh z5>yEQ990|&MjK}e1${pHIq7Gu%Fj&sL$BF(4wLk+9K!Q7cy4@~9mATdF+C^fXmGgc z+RKNTCRrv_mwU*n5m+_BzH^`4rqw3H!b1C=@nAR*Kr(x>Q#zKCgn@=LiHZ+fHThfT zntJ3VZjh)`Y7Mpom8({u7D3Y4DpFvpRw4m1y=VUbgynu7n0|Yv$e2&6SaQ8?El*KZ zhm2nhrZm&X4Z}QDhFGcPjyAA+N!zi%BOA@?&#aP=Q)uZ{J~p0c5HNzK-EbvD^rs1( zCt(`c-!ivLX}M)#GBs&&2_^}_a!^JXkgPiPR<0dC^i9=nvUTq;^f#oKo)3?Vxrx=` zl^FFsVy+P~Q_N!(RMV4rb3N^|$eKf!I+9&Xp|Fyt521}C4W>4U6=pt>KL-lz*Vnu@Pg0fiO_r#!Z{^ik zRVzr1hyejHPf0loz7ZvfHW%WhGK*}<7H;WSQWT;Fv=0giNRbMHMllj5C=Z@*HO$}_%O$(eSJu53~3PVMh0 ziYj)F+lbn_A083!9_nPdbBwmDWOvsnTd5?hrVzBDNyUG6h$>0hg+$x2ygB}LmOYs& z?Oolo$+uEM5S5iFy?y4Om;(sY7@TK?ExPy9+=bHKqtW4cMv>v6nvN-ze8OHgB%>5z zuVL8p1N%eCn95&huz-N#6)8;V)P(^c5@JCUz?^F@yFSjJ&6s!d4i^h+ND5SH(xl81 z00sy#gvJ#E3QCwGc~V8J1a4B+SGBbG5jrbmxaLj5vALwfC~-Jv#OWcec!fPj zlAceTtf+rWeamB@*NAryIlj*G%ga2))jZHj%V=7O2=3fUd?}a!r9c=P5;{!utF}Ga zw##>SEWEa5mXe?lLv0}?MQsI=wSlQ;!hYg*o|?C;N7G-UoKMvm>BcM548JW^PFRl? zSq=+IVqs5-h>3CK?Gp!dvs-hiWnxur%#rR;Gmpx6!VR~05){2UgP|o-6(LYk1Z_-% zfQrIa?H1li`Lt-#E{jp28l`NNVd0X30;GMZR1g6(RYUmB^y8(S3B~gMGt!K^L4eoh zY%3n8sTBBiD$-6;DB}moF_aYnC2xH|HnF~gfo)!?vkwbYrPh_8CFYhA;*zAem{>?s0Rm!VL=#F+ zK)>eq1^h8^++wc^d@~xN!6S&xC2bWOuvl&v&#qY@up;AnH_^=1&urCkm$HN4Z$e{H zN(x9Zs5qpkBT(3=kTzpjs{6l{xM@s5E;53!l&Mmv#H}eQB>KSPg*Sd3eP+seQ`J2t zH&Tv6bmYYpknkRFWk-Fgp{1aZgOqg#1oS+&3%q27Ed5 z9Tar+5Y<&;DkFh}l6jGcsM1P}qy_VqViG~LBHS_Hb0O@%A>YikV|i^w%L!7J+iOdK zCCwUAvanPAB?RaSBOO=~08HO{^Bk)*7PdGcXhNM{ged6>Q3*ni+9wr-NmQpy4O39D z_50VXSu+w`YpU6LhdENj?S)WLWyq>&>SqS)Ph0a+qbzONq);{uKqs8a-fyF=%)4;@ zM%BiFI7Q2VY}hpw5sw^vqO$8N-(Z%9=Jb+wgth^WnGpx7YPND8;&=G3=d61Y!te=j zTtg7UAg!LVo|glLO|Vj2)Ksd8f%4-3+S=H5zaSIznY!!nC5y8XaDHG64mvR%d}@4q zKg+FKO5S;v!iWhffh6o0@jD{B$$yI1;uw-ai@})iY)vYd)WDNqs$dW`gkX_2=UbcK zL*Z)+@I;@Z&E3opG+N%`Hlficuk1T$H+Q}nHHc7t?f{)YV!zoW5$D4;5xVNjtH-%@^*h?olI33y&Q- zxDU5!5^>u=Wp;y<-K9yhxVCk`2>}2v+6M|{rs{9v=Za%*QvFE6aOx;G6p~oXu0a=2 z@J2`^8;c!y3TLoA(o$gCD;>YIKI5jNzwOP!b|tg^=AXufe4CiPc+U(o^#iLg<4{WF zr>CaD6;@c8O349dlJ+;yfpOul23bF0d$E>YGjziXN}6%E5#uHl+Jb>Nbc|zYq+@)p z-|&<)0l>lpZh(%$x5LpW3HjAw)rg2Ld*aDv|R`_bhGF>p>)tk>UYD2|N!Tx*2B0dZjxw zhd1L(8#rHg6srFKiD~bPH@CR(<}o?g*6g*2v`4S*pa9P<7yS=JCa_}JFEQ6(l-RZ- znDZtgm6gC%QB90a^mnFVH9q=hxBxH=b=3FccDtFCWKVaNcIatf5vd{-2WTW>L4kp$ zT)J`L;v*mLK=wr%UrGHgt*p#-y+g(o-mdLW2$n)^8=JEbTTAx#+u_VV?NZ^w^LEXQ z2-L2#!_ZWvl7DiNYT#qYH8{3Ml7Ygsb@(1BOXc@c$}}5Bg{*t(ZR{QJ7Vg2@U{`?f ztyq6}prh+jb8m%!JcqPJRsR5{j<)p^qCS+eh8dMao&b~(uWoepP zif}yGqIMe$;^HgZf;cV~Nxjc59oC-}nq5d(L=u=1ooP@c2_*oetY8e)R#JwOs2{p8 zC$DS~^NKc@hp9Zli&gbkB}YWEMUdYL#AB&yWK%UIRLU7CDmi`{{Wl~LP#bK1jONiBG0Z|v`&O*5?kZ)E4UURA z=AKBRXx6InhlQTrU=BU?QV8$|w>s~d-DON$A-l%XzUd8x916l0fl>r&T0zCYpR{8b zP%Rp6P#a1~DG8Dc5j;msaT8Rz_=ofhE_Dl~nTHlyXr8ky(#wlsScwIt`E=G=StUBW z6Gd^iz=5}%;oc@uX>_2@E#Ok1XH#VOapR^zPxN+dBvhNbj=0LwlO!nVApCs(H0St1 zbz=n2zLn{E5c4X}m*mVeVw3<%($#*Ro=3mDq=q059etd|E#Og=!Z_pzYq?K;B2uRI9APRXVbEu9RS+J#WZJxM)5dYjTPg!K6^KF> z35*h#i5p_1t7921pl=$lesvEax=rG(-Us`l8(jYYj)0@_tk%uYF0GwT*+DpM*&-;m zbjQ-JbH_R#Ntp3YfH%zIbTsqJO^NkD`Bc@DL18xMn$txf0sZrE#@de4t@c(+gdw!z z3>7*OL?5~d*hVqwHG@oC7!p<1G@oY8yeTcxuAk?cd=n7O8G9h~zXLfZJJ3h&%;Z1$Rnw_8@6c)Zt9ZK?h1n#Yct_Fh<%oeHeto_+TbF zaWS*jhTJnTW;`DVrmDg-UqW(I(^65*zKae@s@LDPDPweDx6O|Ba66vkP7kvC@)`s^ zYLlfV19H9-J`;!^aOs$!tIT7HR&hLV`0VJS1?sgh{J+)Qjh!&grB7c&i#{)gRAPBs z2QkxD&YoRLM->=bz_9zuHjS-fRQU2$$?rq%sUcy{2!){~Ay9e_&9oP}XG2pF3fOTt zjkD=ZhFr0VVc*MUPN3t>c4lJ>Q?2)HQRWS#ZqVA_Pmd)OX#x(j>l77GnshlM3XZAj zX!>uB)JUk|WyEo92Zy{F&)Qpq`i>bi*xTKc{xYbo&W%x1u*|QRaQYOR0La;U2vj$5 zEqb%8ZK)O>=^%J`p4Q-zooK}!?2Q3QrIJENA{NIDMpzc+HVOemo7@a!1uG(wipc7oS_ zMgtBc#TSl(W4Imz>RTx1EWaYWIfE`@P@!#PhN}#jYU5dyU*1z5hs90Dk1^-8dw%xF zl0LXOZY<4`lrCN=T~VnOn6O9`1WO? z!XcUogjBP|ShYz}JI8S?EU-$*(S-$l)(1;+5WC-R@eNDMny~qyVV?`wR}w znw;LrKRb1B6NZOYl=-OY1P&mDVla`g)gxl~9S#eO)nN59$170O)X~WzkWt#6R)o4= zU6)&~mmuq}CI)U4`(a=asVPt#Ku`*U*9RH{+%OnfL5~S3C#DR0Iw>n%4JcNDWg7zk z8*<;d8iFoIu<+fr6O3c)LFYgiPr{Q8OA3K4F)ZW|Nh0@CYyCd~+lIksVWK4@3`H6) zfMYncm@8nE)l}5!4MU(>ke_9Munl8>qd*R)kv8$LfaiEpqDp7OKMs1Td))V&agx$h zkOGK>M-kJ^Q_g?O_=FgQb5zR|?Ie~W9d##Ll^wmK>$e-qUrN9U1bOqeqrLaATMN{p z5BR+7q<&`em1C9Sjb26VBQYk&QdD>!rrzCokhw$@`BoX;2vtnaFH?!++A6e-9a#V~ z6#@5sfS|Ji#NS@`(C|*Q#TTH_K+KUx9%H4dj0SmKP3}RxwrjUjt-JQOZeMF;9)nIC z4Q~_Dyvt42Ur4<_#~&f(E~L}ujI~J_%6N)=jb1BLPYcCZkxxxcDKdi=_}HNbP{mD~ zfZI#8mynWx<~l=XR?)DHGGqZG0tAvoi5Q!`*#jpn)SHD^sfUKEfL4&HQ2`56MJ}CE z3Ik?TumK7LiUq$8uA%jkEFzOB;$E5Pat2q)xZ_h+X5k!-SdA51Q?>_~P@+oGK?LCq zM5;W%1A}(vE&WC0j^>-Ytv3E97UD~ZLW76|Y5=ckh3EvXM1+B)ld5O>e7&*DbJwlY znz?Z8(?Lo}L%|NMVp3A#l&f~slc{Ytr4N0`Q7}bYK3B%_-XYY?2QXs2AA=~+;Pn&6 zaVcpqdWcOt)v{rAu`5FFIwD9Ro8MIgGKLpYM*{CH-EPs=k(d|M;z91hpGvhQu=8p< zfJr24M}(3HFkp)8A9l4i=Aw1!gp#NvnII&j$SMi(Mg(!dfGzq;&e?!^ro>w{;qc&< z8JdS1!m4SYR1nWymT^{w8n{X--D)T*6}GV4n@Ze(4*{F!VAt}5cPlOiR?CS}r&3$H zWGP5glZqW|i5MB3rhs|-MeAg_fQUOvm86o9B<-9C>ceQnMT0QG(vGk7M-Ru(m4H*? zm_9u?eMie;@hvq~Ko%sWJzN3W-@01-3@X^?Hdab+7fWuknEsmttqJp6Yk}7lOLd1> zZwOwJlq>t>>`(c_Q0g&7hoRjS>IbGAR~X89j}xiJuoIcFWWeznx}iMFNmPDpVeC)o z7CI+pju6)#Qm)bk)N~Txdu{joB~`mALsu*^+sbVS&<>bGj?Tp?$V!*6g(%GJpoq3M zS3T)clpO(HB1r*XYH=F`5HULiUJgr*dWF+B!hHV#mzB|W$+LJ?T@K{^<3X~+T031pbkW#4c5Qr z9o_9>+4mZ|3V<8bkfzA-0=zLk5(nC#dSZd6E&P&J!d(5l{eUY-LeAYHhd@0)HN`m){CQ_hqAiVb{Z#6;G%7g;aPNGzWH}=RQVv_@+jVD>X zPhfa2OmX_WQhYL)#X(cCr>;oVWMnB3b~oC)$hoo8nTMQxQRW?>TRD_mWoRwjp-mEn zxTU91jcAm?Qa<1~#1a9TgK~Y-Nd3a_1nNi1#VMkamFPgQHfFhXN!+C^*>$?O}xyLlOlH%n&WcsSj< z`^GUkUjT?YL?yo?M$ zslJncGU_g1rRlAF)e%zFQDarKi%~~dBpz4#K)NUrC@VFB5CJX8vo6ZFle34Pw9Alg z*nIOQ|G;m?{P<&9^%)-q6k6<64}yQi>LbJEvO*!nVvP zca1tQTSTc258=ZA-|;NS{{V^)Q#v1rbo&^}8DFU#Cd4pznk>alO-~jnPQo+gw2{X0 zBddF^vqGpm2wQ@B<-5J3=K0Q5X`E**I@%j?1UOntiBd_>rxfB2wn;t}g{2^>oPDCwnvb(;>O%MxH1g+y^w z*g{O=(y2lgMDrY7088pAK;?xO_*B0(HM1_&dh z5eBn#*Q?n}FJo_q=Aj-XhE=*TMz}G6#D+;1RCC+KSPL*bFT1oZC&FPutmTW2j}8W` z`|#WK7ngD$;#HEdTnc#UFkF5bi~-KLE@U99Yl<~ zTR_7>;19$0^2Kz~O-zn=4SS6|eYf!=ijeG5B_eAxN#_*}-0Bar;q-A~UaBopBBlwR z1lq>rX@3LZ+ls@56oE;a#L}6IG8+$p*Is!}Yoz*Oo8%#nnWcsMe11Pq3ssG52&A?x zO&rQeVSi_Hd-(l)eUyo%ZJ0GpKEC>HaqPE=;phvBs3nf&ZV6?&pQCshjwWK{W!LSw z!%!#Z?wXbD$L3hm)kVwj{OT;Z)6cf#Bz;vashL_Y3hGPAOLDM%&Jd1VY_c@ z)Xvb8Bgp)#95dT~;o#u@F^~Ae^s5X106E#G`n|j6&zb&5%-Xx}Zu`Br_+Q7jCXVQ7 z*+HMpD`eOI*2RoJ`NsT3p02V&*mp`Y&2}?8SQ}!v^#1_MXjwqhd{8XzpxfKqf;&~A zYkKKi6`&vSaWFW-j7?!FWmb7xY>ZU$fR2QqNuG(qjIIZk>oL0dAfgsUCAUhz9};(5 z>RZO$yg3UxqT-BWiQBe1O&AXd6vvvdT576juumZ;^Cea{vc}90xFjv7lo;In1^FIc z-Dty@6gtT){{S+wcqDqsqJP%6%y@P@a4br%`K=}%sT=_fsbmXf3j%l8&2pu?s5?L$ zQI-TB5^yJJ<34mO&Pv-U0GN+|<4F9!Het_oRGmM-(V$lXrl!wmVk!@mNWHwWZ=pA~ zi{r~@ecoQtd3c$CIGNk)*FxRZdB+#skF)}%9z9P#*k*0aHDz#wYFdby zg*`1KNO#LTQAXD@$Oo2|yIH&m*ay z2_U8xc#JWRbp$VwuIT|lDM%Wz;7<`j-g<*8*5%*jIbxsYqF7~m%wnKN0Cj-xK1g-A zZNP-(Ilp=)=^%^?TkO3Sns@hz>#pZq`^_pfzzQfeddO`dWNg0iVQM6i7d$sXf!{hVGFr+CcW3aOGkMNil$v^Q^vQf3Z`55=@XdlfYvG6VruO z2dA!%b$6#dM8@;CQ?W_K6p+?pbu_bzdCOJQ%+g63RL5Z)YZ8xfM(wDfoCCL$CT*D8 z-7uEf0FXjK#6m#Z9AjrjB!M{ABJSo*dzW0fadjygO3HjHm8jw*U?d4KjsOw?imd+t z^VijCTbsEEZZPLSEO|^w1d__BBauF9|V9jxtG($JwQ@J7{8Usqrd>GP^9}W z!gcEy_iG2KN&O~|n{kAHt|a;QgWzdRN1eJAiHl=?oa%g%Y(x|kulc1_xK`rUF$r>i z%|76&J!RGxwMm1}9M+8rhSecs2z#X{o~_r$wT|&_xplW@c^2zlPDN?|Yv7 z{Q0|L-gCX%(S3Zi6(!f!5jc1n{h9=MC)r<1nFi{$x%nlgT-X3K$`b>oH7L&#R7swi ze9k_uFus=OELW$M{Uye6F@nmlJ|jblP&GWP$|Q|d9o5m<4ayO9>`yW;b~``HZfx02 z!wc^Ubtz?MM9^Eztx0#E&9hhY{ctb9!SnXcFAeBZ5=p7qqGkp5(8$IhwNE=LeG5-69 zvV$(A`j+W;s7}0OyrF<(+)j#fOB~B3O-&u+r;4j!H4wt=Y|ncO+>Y8`oh{t_*%>ve z?DZ%pps6U)fJpF3R<8-2f(d~&&Ysja1v}?|ZJDK{2JMOvwQKPz7px~hOerzMoC%IJ z0eY~{GiRSrS#KvL1d~Y=7`w0PRwTtlXD!F`+M?C&6@!azJ##eqZkzeut>y69#v8Pul+RUddxRBb#vx$%p(q? z!LZeo;sM$GiW!=3D{O1!m!76XR2#K6Cr%A_-+l7z^~KxU-XTtga88#lptQ8@V z1f?L7Hp=A3vaiqZJj=6HVf|d{)nZ+-98V0xB9N#Atvx%;_8<)}BK}+pxC*XTV`5U7 z>5^3*m{ha6Efl3n-~dSTl26Kp-^SB9;CXM+))AF4LacqiWi}p3_6dZShgcIP*%*@w;Qcf8vxG*CznM4zi&854?y91o%#X20z}`NU))0ms#7$lv|^Z70S*Ve~ZqXGG+j=5(|(^;ewvFf z&|qF9)7k z9pmLn9VtK(J~8K8Tzc*3M1G+#e2zLKRm2?{YQBSJP~2`kh{=#Dj!+tItDcv9LmX#q+~j8B1Sg#b952USxq z<1y*~04ZRf)#xzF#&pAJs%BbwA6ANrjl!`|KsI(?cf_AyIe0Ry&Z~9}>`HALy-0gU4b9JZ35v-R6z%e`MOR3^wD(r&o3WJrSwR zmAuD*9>53P%zmze*Fb_UIqLOSkK#9v;xrvDICd7H{#ypj7@a{aZ!Q?1NQ2w=j^kiH zJcak#-}AQJ#7a~YSB}I8lLu}%deo1)7edc44xOlNN>4#izz(jTO4IxCRq57M>9!}* zEE6WJMjwe*Wa@hSPkiOWO*==hs<+q|CctQUlUb9=2B6j2R-#Yw0|O2?B!YNhS%JH(pX6<_Bn4@}Y#tJRb+(QTkBUlWSdQY#PNL)7 z0I}1xuh{qIdgN$#EVI(|t3qaC0ffncwkKrbYagDsDPEp&*+di74_)zmHy~p9ha=a; zM;u0`Oh#E@mR6DoFxrWJT~Z%j?u5P8-}G4{h~?$SBa!B z;!dJGJ=&G6E=lnC6%~@Zn~^r%!cEFb%2TNT5CB%NbrP+mAV^3Op(3<^>(5f5=;xxo zoM4$2q*B-7IAs)$g+UJ0Z|BNcNH!s)?|*3KSZ)qbyyE)y;^Y#L@{kF`1YnRjU;vuQ zE&bjXw{tAAw`D;pTYcaWBT9mC$E1};HOJIVZZU%X6SWjrtgPSGZ1qn_q_7*lTyJ+L zxd&zK;mnTQ>jeJ*IV(twC^+?Wd+QfBt1@!t)gjeNj+yw@&mV!lOUm>5X2EgH*&Gtf z3R5j4Of-y`QCXQzhC^=PcIPEKUpaPZ+5+seRT9H3vO{WDfo?2`Dg$UrOhLmLG<%=k z+#@WtOENXKRH(v0QAiWU0(`4t+KKQCH!eujsET&9nkf5Z{j2z!^E+=G-QC#99(L8c zbTSaPfo?y%6cqpj6v-3gAjs4~Ae6u$4kC;@N3vd3 zX=0ZpYg!htm2GVbf)Wq(N%16bB=pr^Wxq#Rn;n9y6r{|!RZTYQD3b}NX=GwOi0W5g z8~t3)7IOfwV0COxKRUwetFXz^L7lry3ZhS1qB>k^NCh+yx>md!pr&XQggcawti%hR z;`)7j5L!8@YCTc1DnM--Sw~(tnc+gW;m?z4Gc|5FWeX)t^%y1@PM&Xjvj70J zD8bpKM38ygTM_zH!7*Gz(%R)to6zA{ZWTUa#AlT-n1T6!mNBGMOIi))F*so}>Lg-8 zBo1>EwS3*|>od7o1wrQtB}oNv5)zOUe$D%r7q>IS`^#q5ZW66#~3|0!RR}7 zoNCW#y>0cc0D_YU#&X^hEELF*N#(538C6!m4Xn!<()uYL00Gz)XWCu%TG|;5Tj)YU z3PKcuq=B+hq7$$a2_T*kLh+e75J2aukkEcA4lSScY`s$>9oQ7hTlLWomf z;AG(j2E&2E4_y~-ob|J$-8Jg&Xv6xa1~WARQ_VFjcyjKkM@orhoS5d6ZG|E#7jJL@ zARBQV*JJisYpWgW>IA7en(o?sFI@OkvZMyoBoP{w3B&+rAMz({616#W(Sk@wOu}TG z2#|cbBWD_|A5b2vJw;@0s?sMz^F4hwTg*9vo|6q3jw)Fm8d{oYyhQvL{rw53)Q^u>hq{^=6&(Zrd}fJq;__T^PC-$fM@mFuBY+zR3L?C`e=c#R?MOlcKmcngksZ!okgxflYRd|fzGN7fE_cKd0hTsB9LuCPt`(HuBMofhsqe9mN6ppb; z?8Q$?+0UeS1!)^2Od|eZx{Ledk>1z0@!^J;X+ZH%_!{yIxH^;b6ni~KI^xy+K91h` z%@}hkn-OJ{wT8W}FYkWd2U3Nz3vmd8UswYybvsGprh|P-p>pRpS41MH9d83dLkGp?w9{wCj zb!~3qd$Rf!!0J*-I}DRJ(W)*`kRXqRDt!s$N^GI{iRFw5s_G~zsIh!LqN0vy+(j$T zLsK+=Fh|&A3VgLX8=m|hZrTG!LRJtR6;4Tk+f(i4 zZ)OAwX3#K|Gyv$tVd)V-+^YxFt+17u>BDU*Gln@VdC#ZVJ`p`lE+L6#Ix1R6rz`p= zlk{!pBLc4x4P$+K5Om?rbC{znKzVw+Dv_t80$~3DdUhU)2eXu`JaIOOAwA&K+uAkk^>|bR{TGvRoR1L6oT^6T=V) zgBXJ}S~}_0?vC}3F=lS0^~QX;jaJrF@0za)!0PD~Oi*q}o5^I`7*X!XU%suc2Kg56 zS?-ov)q`qv=IxW+rPtJ5eNiS{drEb$9)W}itaiQ5E;GBeKI(^fdt-CLp5Tfx$%5TvZ= z3DiUgF);=JJ1R!J?Jp(B$9Zvl!y!@uQ^-!jK^UkILV*MvWJcPhk5JyI@=5g*i27>u z?~hPoS*D{1pC6*5prMMVd`PU-H4Q7?CJ4%Roy6GQ$C)+RH)i=x;bl$QU7-b*o^f6v zMwZ=KSV)qh0zn{nxL^_>S3G+}-mK4m^A~P%C5M?qZMKJzrD$5vf>r{I&VV4mDFb0J zV3_qY@gV6hO6&gssNGY{$%kg#I-WPgDOV2+V=owcN9Cwixgy>c@!@T*M}Cy8z!sog zb3qA0VZCR&0Pz7aj?>1nHJrA>^rcBsGoVB?GxZVm{qDhhfAYl<0 zik$52?X1*WwE-<38bBn$Fcpc!$*S1&n^%b7+4j3PVXfxWLlzT3Nnn;)>gI_(_?n1RATb3mP}QyX>(7*m2su)%C7y#m%*+dv5)^jVnWX%5DO~mg!t# z(;-Dm)%Jx*BwSC`R zr^9ouaLtsM6*_Hs=;;}X$`pBVi$qDki0}1tAnuC@m{L@F)G_PZ#-!JGjSFyq^dd|| zOimmonsFYX`kA8i?%39EsLWKjoi1ucma?K5Vk?EcF-6}gj=~vav1^T?wBknp050pA zP^1|f0)aE+4A5=t?RO0S0CbgWj0l}EvkGbaJpF6+r=b3}vd>tfmGj+h3r&oQJUbP6 zCs#95vf4I<8b}>L_heNh3x)+r=J%5%8I__?$wP`6JVW{fENF5Szo)xzjQoj;ET>VMuoOriZeJEgf=2&WV#bP*yEY(!t z!x@ohYI!M1J3-u}4Z~dlw;(l~b2ua}i( z4t_<))2mjMHlU;92WA>UgSJT%6jm~4;)jCf{JmYA7t-EHmb#k?lD}fG4=l0FutiQ8 z=*hDN(_K4TfSc{(ym8LpGRnbF1d!wr6Q}@qbaCmY(YQHV01{eACyG@A&&Ef}fy{64 zsp~hXI{Ztocy&Kaa$@Id*2U8Vin5X8ph@XcC}{&a0!&i_G={(zBr4lZPG6pS%^?aY z>5l$1>c>nGfCFM=z{7K4Q(|J2=w&{P$6K_hM$6p|)*deyc53t!CogX+p`Z>n7}e638_E+}&PRngP5 zKO`il*(6LZ%PXr8LkpF^F_R%xva@#?Vf4O|hdad1tqujJ!aWqcBR)QO9~nT2_@P<8}qD z7~8ntRs@R+0g{8iNmcqy2jy!*+G8YwLacSSylViT9$>7 zBS{iq>cI7E6cyh6-?Yw>h8$%jM3tpb0R^l;kqU`cz+-KE`acm#@vOD#BP4X5n+3xY zD$9W3m9t^=v^41rEmSoXA!;Cn#>8{5F3os{HudCpe5tCqsu4!qi&DpsP5Bq+|vILRGI;mHXFr0T6G0?*` zMLrQlgV42YO(7v;r+_^hNU)oRVss0wuWk>MzN$r-xwm;PE`IjP6gBZApcx~NUfP$k z9?ExjIK4_7X#(8ITD!%Rl&APX*8?0nsB!e)(jQeFEx>bzTBhj!FO??EFCHrvWR8}2 z+YZFxM-Z`TE~^xb#BNYFu@@F6ha0KdCDoeTx48vKxHzm0B?~bMI6+DDf=L@UxiWGej^=GL0uRi1&&ZpF3@0oC%;SCk)$XDh!`m< zjC`@Jk^Ls%c-0TBj;u>w&n-<}O@dg}6pg7JVX}|)hNFkO`r=LARJ7oY7YHZ&;I>Xa z*{CnGg!kLMo3JFfm)URuwiMdL4!9Bf>8sT4CTnv}0f(&u=2O+9@K1E*(Ow2k@lmmqc>kMmlBG>Kx~VQ0B27C0mZe4kEDB z&w;^#uO=l+e@AKJ?Tr%~xRctNo8e>+HlwGhJQ;xPa%FtHXB4s23I19$ZIziIRV-b%w z;8k@qSJQz{9wASPR5a^N=dEAJ{K80Csl3ZEjfoaE?WZy-%EHF@2d$hd(*P|Fl^r^R zo!MAXB@-SJP6jq%SemT%=?#`ur$UaRf`sVTq_^G##0LP8s6m`|<3-=rr=t#%dW7j7 zV@&5wQ;TK@sBsxG{L@y*WumNla1uHYPSshYjRUC+7!nSau~zc#+c~RBbwNvY61K52 zl_VuWC=vuHphzI?C!z;?rP>wd=eeborM4UayM*Zw^Jh>!=M^a-YS2Lh7>st6zd>CG z>DNKJ4}^4I)W#`>(e(m?o;rMM51$u;bwcs)fJPYXG5KsZw$OdN%tlSHwuZ?<6M$BbFi}!wN`^a3Y%vwA#%T3>>f_Yc zQSjnHf+L%Nl}vaKWwWzFL*tFS=4x zQlx}p2$2A+sEh{OD3AGHZ>H9rbc6BcS->eaeo2;@a@O1_sa6YD|x^!G^RpbDk;Mqi69>>l%4c`ZW{+c z2LObmZNn2BHrB>}g`Q)^@ZV4!J;FNkj^ME1cy#qNDTl*`LkN-PhCs5_RnA(XL%Xmf z3)_%(Q`%+j@!bAhXhI6YyRg!9!h%Tv40gu?G3lBl%<>kkP?uzwaV5f~6XBRAt8P71 zR{a-2(yoDiIDK>JZd=1Cq{DLy=O}P`rI487i^%!22vcxUc4BYd>+Ix_ls30-)Pe{q z))bwD5TK=e@Zc&l-gT8&GU|vr96-krj-;htn0siW^lpZRizm_1$4V5@&sR>$o+h;rdW#vw#}SAV8LuIwxfeZ-LSZsp4l;VJb5p5w&)b3H{UJ zd;MJH)w*jv$eLc|95$Yq!Ba@YPfsH{5IxY!eb7O@_58Rsv_z;8v=DuUjO`JrLW*8s z=|@te_2ZJWOc*5d(&D%_V2W0SLnub4GO;SR+p3a0eV62wyti$zrtTh6Qj!8xr5FK6 z014P6kOy8BkoUIBxUv8wl?37j+zii@Q2zjlV06*I8Ws08tAH)EivfRh_x9*{9$XWQ z)I$&{ohRLsm=G7q#Gu?ruqh&tNx1B7@wXz2!~1Fe^wYY$G1o_r)9i6X^)!kWHE%7g zeNFW7VSPD*U7#`)^K0XX`P844I&=~1R&|ykRHVT~%q`|sQ?T&;EF_I?d`GwH_F@Kb zz#1p`yVM`^+x$oAH6vOt!{rCxRk`Sg0mr|b^@pW68%WhuIf|aBBy$+N$lSWfyRI&_ z9`HII+=XvjdgAXcag>!QO=&4k(hy+r0PUEX7&ht}3M;^LoML}<9Nfp#%-NUvZ<%1m zs2v`zhslF!6Dw4CfvNW(B-xlMw}2h}yp&!=)?5RRvb2DtK~NfGED#lm@R)<=jT2qA z&Ti7}lB^svN@C2@nq7KPm*hVBnbNRJvz}QfJDF zn#G{23r!sY#Y;B2NV7X`R*jTck}f}VgRe3pB<&wIFNHd^m3M1xBq1p&NrFKmZm5IO zFsT0kc()raw6@gHR0W`rR7fWn_D~7xL#r952lPvsF#HwZ#-_z#gAA&cnxSf!4a1sM z6PY%?;ZO(>l)2k`w`+1gXLynM(PZMG#hC!$AtbCNCt%dB0}UX7i4=m%E0u?05(JKt zVm+O75&jIFNv5Rgwq(lYg(fmfhshM{8%APDBYJj^YFrQ)cWp_(BA(D0RfWxs*p))m zf{7Yc zhcV@RLlDCq>oXk4vMnuSktIzChzS)K*-5u;IU{EoqxM_LakW66BvFKtn9m!Mu@Pdxf(r|&@5!$?c;%@rY6~S_-5SzJ zfrtnCID-+lVW|To$c}cUVjI#14on$61CPp#X~(dwJ=XvPFA9l zN?RS(EbYBagxo3nUA%cISmsJwE%RtyjwJ-XY#-;$$O6U5L-ZN($MmE~+|n$@^IdB)@ibG)W#k;ytST@;2R z-oMfS;qwbim_pC37C4dz4`oNE$~02O^5y=M;?im(SFEoia3kI&S+%+BPi_ek&>}-e z)X^fxT^(=3;y$Egp0?unEe=wr$}!{EQ$W=#TN1f3%B~_GX%<&fN{0jzE!^>Ajj5#l zfdKKIap<6{$$~MG4<5R%zsEBp&tK|SBxh)9l4iwn?L`Tyo=+|64jWq0rrXKNV z-S}T=Y;Rp!LXr#v;xQv;-IIpOIlLi;8c_%Mfq^)KKLb@I>H5C6B=x%^R^m+5a?$2$ zN@*iz3;vIYt5Ljx&Bn&wFWesek0Aa30I*Y;d&nSy8z-;B;vUd2H9z)Sn2TK1mCS;$ z50UVnjv|luS^Zpky7WudYMg`7?8W?>FXH%p1}ykxMGRF`ZCYb&KDI>jL6KHxrv-vF zi)(IT23wI?Zw-nT`cza3&=i%Fod?7)#V2XnD>w7|=kj~?r5YhYD#al9hlJuFkF;P8 z6;$=<1%4quD_p^)s;Qo$as-LFTxU*IpS#6 zIL*t6ZcfpuV#L`&@9gmAOJwf^nE7*!bH^}l4AKgEMVl{8JWnO5+$4uUgK#Bo7?W|~ zZb)myP<1rp-V)Y_K-nR!A7rbu3!`Cc^yP7n6AFvveGYU$S6BrGqBMbxs(?%QC_GQRjAkWnq->Pj@23XFSD>G%xN~)TUqOEB~ zJPltI^TkMyFi@UyhYEI*E>s)xGTaMWobK3L+37D^-P_zYl`SYM)S%f)O2|ykgQT29 zz&j`rXuWo)Z|v3mo5)hVzp5axMwfHHkBp?=Ige-v?6b;U(7}wk>xmN=R_11jz6t1;)t&1|0_3szTiF zHR@4HVH#8jNC8u*h*1L)XBp`=V?LGhOm(f#}cOu%7II7GpI~qCmaFjG#N$!i9mM0^4!{? zwt|k3*iuu5oE%bAc5MU$=~W$;y3N;2y_4|#tAXa6N|y+ur%_Kw9w9J}AX`-tnKuAQ z_jg?D-%dc;jz^X`a^sF#vZo4_sbv6_5rp)4#uOuKH@ip*4k%zT!hEN1l$u16Q~wTj_*E*~srd1|9sY3bOtqmo42-ddM7 z4p(R<+ktIgw7kmi9MHm=Q-(m(f{blX0#8We18h=)c*kL%}o{`NQP-v2$5={gaXY~H5_)RFd)^WRc)QyYTWRq!#=XOy!@$kDp(*w zjuLhxDEM_A0PXXELN#UAZ8P7vg@kO954>$2v_vAtDzPe9tLKnZ$Rn_opLsEzcC!{C zk%ostrG31b)WB$zfdY0!W6}g*N3$g^VSD*bk^v6G?HVv1VFeSD1eS_*4W~+g0O4AzdgJL` zcSwCiXZ)8{N+C3uthLnZ=Osnpto=HlH7=}67Y6$2ZsO-Ydpplno8j z2g3dNF~4wiX{dp;f+mFQgPJO`K6JqPlY;`2;I;I)in^NsV~{Zx?rxyyG~iNUh%`>JdYP{}(G5{x1Z{gpS z4jq)8NfjsxkMf#(qWej)C*i}E)@Zp&2BdGQVP_x@Y0}>fH2Qd`D4IZ|fmoHLPKs3PNm)v<(^Na@A2Z9*k69SEOmPNS@Z8jsK&xvD zRRZv^-Q4-$TKvvk%gsB~vi$8D7D>WW5wfHG>ar?ql#Eby5Ak@_mHz;pdY0?X$P|^tUsgK+!!@>9^rfZ{^h*q<)qE*Hd~+!525>4DHv3i_NR*rgpD- zBEIv!4}cSdVcS6$D=f=2iaTq5Hu6KIx50?*ml1Yj-;9^nu8&`A*8v#*40cixq>c6!j9!v0>PL9?|Xd z3p+En{8QO=u-@8RKsg-WK9shke-@#`VDszfsiSuo{gGEmKI(B=59PR2RXOfBmRv%5 zn5n5m$uq1%GRVsyRa-_cxtLo}K9KdA#q0WQUSP9aJ}Y;LBt$jDg0A zzFEqZnI3BF-4#N$I>92aY$=3c22_Lrujrw!|FEQ5U!RxBUL`@h@)pGQl;L-h#C%KF22 zHNV&=ca5!XD0OXHu$318Qi%y~NhLsWorwd6*`UkFarYEbnG+KrL~xC!ikGiOsp!{D z=qU1xf=}meQh5r<#!}yAGyqvbFNUXE=mq#S-6k5&oHLG?fDgR%<4LT>l@%;vI(hb0 zi26?Hp~JG42bJlmQl50BrKg`_uF)%}%+ux~GH0wok?LN)tygxE+I|4;ul5Q24=4B`CVW1A!*5TFd0|QFT6{s-WUY`|{ z-&`;>tFRZlAi4mfQ}5c|&PUcND|Ikn%*_s+I#77wOWZ%K`GYOs^|{v_sI91{!s+L) zkgX^RL=m*bNg#JCZ?9ft&4NwGg(6CbN=Hdn1Kw*MvowCuDVURvJ2BfwckuLzuO{?T zxL2z+eAKiiX-PWN*B7a%LGf2}e;!VKq~&NAHX>uX3qn(dAOxhS@sA7&fjbh;P3zgs z;7|8Qkd&{4N|F)=$%KV@5l08rj&jWTE7N6VE<~@yaO`frN<2D}Y%Yna>Z59j6=abk zKuGe_akwD(UtUJJI|;eF@qkhSlw`oeXP!QFncLrf=3SO)WlBocq@ZXLqd#^d6yd}W zNq`KREVO-4&l7rG&Dp0r%~mV1105|rHB~uJl8$g7N-;5xAyZb$43z~G#}hil9f&7~ zxy`yQTmhgwDLACgqIN53(gebBlM@1?{Eq$Wt2LLFrIoE9YetZS#wZe$>Q)6yAVOpb zCWtmu=~v;gFiNo-rR);J8C{aSjiygx%*6gEwH9@%X8rGdp<-|@cV``fJ z08>!-QOhYR7$WDR`>GZ3G_;_?zZ41zc&Vx*%e5BM^pv$m`u_l`>@@M=JFcwa3un<| z=SR(@NC0Hb)$m&AFqsMEH;C*#6}t==d^brm0oG+>panJHJRX%quyeysJE zHF}F&AFSCs49j2CY^7USO<7AQkW^LU)d@h9u@53Q8)@K`n?gw=!-w|8Y+1bGk`f6> zz?m>i?E)~G3FfXL_u4=wPzsdk2@wJbjiyKgqZ+dxP?*u^58>&W>ZuOOk%eJ-cASCl z8E1)1;eXaL)II(p{KssGlXq|lz?DfpQlsl63dtPI{{Sz`ibo#puXL;5Gg>)%?$009 zoQ0n-!pZYAS$7A@)c#YFt2Q-SCXrQ+g@q&*koZ0hx*T$PlBBTmAi zvpi#Ozhw?zg62!6%Uvx1)Mhn17Pn;Mh2s`@H(9qp#-|bd9MyZ456OZdw z_2}y^VpKQ;*q$pY#Ya%BSj=Mq-B2-NSpAsxskgN2?B~XcH$vk!zC&&u33UljBm$*^ zPBMPfk_qcEUrqbXc!N4blt_*PsC%fTWsH7o*GGzHtVpv-h*#Iu630Wm_QrMb0Dup( zolvsNQ(%-^qhb<-iP~UdeN37wZ1+t8&?!6AJY}$)mb9?{0Lb*HhQm@L)Q`U0lk%5M zyUTa_36E7_@S2OapZ1o)vyP2esJT z@@(D0tBaSe7qB4+9+-s@mCWSKQ)?y(R`VTYrpSS*Y^= z08MhoM=9iC{QAAI3dq1e?;aa>UBDjCH@8aG* zFrA~seQ+N-Cp{6tXu5gnt0Lrfcb>kZ3a7;J5g5F2z9lS}j?Xabzif-Uz0QNb2ClW- zGSUf?q$u@jB~k3GQ*pz0bo;Rh3n))mKna-h2Da<`AF}dgKR}sx9+?T3Gvb)8Cd?P! zb(W{dftvc*Bw%aXk$RlgRDZrB*kZB^cfe(Wf25=Cf$XTih<+)AW*kQf$ynwMQ;*@b zbaj+fufHrkR*hwH+{xyEf1>d9DKAZ9mZj`573Fx}fh< zUXeN>m%45KbS1;_tS=~Kd>gnQyy&Ywr{GrKX7q1Vrjr1IDB6<<0JG^1>NflIq-Hw$uRCsmGFoi5oPNJYtW3 z;nmU(uw}l5;aT$_Vc4c6K~a~mi0TMesg0_VluJ1aF=8wv+Cclc&>M>!w=1)@vvWgk zl%Z~7LWwB=6W1ix1!b9rd!FVQhGS}nUAIHewA3IeBTCMsq(&)70ydu((}fP7gzOc0 zpQxFlr>;2*3d1oh;f!YBu$(i=Gr@&PO$eI0mTk)<%nI1p0JhU!M0tgp?DExsvJd7~ zrKkEqM5VGw+u=Ynu*fx#8;gHuooCIo<0yFwu}DLNY6)6&t@eTxAt4SfG{7lVpn9!O z);=MFbj#BAH#SJZaLO66Mx?@E+d%@PYh5^sS5!q&xJS6Jv8;SKj2Er9Xo*5nl2inQ zfP6>A9cLVUYc;o>maME)8EpemN-#=90$`Db&^B~!t!KXqY!VKkemB|kGNOs0%IRGK zFc-1I@W^P?-`nQY9{icm*LRVCf7dP&e8XrYN0C-NRS;zDDCU-pk%C)sf9a=hx~_ND z7g4hwE$h!Ebo&fx6A#JxQxMF~O8bJPs}W(DFQ)Zah*s_iHsP*Gx|Z3iYq_{cQi4Je zIOtNA2!X+5qCwjO3I}$Hy>}KlyG$@jQqp_F{q!KMO6vmz`o(J(_^Eop#kzylx#GlY zn8!^|S$oN%q=jypAKysrro1NH-PQb!^Vcp3C1NN32QYEyJZQ}3PG8w7<#Va@rYE6B z1bbqSr~D@W00qaO=|v-D$U@ZOSb|GaDfditO(cIb>;5(>3j7OlN#5o)uobfundl%4 zJkF!@sMB?>U2}QVh6I!#B}Zg7rTB>H!LT}}w+v?7#k*YJnD<>Kt{{6k>h)4r;@ybh z)p=tv6{)Bd*gg%0&{DxoCdoJAbp_^NqgO2*lW%Q7Bbe8|4u`K=WGfvc$N1WYrE$~z zK4zpH-gLIr+mV1u5kK!xI`Nv-Pw_kT0fTkV)=fg?s!EJLgDqhgJ^&%CWil(kH_QN1 zS3*Gc>CTFFe9!zY4(ZdXAQL7V8b&>FBcqLCmiOKMV(_4F0D7p;x@yNi4=UPhH>SVW zOtCHC%~^(pB|@qs^8Up!R~IrRmCFnJt=wu4I9uDTmF8`k*#{T<0{BU9{tey|RU1?^ zED4wg2$(h5o!(;J>o3rR!9!tE1_TDcf_gy*4!YWcil+|1GCY_Zld582tMOT$Ihoc- z!^~`_wYKd94K(I?qj%Snc8cZ6W0IW*Ya~YOrsfD4Yh6HjQ*`yMkAxlxtEpfhkGC zMgX0Oout6VwPW>5i{(Vg9Vp6}loC&f%MAj>Sp{5jVdgq7E*hFi;bmDCu^ek+R1b+9 z?@s7sujTo7=SYNHIdG)NIOtpw4#*M#tYPgBcVT*%Y|nKS-bxL%`)3H$Na;m-lZRbt17|0O=5WU6c|^Y)|kf%?rUD`0J|MK`12Ih z=4X7`GUYf*7p1TXj}D;{RAMKI*~E$qy}3!ZQCwmq;3}PcVpZqvtonwmhc7f3wjG!0 zsi=|YBd3HX%*iENK{1pg&m!D=&w-<{eJD zTf@Gil4exypsDGOKRT9P!6_YIg&$wTVy7r%?3Z8E+}lMqBSC}X*j-&+Ejz4pO9d!b zk~o?44tuT7eKg>*LSQp^e2Dpu1;zPI|f!Z8nAIj66X z&|*Uf&bXyVn@0{M@>RdfXyq1yI+iEMmZUb>il4J}Q?D@DoV8D&LGcBtdklDv&q0M| zc3+jM?&S^PEg&PL5|qI{TtKbW{{RJ^s$gECeGk!RY!@y;l`y(2YZt=s{5A=eSmURr zkZd8;09)SouX0Vz&H08o&8K;o+%p9CN=TE8slqDsXQOgwf ztjJU`G7!SaO7l2Y9mp&R)+iP-oodTPUy5Xs12)HQHMbwduJN;{{ZaTal`x# zm3n}se4>FYiARz;X%|~Ey)3ddZY9)uAxA8B@}8a=lE!7(b#ZTWTI033oLkqD8w{Z; zN_3NQgt@3f$nbYvaSA7A^tvh(-D}r#*BZW2NI3F0b5UqV}De9W#r<6R7@?7^@=)VEO9Ks6)LxRve@icY2M4PxgP_rEa z3aJlO)N1)6iXz2~B1wJIp>~lX1--YuxS5eCSC`CGzVF;T>LzQac)I(L1vmkrrJ+rV z2_EDH?_=#_ZU|pSl*s8e>fcrXH8!m_}Ol6mtGigwoN| z=XhbKi8mER{%IPu%Nv5k6YcQfP2ulYSm^|NaHDG_Ew&P;OsFDMM-v2+JnGSZ7|&5X zB+1^OYB0W{V$s2l;kkA>s8lUONTiv*T6ly^Bi-g}s3comIgi<YADb;#Uyp{{T(#ru;{y9b)RnSHY@s&sZ}49Z5Vb zDV*aK0nyE15mX?;fCqzn$@m+#pr6ZE6Db(+!l^BL2 zMkdEl4Huw_xA8jkd7nKnQgn`Z@LI^JvrQHs zR;@gVFPm3SM3Yu*395ec5Z&xZJjfO1V*da`Xo67cK?D22C)jZ@SQS--7) zGQ#rCHPlLc-Ir>!MjZwt1{m*D^=QqxWTjBEd1)kaD+@@=uvoo?`N?eGca4qOtkrX& zUJ{U0M}@@{p+*h>sz97@uCMO*ZhODHHb(KQZtx~T^frYcttpiRsDU7iL5{7oPO~0& z%^tHoTlAv~>Mm2F!IL6lbeJfTu2!26sHSW}I+%tlP^{@yF*gK*YcT_zGu@n(jE3E- zA_~;bD^i!Jl@$W0Bc?c$GdNcyx8pT`KX&&$L0TDjB|)#XC~YYrAqXSGGb(@t_14-GTskGi(%6)BZOhE@}e3z+No*gsVbq(QC+dxzydTR-;s`So84sZDOb)* zE7FG26s3;wM^Kdz0+e8ZqyUg$XEW>)3o_eUwJPVZEo6|R+w-}OeEvhF`<{C-kmzj*Kb&uzo&0aa8prYnWq`U z+LI4Qj+&8ZX{j3!mP6-nR7k{I>J_@0#)K&6zWG&@bBx+DK!>g z%~aUBK}^&&6)Hkg;c_@g>**Rb-qN9S8NTwQg-=+v+3IW>s8v zpE74SB7$m&mZnH%Nh#uW1>-3^TaiH*0E4ZqeK`eM?q+#*5L#mp3CSY(vwY8$rH-2kkWS3gnwVmaSAC0Z zm)4>mF+A6ji+_%NW6_%VsKM^kYlSW+NNDSi=^0QFJu2IV+Bk1~ zES`MZpsh~EqK@Uwas4AH0uMOf<= z_eYJ70`6ViI_9SAZiDF+}4_AR#8r>v568dNW>lHtn+56iHB(DS^z?=dBNL&X zo+zU#kp@ZUFCOw3-*1Spy}^cGmNQ~Xg}6y4Y6ESAqiAddr|kscCjfR6jTSwWIM$V0 zK8Z>+0=5E_1Z@ioK^-IzLWtlAp&WN z7(-J~6oQJG6{B&m&E`lIRZumH8t)SFb{}@m*-L3?QW_;iBHc?HV3ijNpu`k}g-(*7 zZ~|LiX7-C03P>C~ZYZ zNhAc7V+k06A~;s8_hQ=0(X_nU6zUG8sB294^Z2O^O5g_Y>GWT6h+B`ahg zg!iQ+p+O*cRe?cK7=Z-gSqqe0TiWKG`{PxwbNf)7Qzb+NVf;V=5s3rJsXNo=bNp3t zzP+^LbWRqaV9lPw_>YEP0RAhVJN+gn?KJ?`d1b$NP$bEyrq ztxMLSj+6F)4~Wj*5syVn8~eO@233|5m$n>v@u9s5SAdZvODFAtvxzu#)VRG%`Z>tm zB2i0(PjLCO8U1;ohD4mDR6O9X#t_PN*HQsd7$Ym>H&IX%9B_x%SNYsHabmKThGUsZHCZ`0IDQVqWaO28mxZSSePl-M!n1zqX`{H z<|veU4g6Pn<>+(yr>E|pU|0@ei#21BEj?yG1hO_B?I3`pK0`)jh+lTsIz7lXxaL`8 z_X)cQx4KfwB`H7}bf;Q?B!V%S#O;6v!BJ-LWuM8#&Sz$Z`{g!Nyk2GZq8z(ROB6LVGzT?fdxhe_rAy#RWk4QnxS= z0ZL8>4kT@g#w@S3=QCf}hQb!6*^`fj*ARQb7~qwCv%_rFSIg=T)!#ryFNx;---u)F zT9{b1jCg-e%ky16-%XrJ~X1iSb8)J5w$?U_LwW-DGI2aw^D^VnpRHCjYW*}{& zjo03_XBngR?KW9uq!fge>y@E;Lee%gG~uLu+f|6IT(EV^GasA?+%q6zD2$DWe{ z2{5boI@}T8www}nMRSqwC7WG18hpKoNK8$N;u1vXww08ULO>VP6Rx~52~#=phZ5?) z-jhE%5nL4AZswtmmePGtp5r5K+ScPy-XAsr5x00R<$rh(f~u12XDF#gpqJgmhHk` z)Y&(A1MoiG3iL{Z)P1=QcX_i!;X0G;Ny3i)F@@3p05x}-KtTkJ4$xHgItyRp&Qh?9 zCb}m|%%@L5Ig*Y6<`B=@z-_n)e_yAAjHv-nB`1la%OMLCPJMOtXRBQ-$uvD(>6SGv z2aaWm+BxXwrj8@!fiBWmI#%E}&SCgryP^2v~M1l^&2q_@J z3P}nCNHbYMVCt08m;Dl+7)H!N!1~dMtEaBaSYaQj(PZePRg*)erO6;gT-+7pl zpaI|qAgg7it44x$2G9m1;1U3maX1a96UQ2Xua1Y7pYN6NG?j+|{#TT7abBon5>reR z7Hv{MHBttnzX11Z)ZmW4c%rl`P&9u%J>ZpcY%8XUt$^^|3!DzkjOLWyLI_F#rht?WF4?8;mI zT=4!2ml{#q0YOj*{{S{jhM25ed{n%-g&T2gnDV7J+{U$=j+ zl5X+e+P`f3NpKYqpa2UvjuWN^&YxNj+cM%*m1)93oIe^Zo}U_pC^H@b4&yEri&sLx z>21&E4Wrp+(D?lvmA8qc-YVYiWW8j{x*BC&JF-}W%-Oz)jL=Z%XS`;J=pL9>U4m6WBLY}p8Ab$+{ zf*^jhL49U=Aj|%hF`UbXbn6kUn*_|5Z6-b=X-dH?=^SfOFOUtENf-wqebUgxeEirpm;$5@du)ZmW(C! z7M3I^5J#b{hWf>Y;rJ(3F+4h&MXVT)ky@;(HlIE)&AQ(0)Qx<5X~Qg}qbwc6F9*Pf zQtBcV-z7H$7?72rP82OTK^q3jnD=q@+}Jj*1l`?=8-o&9bI%Us|-5 z!qjx)ojwyHNj)Q^VhIMN42JRCzTk^?lHqUw0+kc|KMuAIvU*$Ev90o{<>pg@NxjuwJ_*Ss-<}6S8uWFdmYK$1iR}9VmRxwF3 zOj6?4P*i{o?ZF0daID6}+c^XTkd=QB27EKbVq$huP1``S%n`#7~FN1xM?MJofJ-^rxyM36+Wu__g= z82h?k#8~(GFT*r~XZ5022oYTJw6Rm>SYiyz=8d857ujRp<6n-yUn_VD+9#ui+EbOR zH*%a}aG8#Mv~OrIg{a9jYc)@q1wQF^yu-O5GpH;?m>3Gko9hE} zVzV+53ZSd;G#yf68Dd-tqMm);XjAXJ$`eC&t7zw_>|~@oH_v zC#cSJW4{QN{G~y%A!0vd99vq{%g4}ce$o|q}!$BJ8t1y$aO@xLK#vR0cc7> zfE~)5ZEHdlTR_wf$r%ohtr_O4C(VOn50&~|mYW%=#&YYyBzU*Zq>D8U7l_t4S2Ph* z%G=XwJhCe9B{b*EUidd-lHT96<)V>#f9a3yF^sNnPr$QtG!sI^kWJv1*Fy?wEDR z;~2$#A&<`fuIC6~j-w5zrFhrOf`bsIrdZuua1{y;GyI6uOmyVNSBQ3X((~?2!jeDYmoxjp~`UC2gz1XA%~jB}QZHSPJms60is(S({n) zN0=8K=q^p`)*5`c@T^ZS;`0^O^fmiwD`9Toqj)Mvbvh6=<{j>hx8?I2jJa5qw);c< zvAJ7n9Rw+{2WTdMc~dDx+m^~c6R9wGkZ|^5XanlkMtX;ZbuXm7J?O4CQGwvtJb8px zK}{MwHCS`u!WeM+s(As9NJNaRy_pIEgb~S0cejq&EMDH)bVkBx#QIOn6VcVhh19E4%M&ybMLsubQH`|& z+$fc>gApz@=%`YC^A)YPNwXd+n0kAM)Z$J0N=?wzU%YbxV~qYibS$!Psi8YWgXu>1(^UsW@lK)CWj?=9VU16W(xf;n_{6foM;0I) zENMLOl`)Cb?F5@{1GVqSFE|&L><4W1Y6ry__zu-U+7k!J88`|ZWR6)X;3oVY?7%u> zR^Adolfq6h0~o6;$Fjy?tIe2{c$Ibt0!A<@{62S@vXY?|1_BAg?hIZuuq;K{M!UP> zg{z9SN|b=V2Br6ar799*Qb^i09|;q*5ruTk<>iUX+OU16mebg_NcwFNW>j{-r} zsDX~qOw?(-ouu7aI__S@sM3?9jXndjpelV}gH&JEr_J(pa~Z|+rcfCUw-}S>Ka^9_ zOG!+NCAUpU9Y_0|t_v|wbIfM2TkYm{rqC zu$l6r;VMUVPC7s!4VF!<^4$gXg0m z+FB`?7~awQt+j~@at@c5+U6;8*6nITOGt2(wj6?tLVzRqKH?KABkjaeG-jE$Pjzo` zlqIKC-WJ_y)NAh=aU=}@sUuofr0tTK&dYGq^rCF|@HeoovA1ns4 z8fhSAnw0y#VIW5%d2Upc*6Z5VJQntCm%iSmUIm_-Dl&BO0d+nMp@J8$AV7qBbP0bc7=EmI>%4mbW` z)O3-Id@9yS7T1luKZ;PVS{btz3UdA<=fD~`Cu41X!(ZNAdwe;~{n*XMZpM|L+9Cnz zP~fkT>&J}_udPk8@E9GRg=V9vM}=*z{hq_@_WeD%AQ2QvPN^$6{UHU0gcDg z(WXunE(sTX=J*{!H}+cH{+>E1B85BCINxx_%b+*X{5EM=(gliohGpIeCf$i7+;H(G zO&2I(QpHJ*Pb`}PH1FJdeVlZHlSs`;6|ET$y1-jPZSXvOE)>!-iq3I)Nh~Zk0boX- z52uD{becq@O=3!<-c|fOJVEw=J)BaNO(9w^teemea^5FHd+}OmyozbWDpV)B)-CqC zU*ZqLi<4VG#(^x?;GFv4l??6Awq_BE@)UatS_xvJX5BOXy0NA=#5 z`qTb%E&lrd0GIy&T5sXyc^-Dn*R}q0+_n32KfjwN@*U^!?JRKKt%>jYT8ShqZ+jjR=UIVy$p>U} z?15NV!0*c4Ue^?*A1T0lDP0XsByozWrrhk_WR0cGhq|geSx3iDtC5SV)r}a(3MbSw z71%Cxt?i1$Gt@D06T zL1otQoOt8ahfhaEO1r$^K+;Y;Db|CcRk@0Sj|0iLkMekAF*Q{|giSo~Lbltv?PD>y zcWp^G9D*6lCDke9>mp!IkdjYVM!+^y&-tF|GEFy(hf@}3#BexkW)*bXXFgeGiWHeP zsbrGkT9#EIS@#rQc|bPjvuxQ{WICh>GByD^cnJGaFpwfn28>wJlnpyN_VvvmG0cZY z)O_oKbc-q)T5K;Zmzr2+mFgL464J@5lF#m+(gN1G)Np0H7b><HX<&+G%Hs^2rjytXFAiDwuhMuV6x7=AI0sg4SxOH_4RDissv9QBd!G1oO;X7_)kK8B4%txkO<>SF+&mqYoSup z0r4;+{d}M9ZMCvlK*ey_1N-t4J(EN2;#zX+0+EKTEsr8`_f2Yn(ySi5(bPULE+O(D zW@~FA$Mcn)`?t*0$b_F1_;5qo1IR_gHf?>D?4>XbwTSz)*;{VhD{HPPU*?Yr zeZs7lpq&NiZf@!1S?j4iO~W!qAzxE1Efoz_O%zUIS1OZ!o>XQv1TjHt?H3ol_;ZqO za@Nat3Tfwi)CG?2LQ)m6KWUXj5@rE07*MH8YVTSN%S@CK3RE>J2l1=KG^CxAwkBv? z&whpaUDZyUV)+9t_2U46F}S0qYR{OVk)w%bN0-V~sM^fRg*DJz-;-5~4rQ((&&u6? z%|SqDoKj>1DA|TMO-Ju;x-LoXuk93~2!)ssph2B0)v(AIPn8P2FUfdTQmi>2EaOpT z3^xX<^5w)JRS?xwD(;n|DoACFoq?`FAls0ot)<<@@@BcM(wxz7SngVMsP_Ra1gW$G z_M&`H0F@FV*08r*043Fx6%}AfI%hxGW<2WKBWW6)6qi3dl+R^iDYO*@@#xoXlKzxi1|> zC<|CPlBIAUY);$;!9=Qy(tx3jV8eRXjI3$<;}9g0Eqk-j+}!?rH#W{8KiwSv08XFQ zkPF7tukKdhOb^PA5aUN3 z7UTTYiV!f*OZl}>!$H>^Ntl9e)l_6#+DlOj+k~#P;r=&0-w30&){Y5d{pyx9{+N2j z3<6pnx7O%8w77GRq=QNi2wY`KKYO0R_))`T0U<2QCC1$6t7=Ky*{59azSC*NWkNVa&1Sd_xk>6!>*5 zTyP|6m_`Xn1Z<&U_cuKC6SRzbn*rGH!!QM)xAPP0#ipF&?^mC>iFN_42HDi@H)j~5^2w)F7TzHRp2O=HWW&c zLzk=Z0px~CTrt&}_W0CrLAP%CdDTj4o6nTv#5~zt?_de&<^+F0*tdWz~&GVId*_@&ueK znSH45apRx;K9*r>k zUU1R2If^un>taH)76)n5OAB~k;m#KQT5k((sjR4~3(hBI-3*ON_mtOD{*-b)_cFfD zG|zTBgdP$S0fGLSu8R_!!n$#A={GP*C2Gg0%%4G3WtQpIkEhsO1b0@cyoTP*#fSsh z^zd@SI@~He2fWbz)xu(ePPk@d!|^OX24+9#)XhHC8jGDTr*rY*#?l#V#?`J*l0*-A zGzZNY{L<2%2_GH4>Q8z)q_$$sxbv>(TKOXc+yW_~NU!y|Zcm%M$V+Nh^p^+xz!Uh? z8NSYFLr5KG@S#7`6RshK=ltv!-oq%VJG|4i1w4~Cbg*iT{?*_ZuJA1aH=`41_Ot~fc)jR;8fRwR!(_f&cLzs_Ac?*Ouq{wsWa#*Bt-hOY*~-irsOX(@8P5kw|o zqQ?z9G14d`+jBFGqT1iKoDg6A#EpnZo}iHx09dRPf}@JmqvljfkGi*V^re#zOnoPG z&mhc!W}wUXVRf~wB+&|oxE>(6zsHc`7v7{Rq))dWodBaiT)$-IUf*$Ug!NCUGgbcp z>r<*2MhVopaH(-B%sQr`C}Hy`lXI+5x0@h3i*Gj9;cp%y&GQ!Q*-J%AN|a_$F@cOt zL;1K<*J>kzK#HY5#JjEdVDzJzF#H=3#073)mkYvUN{LUD>seBY-dYwQxQwx5ZypVI z7U8wOa9h@;Eu^)nLQb) zGvp6M*x&Vb8n(l-+@wy_?-WTKGR74YOD3V@3VzMDfpM=h&wV#po9y+p0*P8ikYvt@ z+Zbtq$JYwLO~l{3z1ZE`mQWla51CSQjX#(p08fiiSvxTiBN|425gx1YY}eqsLgTbnS$2qRK#&D*I=1o+gg zC#nJ!6NC{EFs#$;_Tc6B7x{(B3P8FxtSFBbq_%~+Wa3oggijJiGgeXSgE9XAJLpzL z!DXr<;Z z1~*xWPT5l}VHix+IE3j@P^z#RnN{VFL3t)V>h=Hw!+?oHDkQqL)>8*NDjoONj`Mgkb_W5DyyFJJ*hN`R=achLy(I<91Wr zlEcegM{OAP?XQmm`>}d&Snu`~1sLema0kd3th3DW!Ix;Yj2kFU8zBh<$E|Ev_(b}K z%KZ`OMje-O*=V!7<#xufsnR1QJUgoc)8e-+*=FwfI^7z9xlg`{fmwM}*kum!n0 z$QCR>?|uw#H(uR@l_AGu5w);q{8&`u{66|oVZ6D$%ZWnKYmU;F7vbw5fwPDQ%8OoP z>ds^J2hq%7 zuu zA+S;sPwLO~-@RLLN1fyD6jqZ5$&2h$VLoW-9yua>af za}mfrD@bE%igc1HYPsdAtx2HN-a@`z=3QREUrtM|Zw1oXwzg^2r5fFUWB`>cNKF3# z2{L41B-9z1S+Mo%&#fscAt0Cpogl>Fw0l6=Rq6P{Qdi}kn|f2|yOJl1Dtz;9R3Mbe=pE|`YUL-K8;9b(eCn+d)neHG zFIi5_E(JCt?qRm0K(*B7Fu@oVKIqgQeMZ{b3p;cm<045?RI*6}YNk(DK#KX#-#f#5 znL1N|M}PpJ005i->e)h0dBd=H`fpNeaLNiPF$k(E32ZAFq#`PK*_nZf*r>g)?C)+I zg@hy$l!9^l983Y%Bved9O0+xeS1i>BBLJ>HcmX#|NNDB?i}0|uoW^6Bem3Y%J!t8SAM zj^Eu|a&)IAbibkU<5k1B1cwUySTysOplC>lWfjuw=#Et-xc#~24i-MGq3MYx{q6d;_ zpuqiKXWGmuFNVX^IBBB*i?mp63^3S#!T$grV*SQo&7OFN+$5!k6yo}HwpP3kNlGAf z#L-)i23d5RVF%VtDth_oi!k*MHH^UyKRzC2o~EnHo{3yAotM*W~zmKzm^!-X? zSyEg4<*oY~(XA!Mn(?JZLX-PJBc`MDW_K1+g3QcpR3C&NN(}Qq;ZxS!{{We=&Y|Ji zl7bj1=B=F|si2>B%83IFk^^8!P%rGiGBbAmp>j1gi-ys5l$8~vs@+L3!AVk7prJo% zfs8t6NZ;me*;L!A986-Q?AeGtJr!LU*YMEw8|cTPGG;!y=6ow1qOQ)kZACKCwL+N0 z&8j3)pi%ECvjB7*yK_03?e@d9e8~-ktG`)6N){9k>`)5AWgteB>rk90jM8g7xfytb zu%=3oQ71_Xgz+gS5GF97v(lC;41FfUF$_#iBo%eo&1{Pm_rIH2A+jBW0?IwV0y&cT z61Cc;NBESp?NOj6@TM-*2k@l>*pW;=y`-Y4^v9QCrh%c3t2N>CBxQ9(DJ+3Wu(=D~ z!%i6HgH5y!E+gkgo2at8)f2(Be5#rKMbnR@k zn$|pC--RqOs1{#Txps{tC~2vTmjd?LPoY2J7xr*jaC`&&MiG zBkEpxRnltAI|!(qH)x*osTX^LW%dnt2UpBd7W5~*X#<9%K3Zr5^v)*D9-?ylR?i$# z;yLy$MP`V)CLGdB6cb@d7)|h$e>kiQ=BWgL zhWgst+k@3y+7#$`I7dJbV`R<;%7!1cT7r`6aynCnJPsJrLosHmd2;-4zH!Ua#Uk0h zTLwjzAT2R2Jt8#fTBFcR2o-HEtw618ncD~x?TR?~AE(}> zH%Kw3y+L1UzQ7$$(+kZ-`5k?ME2UjNYK*Ouu)Md0$MRUI6w6&vLPz>b zpa46xp-2FdZSP-R2lo$m&RuTe-f%j#zVo`VfE+r4Hva$!G4i1P@wDyYgKeD%(3Fue zsst0WX`!?61NGVJU)2_F%ATIRO*Rz-85;+hrV5-5Wq?j*!oyy$Jg*wf8SJrbP)@e& zC(G*wGVH@ca|J70&lNTa2c(0r@DtNe#^rA6a=SM!QsUJurrju16rr}!nEtAt?>fK*~6!e=Q+WHGy>U^7U_Bo3hgYmawOII}iq^R^<` z7?zL+MBqoaXRRQ33w5~sY6){$7#T_w3Whj+pphhE1sgxc%Qufv9a6_S%qZuerOG*f z8k+@rdTAqB;GULfVVe?)TS*+wtYo&(cI{FDxaK`w_G$i6-iOFjj53#yqy>bjmlp1n zC=gN%=^_tJ3OhgErDpcmm&j-YD(QXENGS?JP!g4>V=GkZS=lf+Raw@0Q|pgP{WN-A z^?lHaiu|)Cd#K9PG?EI6dFGQDX7?)9CXB^t+-R+J3t-D@@<%V_?Ae`bAcX30f^Yy5 ze4ud{$fPdsMc(jc4&{1OEmYfymk^kBZD8_3h9x0T5)2c!8rbXA$FCp652PM|vjs+Q z!g7vb>Hz9onHsC-aF~8r(!)JE&`9*rPO+I}5-sIx#-WDT)RAbbb@Jx#E?;q{-B4-7 zcXARiSV~rfr~xpgOyEw)!fFlAbG2R+*k3TvZSL_eCrW$7uHB?MjUX#*l?0QiAOI3% zlS;orez<)V6%LHAZd9vSRN?K}Sh~O;H-HA)JCFo-M2ha;!;- zLEFfqe9@d;U4<#FOv+X6*L&D&0#*+ihz< znk!HWJ<{j7(3GTsq^G44Njo5lDgOYC-%C9;RsIy`)c*jcsKzUU=M4VBukXvPd7tnJfcXvH`d6Nt}paX#68cLK9NE%EKs7WM7z;GDQM=G$( ztuoamD20Au*4QhOw19%8HdJvTAuE8Qc5xzWOiId}LZ&$*ik@FH=EJSj17$&TyV?hb zYjZE11cQP5ytq(VmXZj>Mu_R-(aEMWf@TMfX%-M8ZS1?GjYhup^*zY&_V(ctkWn-7 zp)+lV03)j!PFLX7v~^A@%yAbAHI)ds8lQBV3;TYqR3b?tID2Vsy&woCCt$0!`~f<1 zg=f!PxsxVl3Pi6Jojc9z3Kk_xigcQ)m-(~OyAWGmFIDm>!`2_OjeTzQBw@9 zB{mk1H~LH@2u$HfQnxqI>3#^4b!~R^DYUqi#DyRz9h?kLVK6I&*k}BE#0@M zg%F}uh)R_s!ekvF$Qut;2!5yY2Tt|X2J;kwV%1k2`$@rr!1k;sk$q8C6w2F&3Yt@Sn}18xB~hV7dI-{uyS zYEc7G+vV$rRVd1G`-}a3!W6v&QGxc3lUtb$>rKY_&AF<|TzwP)OBM zO7WU1J(9#yMkYOu)&tpoVebA}J$IVEEoBN8Eukt*584-9T!F?0pAqW|%{395ty@t|-D5qf~ZBvi#6uF;vmD5Q3%dv8Z5DNXWg4 zk)Z9&!Opif%QqvuAp{vEBnk8Lqr9s(dfBn06C+}z$L^qII?vR&>gsDLaZs|=NhH#- zE4kiD41^XMoqsJjly04pFbM_+^uJm$IjzCkr4J$cR%rT-n=>9LYVqpVs)-_zj0+{B zViwm3G`TvF!QNGsv1X}lDZmpW5^(9;=|Jqw*DjF@QN)eA20a@+Vz(ar9I=kDbvy93 zrowu;B(mg;tZ@n~yM;XhM+IdpwJc+(sNR7mUp&Z(IW5?qwQ_h%+bxRn9rI$_FNGsC ze7fmzYKwP?N?dWI>G3JT2GtOQ;7*WWXO89emzQMudyKnihwfP+E-Vm9N`|DiMj^ev zArey)CaGqdq7meONq^R?KM1GAC&p{@6GNthE`mwLkWq0|2WPu`#M$4)aYPLf=; z)mWOEn;dqZWQyxBtWzYN13p?mGWhg-Zcac8=0DL6_A!->al zPpuwn3tFTJ3mi7!F+C^Fw)y-mah$D`as0v2uPN4}7t460G+`+M#~ifjB((rD*`h)X zkbrml0JkBVbRW*GU(#hsj+|0_syp9%Q*hG`2!uFC2?c5J$4A;hBOV(Gq9Kc7IA&pXT-qY_1-C|| zsw5w8#;NGcEVW<=Pqri~19vqe}feoaMqe=DNzkQN)EX(+I{Fk2tpJUhlYj*5Bn)6Kue9NY)IOK z>cdx5R=GcpUrRr(evq>6d+CKM=8D`$GQtu(BGqi}vbk-d0^Vl8SQFrT@_ItuzqNkZ zDN!wVD@sC1Q5w>N18&7nkeY_KYz(6@W#FXfx(}tv7=<=j?;idWMe;#GXiFt;DHl>K*CbWReturNeoQzh?Fa+vCVw50%G7?Y<`po0mMk4Z+Q*7J`~z&@eRuIJIUQdt8g2++CXeOYU14r{+ca6p*y5z!XW1qf7%M%Nn*%+3sYl zqw-5iLdq0~)v5_N8BB<$Jj3{Kb)mCXX2d7Xxho38@r+)wx{5ly!5ES_rfuO|E}Ox> zW2YpHr|S!J5VZ!Ac=jZxySGu1(;GzeMMjy|WI2uVNN>Gm1t|eqwe1}q8h7bGq-wsE z^$QKmxxcGDH&`enXPPz5wCge4tTYmBTaZDy_G!Z%DX_vSQmYD{%!Wn?;d0 z88M7u!hu;oV|kWSc-_k0w<$uTfK~|+7)oQ08aA_JJhP9q_?BDh9!jo=U0zCj(}&0a zwt)dVOG%)|sW7@KdibZa$dwVo zBXI8>(VI)?ZEoDfF?Pd@gtA7EFxmu3=>XItnlz>A%HJnb zBF65Zv#2f;QZ7jr_V71$l{QjT2%ok=8nFHujb4*QtTs%Jsy^P5W1AAlv^mCmq_yv;LgoaZgww+-&ik5AfzZ**=#Y z37ixU!iTP>3agH=LyTo#UwJ-UyNj@>uKsCCDOM6nB$T33<)a0*v!FKijR!F9{>(RP zb#Bl)nt3iIVs&fO2p}hjlMyC|*6Io=Qt{K6$nO=fKcCLHIF(AxIK(!JMEPs{`U6b-4B9Lg0A&W zAczWBFcO6sg#E-$$_U>;Uuw(m3#%vERYN)<#nGje&I|srh=TlCpeO zntI$OsdmeS%JkuWO!bj9PU|CHHn1{WT1hyI3Kj^ zB9C$xlXm0lM1ZBF$5~7n_He6F#%bzjsH=`PQt~8`mJ475t-Bu^^9nB%Le=c4rJx{C zQPnIh^It--%r#fbo}&qnEQ&5;k~J%E4|@^Yfp=~Ogt-y{K|kiK0uP@aigM+$;uMLA z3ipYs@2KhzsV`7nHNvo8P?#kK87>W$r=Y{-qpJC*tbj&ij-sS(Q5=$adx|L`JW1fk zdv}4GyS7|u^}HGlG@WVETSH`!jayfzQ2|5=5CFoW?5fZ5$RZ$;N%QLHqABSiGTtB6 zJe`VWk3F#AT$Hr|2@mDD*z6m?f^I#$7;j-NTfB~~Mj~JkPMN}V?3^Yhk1b^?1v_y9 zc1&SCQ(HLo=P%*dCr~iTY&Lz=a$%5KN3xkpxmekO`%F;Uhjz|hBwK}mAQdxnKPT~)Z zxs(}?dc$&+T9A{7Y(s<*fJp-s%xVTs5;jzIkT%=5jfWDrByBit#(D`81XWY?$1-OG z$`rYG6Y4ilsGkiQf7^|-qzU2#BT8)e=+vcJ3|?`%F29Q%3eysupo&kDU5iD2WX))M89OWG1@RZ zAjH;|br?!PibqFHP|PM{43U6T6_60XFwl>CKzu%qP8TUEZ9r{<@Sy#Jp{J0euqb;c z8oK_zRKeCy!s8-m83&z+U~8A!Sy&6l^3PF$Ror|4iuUiJJmscL>B~2c;@)8@3(_ZS zfZ{;&_g7)_HcnxXwEPbSnLJ<+f_>y4N~FraDoP?02U7bRYa*)Ou>pnc;(k2K6i8P` z9yN=ufK&UaH93IIEBSs{Uw3QBruMdi!o>b(hKZOM&yYO)s5azDF&<=78_x519}Y7`(+S3;r+T_$9C8Vb_5k3k0(EVxYmXle+@9=P zg(S(YV&^H+wa-cT(7EY0n=N8qrSi@N)Er&#iaG1xUz&+zbXvu6B_vbBpm-*j2;?N_ z7@rPHEZUobKe|p=$ee6ND*8 zOze{wRPZ--{K2)p*ggaW5gR}lfgE5@S*iuXF;h=TBw}TJI(@BE5j&DrTWl_krM;Sc z+!EX(R50-khluHeKm<7eiSV7Hf#{mBKS4X}DrkfFg zB)pY)T=N~Ks)Uk7FdLZ(vjD>B>@EA{eqgN$d8jEWQA3IZ!jgh8BzRP$k_wVekgX~M z6njRxVK?@ccNt;5YT*wh4-7*O;h~ZM)PV7W-i4#Pjbd~d+`G{(Y3j~3g4GIswNZ5y zaV#$kshc!VVf5IAJ#9=O>E=qm(tn~?2>ib~24=9@z>APLP4zju*4Z|EryWu*)Z&YQ zXnjdoLy@E?VtgeeByCDcLEr{^c14=Eyt}t<zYL`zQVw;Tt0K92&-rcZ zibDvwLye!=Tp+KzDQUt$FEnLKXpKcFB_QD=7fEBqa~I+9iu6x8)eKJOT0tU+f5;ve`3o5w3Va|zWwhT3t+b-1(G^8Bw2zr&z46}=G7`ExT!@xIpnSy4Cg z+)Ha%=&;lWAn0~j^FKQq&wnp=mW&?#1+mbrN$(Or(;_^{s0TW>)2oJ(7uE_6G3ZVm zRjm(M@}&nvePMM+rPxAk!p1oGwivyE!|{mI5vG+u1bJl2bpqgy{E+)V%Or<}Iwd6e z8H3jc3NW{F7C_jjQ2zipPsV6g=?-(rojdBD8IEVV80)YJl4@G$9-S(dG@UlBQq#$B z<{1jP7rm|l<}Bux4qw_S45>+2@g$_dF|=?PiNKhe5M|d*+1#bak`{nrNjnHWhua1= z)ud+_Gj>?QvCLYBG{n_aRMhd+(;5h16)>m@o>(l*vIN>jfUxn?m>9@FJ<^h6R1XnR znbqRqq!2imJ1eXi4fUpMwpkXACA1QzoGMXD3CC^{nUU0ZRKA_jW%)2k`g22#HaAI& z;j_gR3pFS-(#W1^XqHA3hl)iT)pR4UJkyRk(#y(15=PZ{r1WspJqK?IgGuw-%ZBdL zcB?|#nsp^t1MN~KAy~mmf!i1uosN z0k;A6NVq!iPMc)DwXI1(14xpQtH(Ng#u)pmQF{HfW~sDsmdYMMQe4tC6#yU{F~g4B zDyRPd5{{(dxXx?9IxYOBvMP+Yi;L0YHCTwKHB@-5H|c3&h^Ltvr9@iY$PB%O`IJ4D z<%?;TZ_9}x-`OdoqfUjguL{YSB%xdY!1Y%vq|OjL2=$@AE3IMfR8)k%lctlm{vh1Nq)CzJX_SrK;bOETOzAg?lE$HNLr)vy>a zV*`Q54Zd@<4YiIJ_Rd|~xYI5vmlTts)Cp5-+Lfdn2}uCK+Bzuceki?C^pEOG)81d} z2c`T&F;lh^Q%6@*g5wCY3^H=Yix8ywqRlLe5F>1an}7pqZWM05RcVmtPP1s*nnTSK zrFu*&`=Co}N%5ol1!zjh!9qlwhR%_hXFIIb=4ep2T2d63TQlAy{>^GyLQ)bzDv|VjDb*N&iqR!PZ)39CTomA?k{`bdAczAZ^YR0>9SQJlo>7`{YOU35-Hrh#bDowW! z-d`2C{YJbGM8wdAwZ&}x{{RW1>tp5aujgKf;uRxqAq*IeGLvhOc;(Z?_U)%2jq|oH zEi2%(DY)UQ__tK4XbAd{gU3_b*NC~fW$deUBO z%2Yjvi1alaxY=n%Cv84bRosgWH2Yc~h}V}il~p{+uD7wZz&*dPa@3U6_-2i)>e`Ji zbQ*WlBL2@RoN4-I&!G>q3cDqi;|#`hmaoG@=~C0@#x1lyX{y6dIQ z`+j%!@p?p2Qp8g|e9EAzf)I@?HP^5oUl%6#`*o%H)>UBms-GrSOOr;UiyTX0RecR!NMKsyzI{{TA!@;;R%K0h&U zBWTCjMC1LVsDIdR`nR#an|#;u-#1_PhyCl@{{TgF{{RiSnURO(+#Bozm?XMF6>9kN!f{FZ?@h2ypOLet{-_tEv$*c5^D?F zxM{QiRGbG$qh;xfpwwQVdV?=db3ILFU!Y{UJMj5ioo0+zWpUH}(ZTUWOD8C} zw-7H9KgMYv;R1IsCvB^4?_>~?HM<01Uc^fd&b15r`L4I>Vz;E}^^MEmue2W``3 zZb2>|83z;6F#ZwmHL>>KE%=%>kCk_HA1CiK<6qHBW zC*&%&zZ!0(H6}pI9Uv13qs6Ccs?cw70g~IA+J*UeYHw~xIR;#BuUOj%b6Jn?5>Ky) zr>dg9)AK&%DQIF)+TD%?O8uGv^OF@;*&`)Y{{T?1rK=(e+*Smvk~@8wYn;_G8*96C zn|0Q}1IUkfoH@Pwt4aIZ(38{-frq5U0CHyk0GHY}*&k{I@!=;Lbj)6m@gGpRmX@P1 zXSi@^Xvd&+u%h5?2e5E6$OG=Q?x ziAq{P(g{#fPm58QotSNkj;wS1!phO%ZiWJGo=_#!txh~qsX+)*R1%axf=K(ZIBccd zYNOK!RVcDYr%Ycj<4;qTl02=4e<-TMV2-+`YR8hUs-WyLIG#dpVoJug2e9T^Sfa?3 z=yl~JnF?Cep8x=i5~vsgOpJC#W6SqhrMjKGPjcGIJH;ovQlUu%08~EWB_Sk|CL;>l zgVXgEAJZIxm$G6<98V1yQm8DeypmOK;JN|u1DKhb-5lcK`@ylt3WxZk1pffMf$gcQ zblVvnoxQUD@QGPFO4dr2PgzkkA7_rWVHDn>q3K3n!su~aN|u6}YWWCZQ4gOXMDyff zu_KBQUvIr5-Bm4eLDpSkuGvnhYDg+DKZgOsteiLjw9OD^naFQ2OHH)e;UFnT?~-;C zuq6rc9i+$tD3SWB#JxY~o~^zI*Zgie47ue)^0e&f5U7>`xg${XMeZfTF;YeCal*H> zNJFGR24{&Tag1nVmv_#WE-m$Vl?hS+l%*mBYQRtKpc@LvUxocFf$FiPOCNO&OhgcL zA7-~ud+@c?Sn%%rMf&mWDTWSZCha4HXq@ zHD)#nJ*SAG&=~!nwO@rV3cgVL-p8da{xl?E86WVjrlE>_OE7GeVn%q9wA?cblybFt zmF#V$@5I*)TTK4XZ%V#Gms_gn;9PoR`YrAABzjgFiZ8;xN2bGK#_Hl(Lw=q*xlkwX zYDHbZur@zX*M%!hpct0Ns{a58qog%<2s)fSGM2v@SLN)5_*2wTRO6WLbE&7HqlQ_f zmRweN)Fen;`^{6OfW7^iaJ5X^ksu_FkQE--qf|Kb=~IdafC+AAfQjQqfAIRqvSj?P zmvS8iTUFBFnRT&-shG5tGu7ksNmEMF%;lY&rD79v;5~xLcj3faTOo#zgpdXw(fmom ziT6D&UtO*Duu@P-7+|G%0&wCd9=b070F6&o>u^6%CW9~1n%W+m4Hu9-np;?5E zTT7LUErz6!IA4?_^7czt^sob{ctM|SNV(A$xsP-X2nay)9wI&CZD|4OA}Y$xwB??i z5`^G59tA~E0UPqL)2=XBEDo+=`Ly%0V1 zd>@Dw5mSKv9jVjoCT4m8|-ld+hd?}ApBgj=w`c3rz06|TJQ0JW68D^X++60Jw1lkqivIpY$^ogwJ|084roS~uc2ln~a=plK8(l@VUrk2TcW#DGt3a5H@S zKe+94d%rTWQ)gt-%gP&8rxoF82Vhcyd_);aXN*@``#RrSZpimlr7VSA-s)ROIO5`p ziq-}?5Do{4AXK~$s+g}*y)ffFM$9wgtyNPj^r0~sp%`K*nf#Q&>EZx{iXe$3l4@Gu z3vx^CUoUHSP~C;PSVBA+Ltyuilz>C3JV}z2rvNcEA@&=5_VX7rONTBTaY|BD9Z>EQ zDk>kBKmdT0=}Ok3NjMHP7E{JmFw7)c@WBde{w5b~d-moevW*ERrn)-elN3%f{$qU2 z)!N zaD2sz4=h#3h+}n3#@AV9mZ6xRjA||L;8!bTzUwGFW7Z)mc@HCpr2sF;aYk1 zXE2_s`jf({@e9h>?rNs1sa7DCMyh&%7##=*g5RG9H(%v>jypAvV8`7Ri&hF#8G4p> z_iH|?!{=7%mM}cS)lRSBohiYCNcpE1!)O{H1)4XkMsf>w^5PEPcpQH-SxOdqM0v@e zEu%sbIyQQUt?{w1l%cLl3M&X{fQm3Q0U}VU0PwPb$khqwsG)()r|iD z7C+X!)tV?V`b5L<*lHEvnv}>ISpk9~B(Xbzy@$g6xffqPrCbrL0GuF++ko{I23#w? zbxRn^us&6;ui|lI(1?1u2*iRQF)uZ-dm+5 zh21xBvb3vdFlQpr>vx z77hd{*A!A?r~w^AgL27kh2I!~W7Z&9pNDvq%HBU*UXZjE3L=LD1S;P-MATgy_c1mXt-rxFqg z#DN=5Cv6+=C6DAUODiR1DpsO)l457bVOKlpZw$jSE*sRWStHpFR=_gG4^6eLwpx5I z=B7sPaAuO{z~7iX+vaeyn_5{QiP8eF!^9IFyLMFD*u8>n^5?FW46W6u8QY4sb$QY0 z^YL#C#kt(K*=9Lg!vj7c+iTHCWa>Su6A);VtLP?3! zF(x>WB*kNb8aH{Fbr`5A#euR)LZEt@DZN4I))fX>TCYu5t|yqF!Ej_WwG5M_%TTOj zWSWk2Up7B23E%cmk}O9ii`I0fys=W1-KIgtK?ZS3fYdaJ>e&=!mR#v2yu~O%bz~8Q z5JU)2I2j;y)tJ*|YOGe9pxrj9s!EFGqN~N~mU<@ne=yLgW3>SU`IEASKHwtWJmb3$ zerEpe^x_;@Gau4XC(cRRvxR2vY@f^9+gm39k$|2FNCJ8*OwOQFMTm8G9K!I}(kfr( zxT>l~2GxyfruP6I?%NM^c>8(TyJf|a2mA>>^oqf@Q>yqM_$2!cUhY}y)?VxHt-OXh zKUq^ngf2y*80uFSSn4YyWv7v)g|+fy^2d@!wj`<4gU+7NGHWdNE4H%CMzGR~1FG9dY z>b`dB)cqunE#b6MV6{@FBZ;MS)p1D)n8gdz(io6~eWk>YVSZuO^8G($o3NK0cKL3l zrIf-@lowC%hSeqvNhS=9krk6!S8jKi?Yk}_#Vx7yB}6IGuI5Cjs04{4qf|^yREMqX zOEzX-#8MudX1qbMY4B`DiwpsP5W%!8vPB$70!JE~7O>r=&B*3v?iNdFlw>Gk&9H>J z6r~^IaFL`bYB;EYAara1R5^d0y_jYO;nkJsP$->=Nbx`$04Ec~@g}dcr}rG{EhIYVqOETG(6+T?0EkG-UCTMpl|sH7>Y zV1~j{LP%sNs(4CpDnG=c1$%Sy=kA$#^o6NC;@xpdROt)Z6Z|_uM*&4o@zKfA)qWx! zHR)XnEB^o@%h_`cfD>UEsjT;c=s>to2|c_!^CEjPzE!Q0>skKhgwL2@xO(=SY7Wia z4=Ai{B>U9@tWWVf>+W*&lhaHeJ#^?&oL?8sLob%ANlLX1HWj{ji$KcZe9If^2D(`D zmm7)M)sJYGj;7?PvHL}-Z5UB7fD;B%K`J`1+0$7>jqkbL%XB5Mhd?9tZh}$?lOhNp zh~ez270n*H{X=KWYM%<8u9pC!k_n`B!xZ_m8>kVy^0P@0U47&VNH@PaO}M>+Ztg{O z-Mq&|Y#aBLes;&@&uOHECe@HwdH);zQVs{sX(6ya{1ICz=+DnSm1- zKn~9OIRM`N7SocRMvvH!Gg8iGVP2JX{{V-M1ZcW@m*}yo$*^{OGcaPpSfCS0u_>i- zDTYNT$m`ghEw6FLbIiasV6uVCRr~`E|y1bnkG|+)+x%4Z%Nd zoMeF>XB;SBpSEt7r2_MZf+0e1`EjADgCyj2&Ghxzii&!7p_L?BXe%UDc@cr#=153QqU4K>-MAj?d$e53 zv>W?|vj&@O7O4cKu%s`%D$@l@Qh)#j5;mM83Mk$U-n7aPg*UB5M**sE1IwBt#xOW{Qm%{ID>e7%EhJ_&|B$J6$#vWAlmSE~1@%R=YKoqKau!H6} z8nIdotDI?YDqKGSph}8pqexiGFi8PVg@_~BuR0r)?pAW;gKSu|hZ;j^X!ov$+>{b_ zX;6TpBg8S`6*(!}l>rIVIP4hA?5ZUEc{-I%g8Fd6I&D>l)zf3xb~iza)S;xAsMd`Z zPtqFjqMVj{C_vly5oPW~?b(J^e8%uw3%hc`vu@|SGL<%a_Ci|F;661dl2kN}FhMdR zftkC-{SB!FDoIq~huZ=V@e@2fYgkT{^_Z8 z=)%m9)3SgUx4nDouMG3kp@#nezF7AppPf0n4H0(i{{RXPy+Bnqb*ic=+{J-m<4GE# zg;xFSBqZO$!{NjhSfqc9nws3fUWSD_dO94>>fS|)U=p61VIddLg#y~>3HAa$92dNh zqyyA_=8GC7Dn6eIyMM#dd9qhlvvzhcwM1~?QAH4RVv-%q#7DZvZk`uB1v<$iZxN4G z6=x2mK>+QOKo_CBgP&@8;gB;XKZI97hg9a6YbsiLNl_z=Pf; zF5fSCP03nYSx(uW8!@5dY(tMnVffaUb?ta#~@Ly$@ zTr>U6_Yx#X9C~LBoGW+NGC(Lv!0iToI_Q&nw83!+`r|e&lBlG|aXRchF!(5`sSTQX zj6R+%0(;LfXBShZqfyC|Gk@|~mBXtd08#NA5({Y_$j73CSrxLb@|KusB&kY(5j)?Q1RA3UjCgZKMG$;JqXDd z_^#?NNinRuisQH`qN?)gUknW-sXb9a3r1eUbS~tnxE#c>VoQ#-aC9YUS`?&>QL03a z1}Cnv7ca|RZAfsB2vyRgk^Z`{rr=EC1~>>Z4H?S(`BV6+dVlH`7m=$*7m3j4>fWW} z6XCdhb|*=M;Soa=)HKr7#}r0Nior|nMzNUz4DAp=2@G9tu1(p|Hp_Wx?_3Mi8*qTo zaCesr2}--Bn^8&%mO$2^B#9s}?`Bz+@Mb@qM{p2ZaKe@nvhv%|8b~L_tL_9~5YOTSTADS6f19DiOGqsxHDp$CBPwkrY%EQu zUDfR`F5Y&p(UrcJe=O)}OF=Q-Az?~P>^ee(ksur-nho3TMaJ!4Sd7LI-uHx~Rw$PA z=usO9+XIHtjR)U|9(L*k7!C#L9|o$IFXV2QtUMMi^96yG^$4R=dXG=K3S~O+*pP7@ zB$$D~m=q~u{{ZlqE|2BB*@$6yR!ztAO%zfUhPF)UNr%HC_XQyo@=T*!9oq0Ul6Hl? zH!bPCVF+4Oq?IMc^f{!!aR4V!LdGddfKow)VkxZCFSlXBn|(@71YkTfwIq{?8wnUr z%2{-?{uB3}dKcCV8>}4`$#`A|SC^y}6faSq@o$=0wv~T4(^0Ha!y=NhM19s>2t1Hg zyxEoNN9KcG6$J$COoQPk!;E=Uf0$*>-Y~WcOFG7tooN_x(~P9_9itwaKh?gLzY;mK zBjzfcA0T;^5G5q!V|DwDI71U6gF|ciX2av~<kY+{A9Jjsrc!>4UVBXq4w_+LB;g{aM|$qr)P(?yfGiC2I=71$x$1r~*)(YE&vb8iC*{Y2C|97A{NIjQ5ar zCP^S2MOs2kCu)?eWRghPg;k%e4^eq$o1j>(Bk6Od{WWY}ml?#D5z4dR=4{1V4H;SL z>uD$(^stEO9x^SxMaf1wFCt#ew+``H^3i*mXAeHbkhm*Tt4)TC0-NuaRF{_8iGZC1 zq)8<})VsV}&efH=RN%KtTzM?$C{K8mxJW|OkOrMZ09A<-whdCgRQ!0oV|4E`)aOo_ z(qY*~OjI>BS;BDI8ef{Fr-Z|XLoqbW8d@bJ7uq-e@V_(tU7Iu;NDn@dI+CKYWkl*! zDD6tWqqCsUJ&ogX)Rd(tCy0)W0U&W456X=v;l=oidZ5Ty4m;`>2d0vXr5!o`T>0{o z0L37rua)XrZMd{FvZ!jC%Hir187s;ZH(pNKv9$4-ecJSsHYr9$cb9 z?~;a+q^Z|6VAM{PB$!az1iRe?X6tN=tBop^D5b)jKZnC0q$uHm5d?KrH2THLcpgyn z&D0zNE$6&fJ7(-sT4tfjbK^CYHDQ`{ZfG{W-JF8f&osKe z%!4RZvzG4KwA+uRwp(yViKVGXaciFNnQ*jm@WfUuDHl&BM=0<9}> zm>R&+5(!ZzwD0v9)V%ZSXDHWa9JiDP6+zNm4-=`yMKyGFKQ9@sjuAYM?%ppp;1t|i z#n;^g^Qd-DH*SKpVX9+}J`f4$PhXW!{nK_=C}+G*w+cWDI(5J$NkHPT2$Y?J%vDP} zqq%f*Be}N0ecuv%IO5b6a3qt237v#D62|!dXh98ECJ&L?k9ttf^9>3XGW4qYxld22^zHh{vb&rCb;$C6{4~8O-!` zl=QWLEiB28aB@#x^Ixz$uHLIIv6o5itAL$Gg z90%iDZGIcRytBq~^a&rKu7zb;F~N~=`SA?rjn++H6nJ$H^A(L^r45;bxWes;MumeTKXunCO(OWtz`C*3$sZ&KpyR> zC72H#c@*DUsRO#(DdVz8JABP#Rnx;!SO6FmxJRgi(?3$bgf_(GOQJ0es8K0wAhDqc3KafJrQh@rTRyAn)!oN3FU^ccno*M5s& z*u)JLZWlDTWUxJ!NTl=Ruw}i*@Zf{udvH3ZlJf~tNKnu~BVmc7(#o4!!NBSV;afI- zAKAk$^taWp8EBk_nn~Kx#5*qb@8ig4D?;us(;_?z zk^XP#MBC7Ut3;FyL_X1g2{9xS10FbFj8k>6m`8S{{T|+6q(Jk)Unk;S(Y(%ElncISke&k2k)e9aL2>h$)|IyyMcOz zjU{$&3~-!8dg5cIYaKg9c0ZRoPxm|a&z7K5?4aWatb)3hC8|d$VDW(}>brEa17a=l z(~!y<1W2rmamXZj)hTtGEkj4vEOG$FS@9Xd+Q(=*f!tpA(%%~nNY<$bG%9jU{Zf(jCx2I0YO6pz)2d%ANlJ?AHGPb6mG~QWhUtJ~clF{v10c9NXM`~NinzyGXwMDso!});p-7}>+ zbrd{}Er(aAcPmnRu%tMJj3&AzaoNsLlta!q>1hc|I~ZCLG1Dm|sWCI+pAa%AnRQ?B zY3MZg_8paaF_y48DDudttdkMSxGiBwsQmI;)OQe3%S#a+d&VV4Yw7?4lU;@8bj7;u zb8}^Sg{3f*CDfs_9wchi6yOJ8@Bxn5nn{yxmR{?ry|qo%qlqfig5V{=ge^zK=>!;w z;ZSbGD});8sG_V|WS)|qy0!@+cp9-J5v@Rtb`8nA z+i8_I8?)B4wpQJnZrMDv6*AiHR`r$0O0=ylHuBc%N{WE%rjSuEwbsiX-a!k0HTn9OKxf)Y1Vu?5@e}gaDyQ>Nya?|bt;CV ztvHTh%~{(FrKN%|>V-}(i`L@x*nx`GGE~n==Dr_G8~f4k4Y-YYH;-}LZt-T>cMUNK3DIu7N+Br;8H|UP^0xz>1zcb;r^Ym86@2yaaPgH4!+Hh%YjnW>BHB)ro z(}=@`dKIdLq=6xn9>#b=GPzxLk#7#-9&%vOJ>~;>q<z8r$yN!O$BFxyvR!E<)*AzX0~6*(KJh><3G2_( z)m|rxX0D+0*EI~sh#F|3#IUStnw=i+7|m4r-yKa!Z!OHV^&puFL!l}i z0}V+df`KF)V}*OY%TqtHa8E*qxb)ST^ds@3=++S&^ccNNd8}ef2#XKQm^>8J_-t`q zW1+(Wz@y44*FI~zk^wR?W53(f@*PFKRMTvdP?plCi;GlC&KrelOMrnIJG6m- zOjnVWZtc)W45=;&mkNn-a}Wtsq((8IB6S(z0;X~NPQ5bWxtkHpIoGCXg~5p}J5xGg zmDI4sJV;TQDyRTJB?K1kNdWtKiTRMUU&9hgda7KS)VNlXL8c#4Pv4jVzLeb1kRP60vcTdO^D&lz4`r)3VHRASX_ zJ{)7JI8>EWeBCW=JTz=4jQK}wit0w2l0j zU=1WFhcpD4N}!0NYfO^ZyoVf6J>l^oejI1`Nq|Aw;V0iqzrw2l>E}p2TxL#>B($YPCW`6=xULu_K+VOA)?wHD-ay-u5pM84~aT9#Z$)O7+>H4P+4;Uk7P8psUh z&6_nKw3N0q>4b=oIG&O=Nvrt8XKFmgWnr~i#e)v_(_f>U^US|va8FDhIu16SXpe;? z@n*tl@Em6j#A|7(A&k_e>MEj%LQIz)^o*b`=C$}ryq@Lu97`>&LsE)JNg#|42Vnr< zalqhd^*oe`RuVD8XAF8OzjF39m$7UU38BHUN=oUlmZ`&PT86e7k1o<~jbsr!Y+|qD z+-f-)-yy^jTy06z0@JM}I)@mLFbAT6tfT@!Ao*ieZITxe!Se-u5`w?Vv8j~VbwaWb z3ATeyWnKQ4+Csmk(DlNSBs55YTq$ChD_ie5)BtZ!g6gJ(Erf#l~KG{OTK-s8b zOng0PhV=KWF?8SYGRt^${{Yo&B9}Df3|9>`8I~sb=_a9`D#WFvs2&9wnbD1y4Zv<3 z%3sbcIRYO;Y%NS&?7M5dwm@1G6t@x*wE}QL6cS-d#DGbv?|rv=5vx&|MZH$*K4i}sn&G?z5Jmwi{Sl)!#@6aV>)yoBkCU$4Y?<7-6&yw_9|b&6;^` zIJAMJAc9nqq6s>NDu5zjf|(~0AnbYQJE^#bUMR3Gs=?BJm1G$(JZ_@~$5#)k6uFlR zt)gR3RRujGsPhs>`#PQRo9oFPYyM$umsw4>c62QcCJ^F~VM!q*li~y(JVpj+7KYAW zbD_ZCS`<>Cd`Sui5KIgwVd#TZ&(_|o;69i-iJ$On??==8Hj0BWS4jg^#O9`2d8PAi z>mR-IMO?PaS*&fT7ZPN5f0$(mNz_K9mxvpfnj9G5b)hOJ z%#vz%N&4A=b)zfP=01;REQwKvK_HGzw5=SmNZ#-g!%(Xt0==5nI(YDO7ol27gSH69 zI((`jP?6K+PiEDdM;QcpH1x7y8GyUI^QFp+bq4o~lD;%tJcI zHAQ4yM9T4`k(>E+F}NhHfwG&H9l;(Q@52_}8ibKVt~Wd?-+F_E;vT7e590Jep~NPy z$dgdK@D}pwsv?1!DWLEmx`A%$dvgT0b<><@_YJs6cP~(6tQjgoij>|R8cu>IV453R z6qc0U&1pVZb2Xy978_L3QdHCjr!lGttP3vnw)1~&#fk57bmv5qY+W-LA7(WKo3883 ze5&mIJ7we4zr&BHSq@~hlr>qVnw=DuXr=NX$7y!_8_Qv*j-%VoNAHOKN4-ruq>y{D z2Y}RCSG(O^wcRI9bGyrEktHfPaRh3^{Ng=oi>qU$s#dBFgiO9-S&24b?vOhXbA2z& zx@?qTju;xn*8o_aku;jBqnph@gxd5R6Xj*4lhr>KrC#%6JA zki$`>&Bgnhcz;J0r9hpOKvX@;PD%!SpiQr_}_EN$RVUfAk+&gJW8}E96YqPhL9iDZo(!_ZDaO)H+36oD#og&)EZi(7XOR)@tW=nV zW*3<0vCJkop`MC(>L3Ci(X6q!c$kKe8*Wff*Qn&S%n<~iZ|P7%urphPbO+U6PyJct z+^dOZS?9x`#a3vPd7kwyCXt9M=>gn8hG(-OB!)(}esWi}?3XcV=Nh+8wIroUN}z?d zPN1Z85O^3Mj;hYh(9auNDNs5|!^v9;Ps*#))aT&O>6&c+0E=TePpB!A=B(dTm}*ls zO4CgGkkQ5VAuZS&5D&wN_dB)S;CkH+xnR41+$6Y9c2ou%RT`HYVrD46Fx)$Llw3oa zHA#)26Vy0Se(7hX42$WjqS@~P^+%B_daZ=w^xr##<}9I5=C22ymvD+{X{Oq(8oiy7 ztiWzo4va0*-Q3QsGkXQxEu|sZ(n6L}wj>-#1h%BAM~H<06S8rxVfLxJ+0IXxF!i=( z-I_EO`=?z?Ok60a5Uoo>!-@%%DU+m;rERS$6GO&9^)Kl2Cg$v&i1ho@r%mMPT>GkcV}E0oW{%t3T-dVl2`B-{SXR&O zYAGu)p@66c~ehYx4faItyYCNug|PG-pY_t>CjxZLZv^mUw)qbAtDk; zpdP!d{)}ikY?aubr+meUV;CN2X)yfXjE1Osnslw+*?TiQ;g)yuU*%Xx+w5bK-e4E= zYhvEqwAH(533E^(#U%&rlRfcDrU6kB!5?1ZgGU`!uwJj(u zkQZjwpn{!94yD8vln;C(P5{c`{;z#MQD^+wldxY+ok7F0&M}wiV|ctZ7$k_& zFY_D~BXIPTlI|OlHCUEN)z-{d5^JkGp62Yn=3Q)};z7qxcvd8r0=uk1NdW6grU9KK zpxgO|Xe?T|Z+croT3Kq{NxyX49Z5=pTy;fCanux*A*WK}JC!Xuw80NJm*QtpnmQHJ zoF_2!*E!YVIAv@URT#OfQ-fzJAgxB&b|S2WO;tjBtYam`O59%TrY1(??%k_xyvAK@ zmzq*kSE=0xNz|eMI2CR19}f=)q-;{y zeLAfaWjdii@%|dUcj-PY)!hF8(f*V4>mBI+4TP>2jnd@|a(Ny)7N}=}y|Bn;0qN-` zmus|YJh3L`P&X0Cv$gECtjV`7+GQ<=5(4z7sY+4@fUQL-Qk4e{K#(v8OaYO7k7jSV zVwT;%YW)aNOD;0-T>5~b~}i*v6}vahMHOZnT=j$x^aN_^XZ z;&?k*S;88ccaABB(f;P;TfOc%fZLJ2Dae$Eo>GCgQdAOzsY@XW)!~5=wJOI6#6@JD zd1y-ez&tA2aEKxZ^Mi$H!`9mDPcdP=1MA*8H{v;;B-G^me#29bWZJnf>Em@_ef~v> z9qgd^bFll|%5xhH)Nl7bGxQ?@W9$sB3>rS;g&4^C;R@}>_4CyU`2jP#hKaX_EUObc@r zT@25ANf8HfkU>%|2qb`CKzP?LU9T;jH1$FGQ|L=s;;4z%l#uY+AyKhyD+N4 z@r$HeK9nU6G(&1qJPH9LP)SB9Uxd!M*QOGpe(FB#vmmyxR%eniaunN*uH*7bR;9LH zQ9a@bUZkM8FhWMq6s08~R=0VdDq{Id9H7K&D(R~su0pF*Om7>?mRE^^A)}QaMnVRJ z6)X+;nJ7RBC>%YoaTSKb;I9=3BLn6zKKi*{ka`2?e^&h|Vg8`-+-n@A#c@xXr3Mp6 zQAbUT(<=c%P^Feom1-Ah1Tvje8ynzG@o(;ByIH^Fo^6FPPNa!iT~jg#cs77gOz{M5 zipVUdCu1|U?@*-$!RRT}IC&kNMuX48cQsb}YxTv`&Z9?((pTXa{EvpT^mQuMXI-xi zOl@gmmMJ~fR#nt#yT2yg>`8vnWeGZ(A#iXdAmTyUv&Gghpq-j~)1?0Z5Gg%g-(`Iu zl8X+`xkOS_+2X2*9p1u4)rZ6$atnVlq+DG%1_8hvN$4a@k6$rDys`4iQg-R^p18o( zYIR?y*oF~^&qmAslS)p~dph^E``C>~G1GQ)b>$Zdwz)8ZNHei2;GyTosP$0GFt-;d z3vX`UG0{MkB+gM)fJ5x|p2tJu%$iZC>M8a!BPb1S+8uuDd^td>Xo{YS+A{*AjQ~E+ z4lY5YN)c0_nS{1Oa(n6ZcKGl>%BZQqPAgZrNN{@)J?#O%W9{MSGezV@aEXM%^Bdo> zJ|93H-cdA>b<-$D-5CtN!aO{Fk?i7-DIpc%J&7jWynB#4{bR?A+Z3HbYbVTIjEA-V z0Jshs1kq}Q)(NKF1%V*z;&kt)#PL`Zn_;9TGVK~XZb;KWEHv-i+sE|CqlU~?dHT1? zkYhLmjWQQWBV~O7>@)=0+WdG@;?1hU#@Q7oWvcHIQhF;_kLvC#{bv6FG*=(;TJrq8 z&GtUsy|(gxudA8S`Na1hoZ;Q-p16ts08K$I>-L&B%z9V<(m&FEIej$Abuq_^dYQ^t z@*!_IAi<v(0P4A>onEV$rR8|xK2*QUKWYNAo6$8#L=-;rLc>*LyAh)3(vSzq>xgrL@0uikYErn7#cLpT)xhqUDe}>Q;wNg@C`(Q zF-Y*l5(W??z!VGQZ^U!(o#AjzWG>*5=;repK0l&EZaPiKWIrC1jrs!AYsu0 zDZ>){X?-4Hv$4avZJsL}TWFgQ!66pz8p>YR9fxmbyogu0`9B0VAb&yM@P!JQRo@rD z2m90P+3%#rG5Gi7M1iR?$4fD{g@PsPvD`2lD6%OrQL_Y5pdYu5Cv~h5DM&~Mh-lCI z+O~8Loo&l|fDPBqXgQB%e?dl$X*{3xf?b{|nCMgx^noXP^f znVqrMxUmWtgi8fudjc+go*Xy0=mW!haRv#N*phY_Fm!{_LhEI&+{#>5A`d#fXb0*S z2>C6^fxH`(Bd?GN|BOC`uPBha~_~-h;Ru4m$@>~w2-OdwJ zIS053UZ@Q|jW}s-yY?1lLu*k6br(+Eyc0?P0G1%&Ng(wBQStA`N7n`;fFGHtz*iJT zSmK^M5d=RX@$8nH%M*u2I$VN7p(^6`JQp!zW{^S{jaaY7qpnQ&rx^zvdMirF+gg%b zQi?zz3RPDr91{h|xOGHsB!+rCi-$!lOf=mTyNe@O+Th<) z--9$=I}jUL5fQC%9UFQ$QW3bhLg1+yfy9D%?b-zGrA2S!Gx&{F)TFfe^kK5ceQ7Yd zIF>=!0){pq0o&Qbls4072n;qlm8o9IAdb1E19kH4bD;kKrdJPIPe=H$ejw{nJ|joe z38JZ}ZSzzNK80tI^}ER^r!385w^DRA7T~Vl*uEjQP(a}ZFzS*zyy+m^T&$A5=frlM zN|VxNW@#e-0Ezzqua~WozD)4*)YJ()$trNHE}_AF3nNWN#RvdfZ@~Ar9!5ssQBrLY zCuz{B!`Fo$v$~cc0UA^iI0YyVWbvtZPvV{Ug<%zDgDm3|i7Zl=Or3^O zR=ADBG;3K$3~r)P?zszcroe-*B;2#I%e&=;jJ0XtR2_6C5BH8ONd#>hBW^Sw%y)Mz zQweQv7Sa?H2o36(;=b=$Pe>|*SG(!A@i6IMTyR=BPe>Y<9;JrZrVB|8T=md72GtQO z>ZG*s2yGZw)z)o6(qz#^`DLK{3_=k?^VSa%>9?O7^KqC;ZS< zedJcJzlpC{t2)KiuBlg1%+k?jY{^H0K^c_C8H$orgK;PA0E+FWZO2a@O4m%L(=BZ& z5TX;eZaA6_W$HIK%Y5u5YmwLX`+yZgJu=DoA76c5MVl}TN?OOp^GRu8mXyTM#|-ID zOr$Ae_!q;|yMhFF7a3j+bL#^R?R`x1E5vd_Fv}20B-pbimK6+T{ zcdQKem+*WcVZ*vtM-FDB%^00a$K_Halr7~>VP{vKNH&K+Z5o@ipLdfMZ<||XiB7St z?MYK@jjG2^1_;_}2;KW1f@oog!%ryp zR%oJ;k|}`pNQxWiBHZZ3yXEH6qs1by&p)*c-Z%&JrCmgTNc1K>F`-|k5S(8>Qfs_N zCjS6sf)4)xuYL)#QQll?{)i{tg-3bfzb|O65+mDIbJBdHHg)QTT+1k=ip)ZtUjG2# zSKi0yvYr@cSAxpb*H7@E$DBvbv1;9)&8#vusD%FjrZ9cRX!P~ht(Z1z^;c1rXt1+W zHWu_5dkBgfhBY#6rh2Iw$7;mW5#G6F`9~*VohHe2^!R=q zg+oP095BYHrsNhSR9khdN$yX3lg?1*x6WoO?_W_;l%ldpB*{H|BV~8rcQVE@eKxkp zN*ieb03-k~8%%LLPSSBSK7-k7am@`fxBMClF7^sYqs4-KyE^pW`$LryfT2kuQ{p#cWDFF3RdNEA%H1|*H zKc#qIrW4Y9ywg!;Omi&K;}Fx;+Bv6+p?+F33}BMTih+xp3oy0#Gkhl6%xS>5+7*vq zhCKW;(TJ!T@s}_2Afxsn%_FNw3X{}Hj+qo={a)h()BgaX`m73?RgS5!d_M)Jx4ZgD zV@T!OZ(=Ly?BSm6vEDwXM#j^JQ9cp#q0ac;ep@e6L4vZBdCuQ2I@Eulm~=U>)$UiN zr~d$Pda9;rScMA|TS;NzwTZVJuvmKJtaK>+swB*Z#e~;Y;*Kx4I?zERftZfOIR^g#SC1Oa)B+&!Q1?msP-`e`xbg&l5T2p8EPxt~w2CMUt@W!Id%wbHs5Mf^k<2 zQ^7p@WD(@9LJzkp7B^?q=I0~s}E?CQEOy5q>0&&vl^`L#HSs{ zDsp#6a;;rzR#qlInX6ickt2>InmT%VNF)IV+T9@oQanH$ntMIWi`QmXA*Cpk$Av0{ z_@oR>7&~BeO$zfYv?k9|ksa%JEBJ~EjuXIPAbQ0M-o0sRGIyr@FQoK1VXLdo6Xo2y zO!Z6@Qp-_M8nloqA9#`o)O>l8x#sb-%T74zHOds>)vyH0$Uqo^pqvi_?5s=O4b(SR ziCb=|u*$yF$L%!&ke3M`Xpnq3n5%cn`6`Fg7I?;eGxWO)qs)tv<61ef>`D;T60=jq zG{KQil^9t|DgmjmxxYAbpYL0(US2%%7+a6sxV1Q>YgDUA(2!1@E&YJ)I!QR1>t&W$ zkjqF4P)ltk0U*L*GAE{0wByE#PvWuaH>QiMbiw&U=}*i-KbnX+Q`;C=v-uc8Q7Uq*;zu!WdDBGMFTiL7I8| z74Ym2rXPkIbyk+9d?Ke7&lufwwKS44Nc7ld7L;+Mj~$!IjPHG><8ZyXnMrX6Hgf9Y zyeLAgnLQMz~6)$H~*uEK$6M;@)7Kl5RA=j{qCxo4SXa41%P3i6g3o+plu&PD6}2-KrDf91Cy(9z;m3Fnae65!T;YSpFS^G<0}=C7J74~^y0cI%r`Q18#q<`oK=)k#|-pQ)xk|pA*mooF8XNLt&W|v<`wpdl)akg z>c4aQl2j8sMw0*m$I_=A&&(RI$`fur{RLQT#7Xk#^Q#K{Smmmdp&3sg;f7Hqc3_HC zF$6wZVbroq=Q_DmXyN-zE-!60=15zpgA*9U?K?0vk9)cbuJ!aGME?MsKm*Q*2Tf=? z(Sbvhau#pL>7{JhjL_2r(4?GJH5=G%dMBKQZ$la zomc_^5st(7)VP~Vd#8a7;*ktn68nNO@|G+|N6gi>T&lZ%>& zso%vd(w3t!;t2s(Kt|ZoX=MOk={_9iX7*-@b1$~I4JjS!*;1QQf|LmHtWL~h0sK5kthH|3r8fvJ z1rHEPzNP(Qufy}y)&tgFu*pf1De?S65C%#r$g63qX<(brG;=F^ zh20n`wwjVb&~i&cvi+&tdy0ruVfhmCieDNoU zq^QX~NX(wRa^`-|d1kLJ<9Xy_IhKNks#TcFOv=j*TyBK^iNMo#x*ul??60kvv?#V% zS{RfPow6lbcnR{tr5j@7iBpd!LX--i?1+i-t-$)DgJt|@HTq@r+lsA2;@GU%b|nOB z4(fHJ!{v@zws}dkY+G){?!&h^IldMT-rcbJNG%kWjGRlCR~l0QVnIxm9fAc;83uTp zD;v90I+oBfHUQWhc6CPDtnb9zEH_er984DqMKUAi9HoY!P_ym~-TBc> zmi0C^8M4L!F5Hhqp$!4}RwLX`>_-(8k9^l3#}5q5ndkh*^sg#SO-qVqOwpWi0X1yC zT{KkTW2AZJU`P2R+);d5!^fDd*!A)<2ClE(N{Uk41f)q(Tj3xMv!`!GO&OC4ywZf2 zj7d8H37PlSzFwj8XGNbqW%TsPh1Sqf(BKl%S5@K>6>LhPnVda(!y^`mO1;JJ-~b%! zp6@pOuu*r4&?j#o3j>WPlP3h&G<)-qEio9He)4;Q9Mc=|eog>UKGb zxPFWEQwZr7Lvr>fpKxc!9t%v#-?z*t-?s1hCoOn*T{oOt0rqJ{SD{$}ZXW1N0eRKEgmOdV~({a;i1fX`SR zY*}+A$5B0G(X+D4QBaQsBs9^0M2w{F)PfLR{v3>ZXT1%mAIC_wUf<%pl zMgSWO8KY&xK~=(M^M3*v2PI6;yth5(W9<|}qhxvp+Sz0JkilC`|)TBBl8CN)eFNnF6dK*Y^O`POJNHycY~NlIZd zdQ?C$=~_a15$mt5%n#J7)_0H9L~wgQbRp za6HYu{>U=S(7v6baO#+7+KUu=j2T&CsGUPBwAHC6z3&pY?HOkG znaj=FTji`R#`UF34g|HSP3Zzsl9Z*j!BPkUND4TDDALZ}%EdZeQdHm{dS!SSh*8AA zz>FhhUB{?@QN2}PO4x+njvES-s&(kGVRZQIL8qgjY2MOSSFsJaQ^j@&E?M@d(4I^? zp4IbNcxl!PFDb`0Aw)|_)~Hm;1eAb4lO)a{5ka>d3vB37NuC23o)RMwu$_ahwf)Q< zh`$z3Q+*%AdNu1atC=eu%UG@_hSgP9&`?z-GYNuYRO?3D(w=DE=IbnW1OTN)$0R#l z*=oYLY7w$A#HwSC$}r1!b-caB zEh07j#FZ69%nloCJN^kCi@H+`HCd!%*rqg*sY!7d7_crtLSrCAh~yBa;`Xq=5+{1f z6Cu!N5#dRYIDkmN9y=&%cX`{D5ZD-CW^ge-*+O6#``d^ZFhGsTn5Pml`J%qCICVk3062lQYBakCWQ=c<2M8# zgcWfmMm)@5Bd#D)Yt+_9^yiy8M~ZY;s`!3h=uH&zL9-QUBg1hTaO@?GX)5J-qu(m2 zMo{MKy2){(UCZ8kTkE$!ET_BHzUH3}CCE^jC~;~qMk5J`APJ)U+jBoE+E%{kHdP_U zyh2CtsY>8@jhz%(vMx;YeKl1!Ny=WWYw>#IjyiZ~@QhCmuBaj<76B3su zC%-04(|Fm-kX^ab(EgItQ$AA@1H&8=0Zg8t1}D;y@Kk;nT{!B&>Niw< zRb$w_bsa-3Mi-7%)O?SfZKfHiMjD`P@Q&igUi?LGyk_kH+d_d7l9^Z_@c;}*Ujs`6 zHi24H`Ux9Gqy-4zago;|k1warzIqAu51+FhTJ-siVfnr+mqkZgjsE~I5>mpER{5(= zUFL=&rXv|+V`3~%G1Gq)bcWLD*Qk&Z0=u;l1u!HSmkJKg5R~z$cOwlbC^V!*OyHrn z86%(rhYqSCncML`=@(0~PCM1UgmmJwKVi9R5^TFyj#o=hPlU%^G7^!+5}7I{NfWfY zR>a!E{6DemO;6jjo#DDsc}WW`+vzDvw3MkU;8Zn8{{W4sf*_`VH=Uy)*NZuOWF$|G zdXh*74I^w}#w1ZW=|AFO)c*if-A%|H8_(HS2EjUM)LQxsFBzi2zHuv(3jNT-EOpNN zLq|AYFl^NW6(Ov6CcW(P$8wnuw&SWuZ3_xfm1$WCGI1&?KgF~`G*YeLxzF2ilcXzA zLDC}>kW3S>>BMlDtIf|Jf=8p-FhhgJ`0X@O0Z4#mDwR?sJALwQN`a{!AX|!)bZrmp z*6WIq2=8{|w;VtN6C44ci|waxrZJu3QZ^!buHt4+}i?~7$l zreJt2HGlHjpp{j5j|6(SaN3!0n#3Wn*lq%oZPFk*Ti#T=tGws5T*bT8wzn;mJR z5{~f%v_b$Fsj`ryq0APQYDtk4Ct1ARn_tT%)TwDH140$430Vs76rq3s5=?A}ClC&* zl-)MQC7vwLgkcFTAhL;3>oGX01Jni#jUvdzzV;(W1QVlP{OCJbS^{OJ#HZ~ASOdci zk?H49d-;R6DkbL$3dKe|L?62yv+Lzu=3b2T7cf;~`G=@;QDFGI)9XV`Ejp}|eW_WY zfxSyQB`PlTms4Iqq98R+@Z&7IPGEwDtts-Nib&cuc+emu2Rn!cDa-epFU_BF z#f7xDSX!HO2~v`@fJ#<=(4>PP1Bl0_gwEs_HVQXRxadR4No}%F5P&w8%H2iAW5Y1~e=66@8`Ea0?6EBMRLWT>>0XIVEnL+%x0g@>DhkH; zVhMim?rvGU3vG9H%|27%#XrKL2}vXFY>_1kmgE9N<3z8!bjm`l-EjmQc!Rlq9Auj}`35 zFJJ}u&SRG4o0x-i+ihDmon7XJ^rdG|Db$A3Dp5FKlC=ri0irDK`FCq=POOt4lO;|; z8g(HeRH6tlV8QFGKZ(vHyMaP*IlB^S8d{3D@cQUl3n3xl!`igbEbv$SydH3m%w%ttjx-IoP`=Jer*Sf8 zQTt0^;E*v}hi4Px6;U48X2>ZJ4uYaFkTECmtGt&=!h(sMV4OYkvu$PSUTXCx zkTFl{zftoxW~Rhur>CqD)nk~0S{j(vXeCqgEDFmR48G8OI4>4?bHiIqvUZ6LrveNS zvw;ysrT2=wctl`8lOjhBux5a|-09T(LXC|MGmTW#F*`@|O84H!;wC;mI(s-;<&~*V z_XfYz(fCoSFFUnL)BxgPB0b-YY(eOQBKjiDdC#X9m#4f#IOc5UhEIpZoD(%-6;aVq zO;H1+l^A^tl3KAOm6{{Ba7Eh3X(IUPnK7a53uyr*X~iiClN186wnXpy|a@UL5r z0GL{kl!oJB(<(@rOa%>4XMq&2!#abUav!LUf@f}><2b$zm^yKpahhC0t2#9uZC)jd z)KjFDlx>O8fjrn&Ax*L>I3M(oCDbnPIb5@G()hZ{l<(zOw`tWi-9bY^3Jwqwv!o^z zR_Ml2tI&8ewK-w8FT$mrI!Oe{)`F4{qCV)rfmPM&<1czer1d}4Njme; z{-)*J%~hDOI_ms44Vso3Dq4!k4P!$`8I8ig;z1;28|)*nHUNx-UcF+{ET3-ShV?ev znp_}+D2;{+Nc(h<6p#QlAwQT|Da}rT($oT!+LVB#$oo}?4`JFciX@$A=^sb1zMSA* zqkTP1iBjbJM-`JVSsrBiq4tzuwZx`_%0iZ=MxO{6`4(AiD9D=R40`*=X|lWOh>#K!7XlM?T+PU85ZhU ze=%)~%eEBgdhCD$q^(5(q^SkO2GBqRgh|+_#HPF6yrEgSv2CU6Tq!ASr710?KuVUg z2^jwX2qja16GOL8`lXevdmCCfrMvXd~ClE@cN^vm&)lT8FO-(AxQI#R7jz-$7MMwx(olKFn#?kHY z8uC>(*CHa_LmU(mqwnVmJ!x&p)a>+vK=x7H>nB;MF|Li{Jvqa&A5SO^O(qu*#V{i& zuC*nBl9)&?WS9Na_d4+f<%Pqrtt-Ilz$?YnaQk|wTAP+q2pWCd&rLDqpHdZanEp=<-^BRY>f2V*UeNU_T6jWkjtB}a`&Bn*=ud*aa6_t znII&I$F7EXerDV02z4o1QGo#Ch`^XQPY#;h8~zgG>A#`$9*wj2scaIa95*rMn*2ur z#A;HgPK!lC#o;njI}{f4PTP$@Cs27E?;iEFX>hxY!6-|1NCi(VT0)SpmsdOz0RbgL z6%iaL9`5X`FnQ#(>XIFAyKS)qBT(_LNySA*B1{M|6|Bx^^n2?_`sT$y*mDYOc7q4Z zSoIDCnJFF>q$3lmbEJk(mxgkrl!{9gJ;kgzFuUITzRNBbm(DeA65n{Ct56!uwwB1A z@k<3A+EXi0R*(s&a?Gq35oGBrQnZ2z0ZK{$3R=w3d{lX$o0bNkYg$NC+lE zz*RUbq8LFi92VL0Yu^}CyEDl_2CRdv+OhhkDxQ^|(NsL;ywG>E{@ydA-S z)C&L)C%cn$4~I&UQat4S)AAHMv~JM0kiAJzFe79}0CAD9%}@0+fqHkwdY{w$qv;bd z(Ek7+q5ffsVm0`MSISgVVlvu0wOvx7ks37(9f?(O;7$0mC$V!(9ufdjz`*|iMok0r zg3C+P)}td50XUB?s(j0ym~)41CB4?&aW2#zer}?NAVt>*? z%Q7%9NEC(zbhrjf-(Jry1>;7=!0~O8tqKVWQWLZ`LX?H5ecEIN1K=d!aZhzSTer7y z)^nB@Xop`*ec?Kg+p3)<+yP5!Af!8p1wJ4)(Qy0}vvy|BUahkyPjD)HG3LgyE^|m; zS)QIDTJY|XOm?!XYp-ErbKjB8gx?N^$Jv!`zTW8;LgkMvsW$?b9kX~ zZlt;1_nH#$E~-kCr3uzXk*8XuM%bl&pl<7THpbq}h9A<(n^@Fa3Q8dWi6jl7T4Mt= z8FVWj=^Pn${H;bchg4I?Ox13zSqu{vkfxxozEzi* zVZJ-_aoP4vtGuzzXk4OjO4Xz%!k+RpxK$wuFkCQ@d_dMY3ORh)v%Wu)Z)^D zOKDNpjHGy*DO9Kqf(hCUWMJC}Xlu+XsZ&9$y`5g)gqnfen zD=^iTD5i!-5j=93S|Zmag@-W}?27L_zP8M5GZ$ECuvEK1(loiKf3Gb5&?piCLZ`b_ z=>U>zHLWwY8U=;4l1b7v%2Z%@QqGsxJtk(Jq33LSpdB&I61_%2 z#U`Hvti*OTKHwdf8KQY znrd6fYH9=%2S!-q3JvbcG~k=I-rlz(vzzCJb8&n8#nkuW#?7RyYbzhK3R|8QLcj`@ z6A4tMCuL+dQI)NR(2It~pa!C?sWJ9IF(BY$0&xbCp1=P92ELYh9q5Vc)=kb>esfw} zQlAd2rfF#Ks;XtF_hWiVV`*BVMU+{g_giPax7x#)r`R8FmYuNYKajl2GYcdswW*t; z@lyq8$GdsKYT8f~k>F5N6^$ff4GJ#Q-HJ6OD3QZv-i{}R9TiWs9ZkmYJQlkR!{DT- zTFPS;t8+zdTe353DxxJT695myi(6ZBt&3H*U#Z5(Q3Jx2-8!Y>1r-J7oc=q-eI8k5`t4EKRCtG!mjbwptl5Jix) z9wB0jM5Gb9B6_EF3QyWlgaCUfW2qo_aN60wM>> zdQQ_x!InCigW>X4VrCjDbOU?VQckg=qiwS@!R~ForHJ_Ou!SmPXG|FO#W)^~g+9?w zlHpjUFC7e(`I`fV3T@t8^sgjCYa1QXtbYBEabiacmXb!%=}R>g#F2+Z3psD1d8;(x zXAsGG(+sSufgYgJ)Kyf+c-8iXU}N`z@Ez3ZMUD7O;v%kEk%bGHW{1^xPV1t<^1o0Q z0jZKBG?b}{);xQHk#~XV-ZonuYzYHXeif9Cit<#pOeI8m(+)R;dWpm_KjzhWi!RGw z8t!U^sg9YqHm!1yAZ791MUR0UxLD>~+oM8~2s|lrF5PVE2OgS9Q{ugEsjs5LvD{lP z&`?!KVp_wB)5%X8c*`;^ilY07F@Go_e+k}<(MMPr)br|5DzOPC(Z!me)1eE{| z5_Wpkg5;bJ@s#uxny5Ov(Ok2SR7X<+OBGfDBi2#X(#`{^@)VIIGA5|NGJtM?9!1$* z_C&WOUJVMBAxc{cJO~c7Qncy@2||HC#i$6Q3)b$El7a%#cqRy+@lM0n?4!ZxPw^SZ zShuUJ2dcehS*URg&sT|1R$`OWB{bBvvLG_yIK4Uqjyi;Yf6oe{R4XRXH|<~ApJbNf zENe5#UqER}3GNC2?!X^lQb0zef)gYsy+IEMg@lgmx0QEIwAISMLQa&JfRaRLQTSt9 zQ06?m*vQZMp6hiaotJqwuivmoFLx&H}boZ%ji-R5=0TjC#PZbH8)!` z-3UE1Rb$nxwbOWgeBil@so8Fe8hVqLWK&y6k|Ba-o`z7uLQ-2uSKVc@>1}o9Zf+KC zrS8HAQnWR2q&k7b5|tE@(5arjHHcf^YPNTZ*~F-XIFJaF1w&8~U#jF<*6t2F9nP{gwbre(>=K(rKjKQ+%!6d}p|1k#D=wmRI1ytyrL!=}}Df0J4l z5(8GRxZ8(RuU+a8;$w!N*(<~eok=5w9d7HbwVEi&CFVf~V3c5Fbl@=IjaGJduEjbb z>U*SJLB{hYUc=Dl8j4XIzmC+(=q<$pS%10)|`EJN5uNpsE2L6$}muG9aE9!Psk8AH`;) zCf5EeSiar>^I%b97jU`$uUtnNV5_R3Un|J1N_C0fO-sd*9AUF-e zo5R8ncu0W*!L*=61Zf;A6>|pAZvtG^r1xQ3zUYi+ucxkSW^SHz=hLsI?2m?Jj*H+B z;Fu09H&xKQ?j)4#07x9&+C!$|rv5zUUiCeBnchC_=`N|iw4ISV0ggN)s=80Rc3`rG z?ew;iB>^LhV}UsA#&*#!p~~Gd$zO{`Kb10XPjDQ_`NJ(?S;B!aD$kOdn!bWZr>(2Q zsEq<1f|duI1&!HN#HQqSbf?ZlC5sg z>d6ar61W4zq^zPy8$3EeBB_`0>A|o(z3axS8mq#dqLUiJu-fih0b(28I#>>2UG2Et z?dW~Robl!@A;mSOL|gbulAvaIoCHbRLJYKmq=T~&?X6F%{S*ih-f4WLa=rUPvTO8UW5?RwHYLEH0&a$nU6|Yka>pL)MEb0ZKq7 z43H4Bh{6FYG6~s%uH^kWUR~xHJ)q3lOK-T$IMPpr3L#z$Ns^rj)wT&DwdBmXQLtP_ zuK}7hEr!)p(d>KZX{UG^zzcrwVaZX8onR_{yg`sNbzy@o<#(m@bLF?X)jY&(UY}S!&SKra5O!M)M@qb z;Ru=uyr`yXtVu}aBpWEKj;e(aC<;gr;^1#>F7Gu#|};zypb^ef00>1JuV)riVQBQx=Z^!xX&DgT+?H zvO2xCigj45kw~gLoo%5Vk0HF*dhCOc8t)VV0Ym^ij?*6M$PM1z8|H{{)puyxQ8J=< z7~$u(j#V`cH7KoI8ltMDE8l%gk2JDLB)TbPlKZs!c>!PDo3(2o3@`&=9aWKSG#L;k zh2DnsTdDmU$E&d}lV&-x)+tpBEK;>BHLwqKs~NER^mt}d`@oP$)k=|mBeBh0$=yrs zEoh7tp+PEAc#J}lM;KB_kT9tCdACZ(dzwpEts&h6sl92`5~4J#2@({NQlT(G=>n1X zULp9l{{XV#&KM?r$cdNwahlf|ik2KIh6?N!Myf9!DTjwm-^#yC=1Ot9Yz-tpI9;5{ zJd*vq&d*(~)1BS69m1Re*7PO=ntQ!kKv{y93J-{PWC*TKZoGB*V!_3sHMg( z8!6E9jzWWW=`JN;mk^W?omyTAQqYv0bZYaaQT$NzmOY#>UYB(Tr`eMe>P7?eS*tE% z8Fvh%q{ONzDaA9%f=Z#OXQ=sdmzwdrFO<>+AZ-P1R`X^%>3M&Zy5J5lpq~Z9E`DvZ z;Yk`=(e{CgN&rlFWYZGm%(#Vg!6ovq=Z6V&Z41E zmIZ^E$DtjxT|AtDp@})7fM-5@Wf8DSsxTD^x1f zOxVU%XCgK-$c6UrR!Ws(Lc3hDH-7!)J7!#82Nv0J67g9o)DjyoH4IdRHR93;)gp$C z@6PMA@=!9AC8Z##YyFmsbv869Do1|~DYn!JRl1y(6p|36;1ro#KYk?-)ZT-2_tmXN zR?b~E$5MQ?N18A!E*gARoB5qOtQ45xK$FL|Xpvc2Hi>}@Ly>sbdh$!W!!9p8wYUgK zN{Z6pNKw_NP(l@|c9oS7bthJ%jL+HL`{dWRUzWA9{ENn08nlw~Sl|j=Q3VL`wwF+a zDWk0gNt)TCpjn!#jyicNh;6F7fEKxo>}5XFZgEQ4^<+278&ZW6rat6?WJehWI`FQD zW(+WL=YB4Uo^#U!3Mbqwc&_qN18bB8C0Z4VWjhE52_14cY^Lgu#7`>aS>eMv8J8+zs!G@@ z<)0s@hH%kGyfh&wq!I^_Sf`!lD=wr1dvYntJ2qOLE53CqK|+!c+Dc5GB&q-dY$qAw zDsJAc)Scc0x23eDNFaj(I>1bv53mjfx%E5LehHuQCKZ+XeSqRPEo3;oJ~3P8N^2nV zX~BANO;D(^x(S*+iZ;3;RV{_40)YMZ;QBedHRFVl= zqMn>n@A96{?lXI#&B?Z){JU_IySaih5q5p6w=WmBFJJIZP5qHtCAo%apyi-G~U8?UE^qTHFDOh`V?zrv&D z%)zT#^r6&$Son4wisau)^i+A%1;yz^nWHP!(8E_Nz=O+&8^h?Ne>cyjlWNNJ;DQMA zB47h4W>SZqX61mDDJe*H2aO|2fWwtn&&;Vt6BoDwxc%#}t~! z5G;0s_Iy3tb2j&O^Yiv?JH(&@CSa!nj~$b@jYK>1mmH@$yJ7-IdRCAG4GwtHK;R7d zbXB^368@ob&PnOlQM!MNSJTl})ixW7P(z5)eC8QjvBVV=br9ctGU^%{k#8-+oxlPP z1@_~+PhZ~IUbdAf3D(-m6`|Ju0EsI}*rc6{X#L=k1jG*aCiDheV_^g+bV0&A=Z?>T zA-1c0+o|SQdhq+KOoG1v{_3otm5NE z3hG#tD0&gbitg?I04;E|j3H7yjw9n=NsmLlU#06Or;M|mV1F=H;q=m8{w6R_*L(Ar zJMM)g2ysFR3Y#;x10xNdT_T*ePj=$adP2Po3f*JLLo#6p8lYX(RI8{R-8@Ie-W_WK$lR8{FyJ=x6)r-|#31*(+u5gopz!Ur(PGnF(-HY}DPw!;yKX+Q;luPhg%>Fm z=UsolM=b!MGx{P&3)3a}!&kd9${J;55z7hIY|I^iUVI`w$ zBRJf{a;dv}$51Vy{cXXDQjj)QD`{CZ!aN#zRo*IQB-j8{fDda8EG|B-ECOl%=}PIY z5?~eV+YK~@N~mJWK?eT-Yv>=x;loe?rp23wfvBmKaZ(Ji(n)pH+9o#__fK!LsMqr1 zumu>mm%WM7eV+Q{y*|u!!Z~1~oq)M3UV173{y=q^j|+kJaW`w6=GOU>k4^1-G!|t z)!W|J7VI?OpD4Rw3P^E4r%=>H9}MH}tE+RapC$(06tc{onR>aFa}{0&*hOVbVT6&( z9XncBq){YnFW8va6YM&2OU+udvASC=I23?V+Wf^~DpFzZQZLW_;Gi;1}$}##oDQ`A3BG=Nz z$8XnO2s?&I8i?w|d#m5sM<>Jwv{b12Us$7MY_wG6uW>DOJBQp));MC)7;h3#Jk*g& z(Yo5OB_qv3m3U`OGVF?`uN}dlQVRRkauP*>HVYdQuie{{1-|g*)`P~jV86&P;|4V^F?X1HWt!_BW*o4BT#HW)R?Kxm)7HlzwD2b+Xx{Cgn=jFM~&`< zlEkj@q@I9BR#L>cDS^GheQfE zYjtwOefNZq?-*G=(*lJ2KcLhzHrO!i>05gRFk~!Aevmf-U{8Vk`QzKAn^=K9RDRy? zWMKH7xKRG}nE0Ag#p$0BkmP3k+x;33IUCD;H96D)(d@%Y$j!sUHJA*1^=k6HX^ z;W-xV{{RuZKkjM#X+clYq{_uBacsHN+&sl{UTl=|g#*3BOvcOb(}JrXse88+5e=*y zG#SUM?wUStbGJt_NlVRNl$;b&&aoW_P9xH-@6z9>T#eMsw}xeWJ2KGMXUvIuya};9 zG4RY@J1*HMYbmOtMy;TpKXO=Gc-ngl4hRvvZD$WGILnslxDfj!uR$9_t?Po@sa7dk zc=5#68}_x?u0@ySin!fZ)KrBfUBc2rlc$1^p@=x7gCY+_U#3F!7uHWzeItjfo{{In z60;0*Lz=SIDy3?$dhi8>FovC)N-0I!CU4vt5>yLqmX zQmh?G!D-nz;UJtkvdpeCHaqrGpilx{Wg!~cU-XkG@iL)`PSlW6W(*XMQ5mn+Eq-mt zeKzX$8-onFQ(0e*R^k*McbgaTYDSutFtWmc8S0)j-Ftuzn({g+TS00`LcE^M z#7^2Iytwa@8+|KEiiUuopB6Z)!jZ6Wqm$8|uk@?Zf2GIj2Uqhh8G}iN;24H2ELD}T z$5AC-D>IlPNEy7=l1O1tiWc@D+T6u*0F%{ODQ55FtjYc^?CBg- zrI-MFr=yK&IqHWx$%ti~A2IyEXlXF~!I`QXc`CItqs0INzV9-Bq*(ZKBlnNQTM0UZ z6C;kyeP|K8NbZoN5eHHck5(t)K)>MWlxAG#HfgJX$gxK=8Kf_|HjX=sEv{NukOE2U zEI2FOyIm*_@g+mh0f)Ad?~UOu7D2!S;nGxbpFu~ntuelH&p7ok#j!XryhR@^<}r4MZj`>k zeP8iDT%|ODFqa;Nl(WMfK_YSJ*iC0IWw~j(v_r{Ehcgz6lujy26kJL`+F&H9Ltqm- zMO-hd%)uT#oayR6a;my%ZS6?KkbEux=Qytqc=%8BL|0#OwQDL@PCoi0eM+sSq{tPL zL9Ft)544>TMg80R3HE+`5wd%*Rs9tFaHSWnX-}DouHLI;k&g7&8NsPnWZ2j8?7b1S zlpIc_7N8Pt2Izxs<5ukcVW)q-(9oWj76J9r4OMSgjp*Ez`wdk;A7SLB^<4(0(3quD@g1j=4zr93NtjdulZD5~ko;v>^Wg z9XLUgqe)u2fcMP@^W{TGNaCV>(OWqF2U#X;Tha@V`1%C`jm0_QHP}ra+xfPe3Q-^Q-jrPnhAtIvtwpDq|8O(mYPANLKS#%Ty#0 zU`ucxey-x#NBhz}xKY+@;V2++BB)O{*5~Y3rdU-CT491AEI{ok3}NXO@guQs(rjH+ zcKW#j0^*W2#+c#KHUsHF1^@>M*;P~O;KN+j z2i>x)7p9q!t3R$dyt7{ws;+73TmvibKK;lyE-rn#^M`FEO|x&P9V$XdoF++9qtxxL zf;x~Cpg0)$3aOvQ?*+|yH`4|eioP)&Mj4D_lvr}p65lf|OeO1TC7L8%vBm|0>Tjny zUD-BJ8f@5ynXwq~y7sq-@_zcBU zM@u9$@Z{`!68Vx8M)g>&Z_39BMzeXWuecH5EPL}WYy*tA^4pQAY6Rh?2800{WQjVu zqM$6uCHFKhWPvd85_mrrwiaA~|Vbj;kJ!C}s!|7UN<23VVUu?&L4LZigLVClRcu z{=UjR$`Ea>t{qko*h+nA&+&7^Pf&5pm62+(Ik1c-gA2xSn)%>_Ou^nnrlgF--*3*4 zG5`TL@V5>unHM2aNJ>*BKui;W5w{bD6vpbKKwFWCDM0s=?At{T&}Ju|CG{(lx;vjT zK>UtVz-lW78G!jUl5(yK0%aDIaQ&N&f&AFpacjKN4K|^Ky0b6R(6tO@(Eg3kbt%5uQ|Py4n20 z5zySKvDEmVXCO_)w=UgTgpIBhku_z3r%{T(Ut@&F+c$~w|jVVrTLR(^mk+U&YhFA8N*@2fx@v> z+`#2cF5m!40Dy23R0cd?Oqi>f^u?8MI$y;X(MJb|9MBuLvBVN=b9W^Z!F-dG4L1zJ-e zZ6FX1Fh($XYQ(=1o}~J7qV*M%aF0<`_)Sh1O-G30lr-3kB2v|G$Rh%tEpIN%6k8Hb zplQr#$<=V+xLuMK7NsS*NbrPgg>(Z_?&m7qmI=Dk1yVI}DI7ef8rSpF?^rW$s{a7Q zrylhN*nTUE;aCnH1r{9~VQQhmDdbp^nly}gXiD#50I|Nh-t+4S*d&QEe zP)JjSIQWjp!_ZLMF}YRKF1Uh6ganwx3BwO5t&V*?`se8X0IKiA=cl-y5rbnHYJ(x+ z6XVr)qIIf0wp+IM`~T;469$}eq-)Rl#RhSW-=jiyem z2?hY6CP<`R+udlvWsnjT0(B^Ko`FalPbBqAsh^B45!S53lQFzME7Ruu$BRXb*3h(6 zveIGrb3;t&Av?A;gDuo(Z^1razxg|vJ>pYz(Rue4;cia9+PVkCfsO{Xn z#JtccI#aap5ITJJP%-$S=4dH;>(aU@>M&NR!@6ym@j6O8Vn09UD=V=VjtKDd()Dbl zyliv;7O}R38;z4(Ut1xT(DBywwzA#Nf>+T zhjT|lq0OCPz_JbnQ63AI@T@kJ*VIW?C2>nzDD&Qq>}8f|mw8yt$Z>AObFDkazBap} zi+|1sCC~yxX)YXbQp|m+;~Pf6D;Tnzh5Y=x+!XjpB&g^TKGX@?cuvZ?4^!F01dGts z9s|(Is4HTwTq7=E(tlSegmOnca>RFjkUcXP)b2JL9{q{Xu{SN|EeBhbB|=jzfJl@4 zUvNH^6{gvCS7i?kDnTVfRKWwQ1M{aZ#3q`*Cwf4^dT_KDp@3Flw2F{ncwDHh3{36* zM|D75!0l_2doefRYljKGD$L9{e+qL8ZE83?zJCw853+TEs=0VEd=*^}W+{{Wgc zb16JxvXHm#Mu&$$1YgWorDtUy9&)JmK~6)0`@(8i~?HnPT$< zJDxu?+#s8(_V)1Sd6-SbyG;YOB>GV%?>LlPI_cYpi5n<)%NQ@?5%{}iI4YyYD{u^l zgjP#MLk&u`1`ACpx18`{_8yDLr_p zNkBMaqA7Z_56U=74~YK&M-v@q5C=yRYir-bbI|WsKMrh@i2nduI==l)sLg^2D)2!? zYI;f02>Gyn+P=^uYgiBlgz6z{{m!(`E>xu_y22%~6OI~+uvAZn0z{l?UDjgl$OU8* z)=40B@E(+Wu@0r?x5BINs@y*do*YFPB{dY0vZPE1WKS@VK_B7=U%P_5yR(eC)MApk z{*VOuY{Gca6zZ9SJzG4wC^VO=nV&8*H3mJ0-~q3HBBBaau>p4Nh@vWh1*`xZm|MuL z(f|k;Uh*<7Zi_%*6*GS2~E<2Quxj1wgKIx$Y zcJLx7HN-y<{{X|w1KM#ev*pxu`zAW}a-n;V(W`xYbq%!cDNsJ&!j|buMkEh1DlQ-R zw)z0ewT)eu`u#;iD+6OoQCOPZ*7qW{z8*aCtPuExBrDNhfTckU?NLXxP>Yp+6kIFR zpH@15&@V{ca(u^*WBA0i7~|7O&m|TIh0?ukagI8eLbSC^BY_&sR5Oq?xC>rns7leL zBn?uf1ug6EBFg^#jiG%#ngt+qT=8{kr?Q&Hi4qnA>-E zYGtB9Qp%cBjS!%fl1hSH1P5jS#UwyA%Wl>8*D&4e*2Q)=Dpiw@tuG}BK-ZyZIwd2* zOKSU4WR&_*zQwZd{5VJ92}hgyse&$l%sG!FO*9ROOzk3ON(GXh8nH12)@7AR13-5X z*q(6a)pvW1yr_2F)wYye!q!ThDsNCd+RDm`W+dDg%ro!U|5^vT4f%W?7OyHFjFoxjoTs zC?L!NrKB84=_d%BX-nw8)y87=Iq9#~->x5$pA3^0p~|^a2&M@d$pt)6R7V^r(JB(d z<~Log!^MqAD&Muu-^X4;CAt)dFBQH7P080nn^>6|gFpWQ1}Wm$E~&Yfy2Qnc(6 zodcps1PK67MOEHh>0WKiKAZDiGl1ds809_*k0u>97f(?jSE_meRTPaC_DH}f8<-t$ zZEeZnw;5fwBn5ZGV;Cf+cKPtAbxJMWfOZzJJz-Esu+T@-+}qY{)9Kfw7(PzQm3XBN zcApf$@p)*l`nsBoIMU-u=1P#$4dtMum6<`YJAKj*9M73TZCZ5)Qrl_Ngh(3H+Q~{W z{*X`}v~ibSqTcr5w-gecZLd-LKvE)bJt@bchHq28lzl+{9z8+FJy~Tu{{V^AWc;Dj zTox>&C0=N&ix8-wTF7KI6XCT4{Mt<$yjxVOC`NWohmn`_8$8LiTCUl)-zX=**i1$^ zAH5`|2?Y2~5=fytPwRKWptk%{p`?XIsEEb{12SaK4Y!BXj0Y6V-;AYiMXU1F8ezRh z%h=Qyeqnq()z4FbVtI7WS%r#VRcA~-x*s+c)rXqV1!X+u!`rBHecgBRNprt$`F99P zT`g;Ul3^ig@PsH15&K9`Aws6>to0dX@>J^7P+3X}Qk_HxHV~AJM4#f@-~3Gh zD|HBTfS{zKT0)8fl0a6Hbd%Lsv2T9PV3j(8ve;UXH6ch+icD(KsUaq1Bw$7&qk4D4 zdQ*yeh{^eL)ebFDmog1@ArfQwo*5C6qLzt+Zk-A&j4b;@6;@!Rkfe?k-S@y42`VCB zbac)*^lhbAsc_pZR&res5vWcw0q~NLs7#QOM34lDtL*i8*W9Jk&Y5MOMZSUa9vjr| zl4i(d!7yCkj$whZstRYEJ!S<4AyXVi8WB4Oca}0^U$Vd`BL`8~?pu-P-`jG#mL2_~ z-nVJOE#Gkng}m!POO6ys2}np%fFu)%5aiq4f10xPM|4oNHc$f8-*lpd!9gh0px%`T z)u`YwfrV7-`Z)EI=})gU9X6W}n=WPsny&%#9-1o3T8Jl4E_4jbBr`@^mwK{hvArYB`yt8{{S|XmC<=N zGORBjn5DxhVoZbrO7b$wx3@6LvbOTJ63SakNM%^4sG|g_ddY;SCRQ|{CPV>@(d)ag zt1RZ>=Y3dz(kB4Ab_8o~=;IKIn!nkBK z^3mZjZLmf~r-2F%*KI9*a#M6#4cUbyG2?@WNdS8jq#n8mX72Y1NQS9R%ovsI!6%_85rIB0Cl!CZ$j5>(`f*bwS7pXlw0ipb5- z%4~*Smu?bSaDpRINeCDMnEsIQOmX8{^7`b+p0KfQwP&8C^s}hhlNrjmRvAf(%ZO$i zd4?fZ8^`2MR4Zz3D#33GDy_21e|1JC!-UEMAw;% zZ#YZnD^iv~A{7b2DUwP_k&XgD+d=1{%sZzZvFm!L(eGAS+OrA8G0dFRxJ5(78ZB-q zgg7*D7b*ivAanM%?%GLhHAi)yU$=R0V#UAa8oXa~a^b+*wv?47UQfKSn~4;w*@z%6FlKM9-Q#_L;@n}V4UzT@2SSpi z4+@F?=$)PwY#;?0hj(tSoXc&WxI$WS;ohyZf|89`=^&YqASjseP6J>kU0dqUrTn@0 zdh~xiblV50rRy$Ark;xs#NA~~nkeIue#r?cf>eTaBir=zs+n&0-dZ+Fl23{}G9*Xb0rnA4mF7)u zR|z9$9Am0Sx`S$5Q>qJ9K(S$U)U)DpMNdT}@kty~NbVv=4&uc@adJBicqV6l9wv0C z6M)CAC!abhUR26Kk_ZAwA9O^(>oJE(fm>VjAJQ~XW~wfk<{9exx6#a!w6*zL1k4aa z40PDlY6r%#DrSK|o}Nj=#)~5rWH+!P?SWh1NEt9>nk+)2 z=5sa!f>bn8;xy2zJZnp_f`x`fGKdDy&Plsk+=sVahH^C&-n?#7qL@?RDj*(VDidSQzCf9qeU z&r|p|E7rcG<$Nj}UJSd8<25uC(cyIxe6>zJU5Xvm6*cKGyikqPJ%Lb5i+i*@@vYYu zSyiLolQ*v=i+35f?;B}oS9r7*fd~k35{*j1Dp7Egq|%&)yNt}L>2MOCP4VvOr728yCJA~GDZIx$uIH#X$gy4|<2VDj!S zQihxbV?szE2M34}Wa>#I0%Kq?Mmx{haL#Po%h0l>QQVMK_v&IhwMu`*6Vr&Kc1Zj> z`d}svRp~=CpE+2{wK?XMcbj{~9yA0H4~?zD%f8n4O5MK@eDJ}-W6lL>-NxQaf=X`f z(TsvvB#%E9HLx#6J#BiQ>8Gb?y){<)bej^(6qI8Rik7E4QXr2GODLxe9Wile#fxtC z`*Blh6q-T#ulGHW@8_>fz>TDFrBtf_AysEkeH@Viw#BxsE{O!Ky z{F=(~30g*yKySh}5El9sjNo*^7=u9U`zL+JWBG<4X(7KB&4W^#DGD1lk~o1y-!y(4 zogDOEieVjW%e^R@BT?XV`IdUfF%F>N`1TX#j3RSQ6!eSwNSG=JINas7?W(|3I9uPn6U8vrq@UJ)JM znMzVsue`v>DaK@-^baaw9WM0~(H@lIxa~dxmZ>^HTZv|hI>R#I_^g?NzLh4Tt)@_8 zmF1RepqVz_Fip0D%4P_0HfQqSmjVev#!CDtK{3*()J_0N;3_W7?^{Kq&t0gY1%I?! zF;i&7txe&Af^h{g2dahd$4AngAEXadJvHk;;r@dmXG+w=Fp9b?wJl6yu@AhpB06OV zl#NRP`N)acBqMY7H;Vf|e*1Y?xXbsSFKG+3xVJ5pDBN2-?v*&3i*EU}sU6yc6p%}5 zF(8!+A6QseWLmBA+m*Q5o77OJH5RoErOic3Hz0+XFjSJHj~SpprkKVllD$cE>(%c= zaqsG7A6RO-u(%Enghfjkz#&{7M~(wY3JP=);}rE1Qv$3R95DfjzFX(H=kjd5$E;W0 zDPivm$pk4W8p2j4VGqpdF^WMX6(+I+vQ67}cypU^nOYHV-ggPOTm)P?8&w{mETC7w=?!P*UX=ebssWfl3 zk)~atT&I&KWwI(Tgp-b!9jGSsOcYR+5iAX6f?|SQ=|g2 zAf{spg=xeMlNgPd(*FSQ#KCa9AJ)B2SHO3}6>eR?D-+3mkVeR7hDyJeC&}NZ+uOJu zN!OTZ^xK;}=1p+Zs#=O~9!OG&kTjry;@~lX!-XW?mVmk{7)n!s+578V97C&_-v_Op zhMyCujcFx#_e2p1AeFe1-Ti#SNaFx}}O@x#MnTuB@(P zibAxq0`bZ$cWzRB(!KAe({2bdY{Y(LDO{4Ur0l?wFrJEzx1Aw&YAF5^l6qomVhqvO zIeJ~uEKjLzgFy5cejP)IM;vr<#q*+?5YCbn05dd&PUh`v*pbK<DN1mO(%_T4$Px5n5$t6ur9<=buO;1_1yvUY9 z;h9u`tVX2WyKxIU(|BAU+Meht5UDzppXo$ECvUrLA1g0u2#)Y-;y44uQAWw#M8mSh zdelu0AybJ_lqj_F`>~kb%2|op$)=XRjoRRHa!>?$(F+d*;AEOKzNWoHDP~ z8`Ey%_Ad7%rD;x}QegN@$Ed0>;VSV_?)*=BZk;^!j+FTe52V4e_GH7U+sUSaGXmE@ zrYePsBBd6@1EKDGPP{JNwXIomDs+;v2_)^>Vo#Mg%8QFvMB&$k8IQvo@qr$T@H($b zzN;k0@r<=WRU748LWUzzRfU>{{XQK~vdEU9WFV}UYw=B|^!L?%vtwOj^w)*sxHe`Od(>y_ z2N1!H5t5#n)!@t+L#w=1HI#e&{i*&^11j935y^{j*}2N?RhQ;ES8lVUl$}JTNrIEJ zyCkUx0|iLfXp1nox42S}pmex2xRN%c{{RsF_-zDZ*H&lvIr`hG^&^APbZ@D(vA%H1 z^b%4#g2U(NBHGlo0I|G<5U$n--ieg`rEYVJ>JN37lv=E4)Rx=@4q$a8h$comARZ+p zDmx~n?ZeO1^KNB#N+tVfEv-gP#ks*Q1I1`Q2L{=NAGpz}_2{^^AD;5JQt4p=8VWh- zrjWMRS!ruvtA@#a&Nhd+0Ncjg#~#TaE6DDU4#yI`F^Et?gyXbe2gZXPqucjR+FSwl zxdik~Z9dwvEWtxdnsBV!HWwhCrifDG2~ST-;fl`+k|baX%A|YSmr>)$tF^YjGD^}x zA=Is4Azl=^*wmt}h6tToBLi7OcHu)7&Jc8{DX^ljLDHiTHm9NwrB{zka^F|+k6W0Y zBhvgPmk@&(!lHtzp0Z;VJxXo4&30D!&L<7eIhQp0m*FrHKxZ>Rc>V^^5d_Ek%nDA=a zEJkcPmD*?#00V3fC%-gL8hfs7cD{g%aAT9%w%${E#jB1Mtrcf*66nz4id|bSC1^3F zNe+c+*fgi48X|4PCo;5fLW7#os2LcH4gf)&q5<25S8uB$kEc%Rv)nbqkYb!#PIwKW)Y6?mOIv86OMW}ch< z9qHzUnqf4m0t@a9?%Q4qJ0oVdN%G+-QVpI|#Fnm#1 zjhNeu^*~FFkYZMu1~wgFlkw`HAMn?q^@EuDf0pTbms>pqxP2+6k}Oh@WR)3hus@k+ z7fTR)dma~dvz%Di+`iL(Jwy?t$d0YMHbrJ`kEC?ZojLl3^as>x zUtDqe$<7o9su^N>YD_w820FjxwRCEbx)V)M8B@tJHu4F*$-Tz}{g3vOm7>+WlIgI~ z3vp^CMJaz?5LNsu0x>v1!lHfn%AU<0{N=VGC`v*$sjvx>C+-R+R5r;tMFHQ9S4Rg` zX|lF{%lTc-E;4IZC;D_>H%T5JBCS;^g8u;NJ7Ho;OPww>=R)@!DK5I(LJ|^!6FQ+N zDn^_(zzHDZBN~qPnLYMhYT*Q_DtWosKp_hr9ui8v6;xk^-%~n4lPa;iy^5rgW<1p- zbnsHj!a8cPwE0xaQ6+*%TkMv%y=xorlYTOL+|x9(bOb4eRup8x7~)S++3cDa?k;y_ zmSp#=sHi^jNJs*8ct}V|=@TS-D%Wk{K0lN4&y>YFJ&i`vqDV{_l$HdY0V^RV$5W~A#X1M{54MY( zJ#>CQ4m#=@e7T;weSl@mUn)!H(c%$3TZiB8+;S|>_kE1Y<%_ii zCEIZ4cA!YXz!IdYKI9NS)5jY1vxTLD)+V*A{8>71G8e9V`-at1(Rr1V)77)n#$=LX zJWDC4l12nEa@%wrmc(2VW!#N`ZNijEB}%~m01nI(hug#qaVHwyY~t9sQU(|UhQm0| zpG^y&g?4!UUDQepytNWizCVX%T)R-vp;GafW5p5l|<*X@tLNpzpatTg8kw$y{VywG0eJPI;g80NJ z0%QE(sWeLQV?3^JbXL89jzt?!ay)JA2a|&-)5zOU1;OVUNJ^4g^C2Vx28;kd8x2AI zdvNVNR1SNtnI=;ssUgTV)JDKq4MFyB#UOz})u|JNDG;;w`{dS7t5N zq@gemna9-rlrrACm0q-ktw4|?00tZ;2kTY?_-No*Hf`%pCz-K&Gm1x-FnOw}{N!M; z)U<(8RJx7Mg5+!LJ@~6WTAH^B*(*prVD!)vbS%*Q+Loa@5L73ErUCP-;Qnz(hs`3( zQM#WP!`LC17xL<%{UmZF^}CH25^u~)%)*qv4B)Bs<5`Z*DIQc+>MC)Jy`F1nW;dmk zW2mMo4zbT-sOP`v-*Vr>OWNFZE^0`RDkgC-qdt|B63q2Ee;lUHP!=msG77}nSeQ## zuv2hZ8&zv+Ey9DU>Q=`lkSx+SV?k@ybLp+$q9~@CS$k=3;^J>I!5?&HK!y1sg$|&K^ z=jO=B_ki8zB&Dmb**LcQwCXFK?6{W_TTDBqP6;wdDb-jv+V<{eCnx;ALZ-XKJe8$4 z2t&znoO{F+xI#O`m{JOe3IL5sCTNO!fApK^@6>)x&)644^VT(wX6yp8I_x5nq}0&U zW*jZ$4-_>t(*!X~ELVl+Q+TQZO}EP>d70bMzLxux=^2|Z7F-a^&9>Awv|yyZf~66y zJ|q+s=#4P35rPBzVEw~)D;aYMRlbEcr(MHuK|++ov%_K2OCT|o}%Dv=^5 zGs<4kcFW}2DFI>f+iKDk0VQP-DL8_(At5IPKm|rWOWWUTmv;-Yu~B8zDao~E#6H@R zprtix%b*pu;7q)b+SJP6H?0H|e^>ti3?EV+pYf-p$@r#a$Fa(M#T-~-Q!P@`J|Rgs zsHPab1g+-579kReA*%t_ITl2fZMBR>_Vrt^^USG8?vhjj(vk~+;1<|1;sYM-Sg3uZ z?Wx(V;JkcWW?ztPB&SW#SkrdOV@OjgDAcylL@9-othA)*f(Wh3Jw4|N>_UQ)w-u*+ zKM+qFe+eoQ({s}i;WM%w>fXV?EY5q4>n{fAn-G`dN$WbGPgfBY$u9A zjv_>gqc8YV&qw8ebfeV{8AN89NGtNiOo*oO%Nq~*~KH94cqnzIy$yiour&TRg zO&0qGBow}cZMeA9n~iU#yb14Bxyx@N?sg zWvZu1QtwJz)1DJ|%uW*ln+&KQMdURkM(%#f8xngX6(S@b zBhfHxT;E!m8S-bUOluIrX~Z-+swzywOd?IIzO^=0EJ_B^vaKDhZ3}kSnd`WB{{WuK z8%oJ4V5x;p*g=#McH-Gco~q|A_T_)cvp1LRRt^VKSznhR zmJQI$0V*U-z^bzCwZ)CEpucm$wc<3AI2>vmw=k?Qp^k#P7RIp1X3P>)R+>0ck}sGt zNa+lB0y56Ul@jM*Q(!bu0OVHa4V@_falim1`3T34N!wD}1g$cxcw<|-{{X^$I_xud zrg-ulbfxOD?M#%VSd!Z>xi4@u+I0AHoxP%E#kJiql>Nakr>Zu_-MGyktoWL9rdvNR zeQc2$?p6oh2H@$;5o%NB>b(ILce`m7eH(MqM2Y-4X|_Ji&4BbjHH-?y4F9&gBw zDNx!E%A-fwEGVSbWSZ-JT#;fmKdty@jUhE9Y73~4mJM-xUc_5Zql=qS+es9f&Xp0% zADRZ%*TYMApO43fjkzL_tr*i`W=WN#T}{_Pr^CMt(x{|r70gx0fUJW3#-Qpx9})NP z(YIjHa?v#%YQ%+#1|X0;Z*SMbhfTROUZllKNv3G`#c(b_8*~Hd@!^nFCn@Quvr8wJ zy-t#h%xAh87^YQaPEZ$FT*4F#GcDL(pBJPiO-Eh@Dk@(b!-zqOJFaOzC ClaN&a literal 0 HcmV?d00001 From 84256b61800db5b01b7414ee89e9e5b94784543b Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 5 Jun 2019 00:00:18 +1000 Subject: [PATCH 215/223] Improve robustness of huffman decoder. --- Directory.Build.props | 5 +- .../Components/Decoder/HuffmanScanBuffer.cs | 77 ++++++++++--------- .../Components/Decoder/HuffmanScanDecoder.cs | 24 ++++-- .../Formats/Jpg/JpegDecoderTests.Images.cs | 4 + 4 files changed, 67 insertions(+), 43 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 6e3cc9b3b..bf004921e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -27,9 +27,12 @@ true false true - true + + true + + false diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs index 72bfa3864..dd5160414 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System.Runtime.CompilerServices; @@ -19,8 +19,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder // The number of valid bits left to read in the buffer. private int remain; - // Whether there is more data to pull from the stream for the current mcu. - private bool noMore; + // Whether there is no more good data to pull from the stream for the current mcu. + private bool badData; public HuffmanScanBuffer(DoubleBufferedStreamReader stream) { @@ -30,29 +30,29 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.Marker = JpegConstants.Markers.XFF; this.MarkerPosition = 0; this.BadMarker = false; - this.noMore = false; - this.Eof = false; + this.badData = false; + this.NoData = false; } ///

- /// Gets or sets the current, if any, marker in the input stream. + /// Gets the current, if any, marker in the input stream. /// - public byte Marker { get; set; } + public byte Marker { get; private set; } /// - /// Gets or sets the opening position of an identified marker. + /// Gets the opening position of an identified marker. /// - public long MarkerPosition { get; set; } + public long MarkerPosition { get; private set; } /// - /// Gets or sets a value indicating whether we have a bad marker, I.E. One that is not between RST0 and RST7 + /// Gets a value indicating whether a bad marker has been detected, I.E. One that is not between RST0 and RST7 /// - public bool BadMarker { get; set; } + public bool BadMarker { get; private set; } /// - /// Gets or sets a value indicating whether we have prematurely reached the end of the file. + /// Gets a value indicating whether to continue reading the input stream. /// - public bool Eof { get; set; } + public bool NoData { get; private set; } [MethodImpl(InliningOptions.ShortMethod)] public void CheckBits() @@ -71,8 +71,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.Marker = JpegConstants.Markers.XFF; this.MarkerPosition = 0; this.BadMarker = false; - this.noMore = false; - this.Eof = false; + this.badData = false; + this.NoData = false; } [MethodImpl(InliningOptions.ShortMethod)] @@ -141,39 +141,28 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder ulong temp = 0; for (int i = 0; i < 6; i++) { - int b = this.noMore ? 0 : this.stream.ReadByte(); - - if (b == -1) - { - // We've encountered the end of the file stream which means there's no EOI marker in the image - // or the SOS marker has the wrong dimensions set. - this.Eof = true; - b = 0; - } + int b = this.ReadStream(); // Found a marker. if (b == JpegConstants.Markers.XFF) { - this.MarkerPosition = this.stream.Position - 1; - int c = this.stream.ReadByte(); + int c = this.ReadStream(); while (c == JpegConstants.Markers.XFF) { - c = this.stream.ReadByte(); - - if (c == -1) - { - this.Eof = true; - c = 0; - break; - } + // Loop here to discard any padding FF's on terminating marker, + // so that we can save a valid marker value. + c = this.ReadStream(); } + // We accept multiple FF's followed by a 0 as meaning a single FF data byte. + // This data pattern is not valid according to the standard. if (c != 0) { this.Marker = (byte)c; - this.noMore = true; + this.badData = true; if (!this.HasRestart()) { + this.MarkerPosition = this.stream.Position - 2; this.BadMarker = true; } } @@ -184,5 +173,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder return temp; } + + [MethodImpl(InliningOptions.ShortMethod)] + private int ReadStream() + { + int value = this.badData ? 0 : this.stream.ReadByte(); + if (value == -1) + { + // We've encountered the end of the file stream which means there's no EOI marker + // in the image or the SOS marker has the wrong dimensions set. + this.badData = true; + this.NoData = true; + value = 0; + } + + return value; + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs index 76fea9297..c28733250 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -130,6 +130,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder int mcu = 0; int mcusPerColumn = this.frame.McusPerColumn; int mcusPerLine = this.frame.McusPerLine; + ref HuffmanScanBuffer buffer = ref this.scanBuffer; // Pre-derive the huffman table to avoid in-loop checks. for (int i = 0; i < this.componentsLength; i++) @@ -171,6 +172,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (int x = 0; x < h; x++) { + if (buffer.NoData) + { + return; + } + int blockCol = (mcuCol * h) + x; this.DecodeBlockBaseline( @@ -193,6 +199,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder private unsafe void ParseBaselineDataNonInterleaved() { JpegComponent component = this.components[this.frame.ComponentOrder[0]]; + ref HuffmanScanBuffer buffer = ref this.scanBuffer; int w = component.WidthInBlocks; int h = component.HeightInBlocks; @@ -210,6 +217,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (int i = 0; i < w; i++) { + if (buffer.NoData) + { + return; + } + this.DecodeBlockBaseline( component, ref Unsafe.Add(ref blockRef, i), @@ -294,6 +306,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder int mcu = 0; int mcusPerColumn = this.frame.McusPerColumn; int mcusPerLine = this.frame.McusPerLine; + ref HuffmanScanBuffer buffer = ref this.scanBuffer; // Pre-derive the huffman table to avoid in-loop checks. for (int k = 0; k < this.componentsLength; k++) @@ -316,7 +329,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder int order = this.frame.ComponentOrder[k]; JpegComponent component = this.components[order]; ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId]; - ref HuffmanScanBuffer buffer = ref this.scanBuffer; int h = component.HorizontalSamplingFactor; int v = component.VerticalSamplingFactor; @@ -331,7 +343,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (int x = 0; x < h; x++) { - if (buffer.Eof) + if (buffer.NoData) { return; } @@ -375,7 +387,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (int i = 0; i < w; i++) { - if (buffer.Eof) + if (buffer.NoData) { return; } @@ -404,7 +416,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder for (int i = 0; i < w; i++) { - if (buffer.Eof) + if (buffer.NoData) { return; } @@ -691,4 +703,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder return false; } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index d428000ef..56496fad1 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -17,6 +17,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg // BUG: The following image has a high difference compared to the expected output: // TestImages.Jpeg.Baseline.Jpeg420Small, + + // BUG: While we can decode this image we do not return the same output as libjpeg + // based decoders and are inserting a number of lines equal to the corrupted lines + // below said lines. // TestImages.Jpeg.Issues.Fuzz.AccessViolationException922, TestImages.Jpeg.Baseline.Jpeg444, From b6883c1a978f67eeaecf6c6dfd7bec952232ceb7 Mon Sep 17 00:00:00 2001 From: tonygameplan <50851017+tonygameplan@users.noreply.github.com> Date: Tue, 4 Jun 2019 23:44:52 -0700 Subject: [PATCH 216/223] Fix missing "using PixelFormats" line in Readme example (#921) * Fix missing PixelFormats line in first API example "" does not appear to be defined without the "using SixLabors.ImageSharp.PixelFormats;" line and causes a "The type or namespace name 'Rgba32' could not be found (are you missing a using directive or an assembly reference?) (CS0246)" error to occur. * Remove stray newline --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 515fc7196..a5c3457fa 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ On platforms supporting netstandard 1.3+ ```csharp using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.PixelFormats; // Image.Load(string path) is a shortcut for our default type. // Other pixel formats use Image.Load(string path)) From 6fcfe09c388de30459b22f402e649d72745958c6 Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Mon, 10 Jun 2019 08:24:54 +0200 Subject: [PATCH 217/223] Feature: Bitmap RLE undefined pixel handling (#927) * Add bitmap decoder option, how to treat skipped pixels for RLE * Refactored bitmap tests into smaller tests, instead of just one test which goes through all bitmap files * Add another adobe v3 header bitmap testcase * Using the constant from BmpConstants to Identify bitmaps * Bitmap decoder now can handle oversized palette's * Add test for invalid palette size * Renamed RleUndefinedPixelHandling to RleSkippedPixelHandling * Explicitly using SystemDrawingReferenceDecoder in some BitmapDecoder tests * Add test cases for unsupported bitmaps * Comparing RLE test images to reference decoder only on windows * Add test case for decoding winv4 fast path * Add another 8 Bit RLE test with magick reference decoder * Optimize RLE skipped pixel handling * Refactor RLE decoding to eliminate code duplication * Using MagickReferenceDecoder for the 8-Bit RLE test --- src/ImageSharp/Formats/Bmp/BmpDecoder.cs | 7 +- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 240 ++++++++++++++---- src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs | 9 + .../Formats/Bmp/BmpImageFormatDetector.cs | 6 +- .../Formats/Bmp/IBmpDecoderOptions.cs | 5 +- .../Formats/Bmp/RleSkippedPixelHandling.cs | 26 ++ tests/ImageSharp.Tests/FileTestBase.cs | 2 +- .../Formats/Bmp/BmpDecoderTests.cs | 226 ++++++++++++++++- .../JpegProfilingBenchmarks.cs | 2 +- tests/ImageSharp.Tests/TestImages.cs | 57 +++-- tests/Images/Input/Bmp/invalidPaletteSize.bmp | Bin 0 -> 9270 bytes tests/Images/Input/Bmp/pal4rlecut.bmp | Bin 0 -> 3610 bytes tests/Images/Input/Bmp/pal4rletrns.bmp | Bin 0 -> 4326 bytes tests/Images/Input/Bmp/pal8oversizepal.bmp | Bin 0 -> 9446 bytes tests/Images/Input/Bmp/pal8rlecut.bmp | Bin 0 -> 7980 bytes tests/Images/Input/Bmp/pal8rletrns.bmp | Bin 0 -> 9212 bytes tests/Images/Input/Bmp/rgb24jpeg.bmp | Bin 0 -> 2457 bytes tests/Images/Input/Bmp/rgb24largepal.bmp | Bin 0 -> 25830 bytes tests/Images/Input/Bmp/rgb24png.bmp | Bin 0 -> 1210 bytes tests/Images/Input/Bmp/rgb32h52.bmp | Bin 0 -> 32578 bytes tests/Images/Input/Bmp/rgba32v4.bmp | Bin 0 -> 32634 bytes tests/Images/Input/Bmp/rle4-delta-320x240.bmp | Bin 0 -> 3686 bytes tests/Images/Input/Bmp/rle8-blank-160x120.bmp | Bin 0 -> 1080 bytes tests/Images/Input/Bmp/rle8-delta-320x240.bmp | Bin 0 -> 4646 bytes 24 files changed, 495 insertions(+), 85 deletions(-) create mode 100644 src/ImageSharp/Formats/Bmp/RleSkippedPixelHandling.cs create mode 100644 tests/Images/Input/Bmp/invalidPaletteSize.bmp create mode 100644 tests/Images/Input/Bmp/pal4rlecut.bmp create mode 100644 tests/Images/Input/Bmp/pal4rletrns.bmp create mode 100644 tests/Images/Input/Bmp/pal8oversizepal.bmp create mode 100644 tests/Images/Input/Bmp/pal8rlecut.bmp create mode 100644 tests/Images/Input/Bmp/pal8rletrns.bmp create mode 100644 tests/Images/Input/Bmp/rgb24jpeg.bmp create mode 100644 tests/Images/Input/Bmp/rgb24largepal.bmp create mode 100644 tests/Images/Input/Bmp/rgb24png.bmp create mode 100644 tests/Images/Input/Bmp/rgb32h52.bmp create mode 100644 tests/Images/Input/Bmp/rgba32v4.bmp create mode 100644 tests/Images/Input/Bmp/rle4-delta-320x240.bmp create mode 100644 tests/Images/Input/Bmp/rle8-blank-160x120.bmp create mode 100644 tests/Images/Input/Bmp/rle8-delta-320x240.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs index ebb7ffdf3..a404ab418 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs @@ -14,13 +14,18 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// JPG /// PNG - /// RLE4 + /// Some OS/2 specific subtypes like: Bitmap Array, Color Icon, Color Pointer, Icon, Pointer. /// /// Formats will be supported in a later releases. We advise always /// to use only 24 Bit Windows bitmaps. /// public sealed class BmpDecoder : IImageDecoder, IBmpDecoderOptions, IImageInfoDetector { + /// + /// Gets or sets a value indicating how to deal with skipped pixels, which can occur during decoding run length encoded bitmaps. + /// + public RleSkippedPixelHandling RleSkippedPixelHandling { get; set; } = RleSkippedPixelHandling.Black; + /// public Image Decode(Configuration configuration, Stream stream) where TPixel : struct, IPixel diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 0cbc4fca1..294b49ed7 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp private ImageMetadata metadata; /// - /// The bmp specific metadata. + /// The bitmap specific metadata. /// private BmpMetadata bmpMetadata; @@ -83,10 +83,21 @@ namespace SixLabors.ImageSharp.Formats.Bmp ///

private BmpInfoHeader infoHeader; + /// + /// The global configuration. + /// private readonly Configuration configuration; + /// + /// Used for allocating memory during processing operations. + /// private readonly MemoryAllocator memoryAllocator; + /// + /// The bitmap decoder options. + /// + private readonly IBmpDecoderOptions options; + /// /// Initializes a new instance of the class. /// @@ -96,6 +107,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp { this.configuration = configuration; this.memoryAllocator = configuration.MemoryAllocator; + this.options = options; } /// @@ -207,7 +219,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The image width. /// The pixel component count. /// - /// The . + /// The padding. /// private static int CalculatePadding(int width, int componentCount) { @@ -222,7 +234,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - /// Decodes a bitmap containing BITFIELDS Compression type. For each color channel, there will be bitmask + /// Decodes a bitmap containing the BITFIELDS Compression type. For each color channel, there will be a bitmask /// which will be used to determine which bits belong to that channel. /// /// The pixel format. @@ -258,8 +270,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Looks up color values and builds the image from de-compressed RLE8 or RLE4 data. - /// Compressed RLE8 stream is uncompressed by - /// Compressed RLE4 stream is uncompressed by + /// Compressed RLE8 stream is uncompressed by + /// Compressed RLE4 stream is uncompressed by /// /// The pixel format. /// The compression type. Either RLE4 or RLE8. @@ -273,14 +285,17 @@ namespace SixLabors.ImageSharp.Formats.Bmp { TPixel color = default; using (Buffer2D buffer = this.memoryAllocator.Allocate2D(width, height, AllocationOptions.Clean)) + using (Buffer2D undefinedPixels = this.memoryAllocator.Allocate2D(width, height, AllocationOptions.Clean)) + using (IMemoryOwner rowsWithUndefinedPixels = this.memoryAllocator.Allocate(height, AllocationOptions.Clean)) { + Span rowsWithUndefinedPixelsSpan = rowsWithUndefinedPixels.Memory.Span; if (compression == BmpCompression.RLE8) { - this.UncompressRle8(width, buffer.GetSpan()); + this.UncompressRle8(width, buffer.GetSpan(), undefinedPixels.GetSpan(), rowsWithUndefinedPixelsSpan); } else { - this.UncompressRle4(width, buffer.GetSpan()); + this.UncompressRle4(width, buffer.GetSpan(), undefinedPixels.GetSpan(), rowsWithUndefinedPixelsSpan); } for (int y = 0; y < height; y++) @@ -289,10 +304,46 @@ namespace SixLabors.ImageSharp.Formats.Bmp Span bufferRow = buffer.GetRowSpan(y); Span pixelRow = pixels.GetRowSpan(newY); - for (int x = 0; x < width; x++) + bool rowHasUndefinedPixels = rowsWithUndefinedPixelsSpan[y]; + if (rowHasUndefinedPixels) { - color.FromBgr24(Unsafe.As(ref colors[bufferRow[x] * 4])); - pixelRow[x] = color; + // Slow path with undefined pixels. + for (int x = 0; x < width; x++) + { + byte colorIdx = bufferRow[x]; + if (undefinedPixels[x, y]) + { + switch (this.options.RleSkippedPixelHandling) + { + case RleSkippedPixelHandling.FirstColorOfPalette: + color.FromBgr24(Unsafe.As(ref colors[colorIdx * 4])); + break; + case RleSkippedPixelHandling.Transparent: + color.FromVector4(Vector4.Zero); + break; + + // Default handling for skipped pixels is black (which is what System.Drawing is also doing). + default: + color.FromVector4(new Vector4(0.0f, 0.0f, 0.0f, 1.0f)); + break; + } + } + else + { + color.FromBgr24(Unsafe.As(ref colors[colorIdx * 4])); + } + + pixelRow[x] = color; + } + } + else + { + // Fast path without any undefined pixels. + for (int x = 0; x < width; x++) + { + color.FromBgr24(Unsafe.As(ref colors[bufferRow[x] * 4])); + pixelRow[x] = color; + } } } } @@ -308,7 +359,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// The width of the bitmap. /// Buffer for uncompressed data. - private void UncompressRle4(int w, Span buffer) + /// Keeps track over skipped and therefore undefined pixels. + /// Keeps track of rows, which have undefined pixels. + private void UncompressRle4(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels) { #if NETCOREAPP2_1 Span cmd = stackalloc byte[2]; @@ -329,21 +382,20 @@ namespace SixLabors.ImageSharp.Formats.Bmp switch (cmd[1]) { case RleEndOfBitmap: + int skipEoB = buffer.Length - count; + RleSkipEndOfBitmap(count, w, skipEoB, undefinedPixels, rowsWithUndefinedPixels); + return; case RleEndOfLine: - int extra = count % w; - if (extra > 0) - { - count += w - extra; - } + count += RleSkipEndOfLine(count, w, undefinedPixels, rowsWithUndefinedPixels); break; case RleDelta: int dx = this.stream.ReadByte(); int dy = this.stream.ReadByte(); - count += (w * dy) + dx; + count += RleSkipDelta(count, w, dx, dy, undefinedPixels, rowsWithUndefinedPixels); break; @@ -374,7 +426,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp } } - // Absolute mode data is aligned to two-byte word-boundary + // Absolute mode data is aligned to two-byte word-boundary. int padding = bytesToRead & 1; this.stream.Skip(padding); @@ -418,7 +470,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// The width of the bitmap. /// Buffer for uncompressed data. - private void UncompressRle8(int w, Span buffer) + /// Keeps track of skipped and therefore undefined pixels. + /// Keeps track of rows, which have undefined pixels. + private void UncompressRle8(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels) { #if NETCOREAPP2_1 Span cmd = stackalloc byte[2]; @@ -439,27 +493,26 @@ namespace SixLabors.ImageSharp.Formats.Bmp switch (cmd[1]) { case RleEndOfBitmap: + int skipEoB = buffer.Length - count; + RleSkipEndOfBitmap(count, w, skipEoB, undefinedPixels, rowsWithUndefinedPixels); + return; case RleEndOfLine: - int extra = count % w; - if (extra > 0) - { - count += w - extra; - } + count += RleSkipEndOfLine(count, w, undefinedPixels, rowsWithUndefinedPixels); break; case RleDelta: int dx = this.stream.ReadByte(); int dy = this.stream.ReadByte(); - count += (w * dy) + dx; + count += RleSkipDelta(count, w, dx, dy, undefinedPixels, rowsWithUndefinedPixels); break; default: - // If the second byte > 2, we are in 'absolute mode' - // Take this number of bytes from the stream as uncompressed data + // If the second byte > 2, we are in 'absolute mode'. + // Take this number of bytes from the stream as uncompressed data. int length = cmd[1]; byte[] run = new byte[length]; @@ -470,7 +523,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp count += run.Length; - // Absolute mode data is aligned to two-byte word-boundary + // Absolute mode data is aligned to two-byte word-boundary. int padding = length & 1; this.stream.Skip(padding); @@ -481,16 +534,105 @@ namespace SixLabors.ImageSharp.Formats.Bmp else { int max = count + cmd[0]; // as we start at the current count in the following loop, max is count + cmd[0] - byte cmd1 = cmd[1]; // store the value to avoid the repeated indexer access inside the loop + byte colorIdx = cmd[1]; // store the value to avoid the repeated indexer access inside the loop. for (; count < max; count++) { - buffer[count] = cmd1; + buffer[count] = colorIdx; } } } } + /// + /// Keeps track of skipped / undefined pixels, when EndOfBitmap command occurs. + /// + /// The already processed pixel count. + /// The width of the image. + /// The skipped pixel count. + /// The undefined pixels. + /// Rows with undefined pixels. + private static void RleSkipEndOfBitmap( + int count, + int w, + int skipPixelCount, + Span undefinedPixels, + Span rowsWithUndefinedPixels) + { + for (int i = count; i < count + skipPixelCount; i++) + { + undefinedPixels[i] = true; + } + + int skippedRowIdx = count / w; + int skippedRows = (skipPixelCount / w) - 1; + int lastSkippedRow = Math.Min(skippedRowIdx + skippedRows, rowsWithUndefinedPixels.Length - 1); + for (int i = skippedRowIdx; i <= lastSkippedRow; i++) + { + rowsWithUndefinedPixels[i] = true; + } + } + + /// + /// Keeps track of undefined / skipped pixels, when the EndOfLine command occurs. + /// + /// The already processed pixel count. + /// The width of image. + /// The undefined pixels. + /// The rows with undefined pixels. + /// The number of skipped pixels. + private static int RleSkipEndOfLine(int count, int w, Span undefinedPixels, Span rowsWithUndefinedPixels) + { + rowsWithUndefinedPixels[count / w] = true; + int remainingPixelsInRow = count % w; + if (remainingPixelsInRow > 0) + { + int skipEoL = w - remainingPixelsInRow; + for (int i = count; i < count + skipEoL; i++) + { + undefinedPixels[i] = true; + } + + return skipEoL; + } + + return 0; + } + + /// + /// Keeps track of undefined / skipped pixels, when the delta command occurs. + /// + /// The count. + /// The width of the image. + /// Delta skip in x direction. + /// Delta skip in y direction. + /// The undefined pixels. + /// The rows with undefined pixels. + /// The number of skipped pixels. + private static int RleSkipDelta( + int count, + int w, + int dx, + int dy, + Span undefinedPixels, + Span rowsWithUndefinedPixels) + { + int skipDelta = (w * dy) + dx; + for (int i = count; i < count + skipDelta; i++) + { + undefinedPixels[i] = true; + } + + int skippedRowIdx = count / w; + int lastSkippedRow = Math.Min(skippedRowIdx + dy, rowsWithUndefinedPixels.Length - 1); + for (int i = skippedRowIdx; i <= lastSkippedRow; i++) + { + rowsWithUndefinedPixels[i] = true; + } + + return skipDelta; + } + /// /// Reads the color palette from the stream. /// @@ -506,7 +648,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp private void ReadRgbPalette(Buffer2D pixels, byte[] colors, int width, int height, int bitsPerPixel, int bytesPerColorMapEntry, bool inverted) where TPixel : struct, IPixel { - // Pixels per byte (bits per pixel) + // Pixels per byte (bits per pixel). int ppb = 8 / bitsPerPixel; int arrayWidth = (width + ppb - 1) / ppb; @@ -514,7 +656,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp // Bit mask int mask = 0xFF >> (8 - bitsPerPixel); - // Rows are aligned on 4 byte boundaries + // Rows are aligned on 4 byte boundaries. int padding = arrayWidth % 4; if (padding != 0) { @@ -810,11 +952,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp uint maxValueAlpha = 0xFFFFFFFF >> (32 - bitsAlphaMask); float invMaxValueAlpha = 1.0f / maxValueAlpha; - bool unusualBitMask = false; - if (bitsRedMask > 8 || bitsGreenMask > 8 || bitsBlueMask > 8 || invMaxValueAlpha > 8) - { - unusualBitMask = true; - } + bool unusualBitMask = bitsRedMask > 8 || bitsGreenMask > 8 || bitsBlueMask > 8 || invMaxValueAlpha > 8; using (IManagedByteBuffer buffer = this.memoryAllocator.AllocateManagedByteBuffer(stride)) { @@ -910,7 +1048,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp #else byte[] buffer = new byte[BmpInfoHeader.MaxHeaderSize]; #endif - this.stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize); // read the header size + + // Read the header size. + this.stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize); int headerSize = BinaryPrimitives.ReadInt32LittleEndian(buffer); if (headerSize < BmpInfoHeader.CoreSize) @@ -925,7 +1065,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp headerSize = BmpInfoHeader.MaxHeaderSize; } - // read the rest of the header + // Read the rest of the header. this.stream.Read(buffer, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize); BmpInfoHeaderType infoHeaderType = BmpInfoHeaderType.WinVersion2; @@ -953,7 +1093,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp { byte[] bitfieldsBuffer = new byte[12]; this.stream.Read(bitfieldsBuffer, 0, 12); - Span data = bitfieldsBuffer.AsSpan(); + Span data = bitfieldsBuffer.AsSpan(); this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)); this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)); this.infoHeader.BlueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)); @@ -962,7 +1102,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp { byte[] bitfieldsBuffer = new byte[16]; this.stream.Read(bitfieldsBuffer, 0, 16); - Span data = bitfieldsBuffer.AsSpan(); + Span data = bitfieldsBuffer.AsSpan(); this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)); this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)); this.infoHeader.BlueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)); @@ -1021,7 +1161,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.bmpMetadata = this.metadata.GetFormatMetadata(BmpFormat.Instance); this.bmpMetadata.InfoHeaderType = infoHeaderType; - // We can only encode at these bit rates so far. + // We can only encode at these bit rates so far (1 bit and 4 bit are still missing). if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel8) || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel16) || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24) @@ -1030,7 +1170,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.bmpMetadata.BitsPerPixel = (BmpBitsPerPixel)bitsPerPixel; } - // skip the remaining header because we can't read those parts + // Skip the remaining header because we can't read those parts. this.stream.Skip(skipAmount); } @@ -1105,10 +1245,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp if (colorMapSize > 0) { - // 256 * 4 - if (colorMapSize > 1024) + // Usually the color palette is 1024 byte (256 colors * 4), but the documentation does not mention a size limit. + // Make sure, that we will not read pass the bitmap offset (starting position of image data). + if ((this.stream.Position + colorMapSize) > this.fileHeader.Offset) { - BmpThrowHelper.ThrowImageFormatException($"Invalid bmp colormap size '{colorMapSize}'"); + BmpThrowHelper.ThrowImageFormatException( + $"Reading the color map would read beyond the bitmap offset. Either the color map size of '{colorMapSize}' is invalid or the bitmap offset."); } palette = new byte[colorMapSize]; @@ -1121,7 +1263,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp int skipAmount = this.fileHeader.Offset - (int)this.stream.Position; if ((skipAmount + (int)this.stream.Position) > this.stream.Length) { - BmpThrowHelper.ThrowImageFormatException($"Invalid fileheader offset found. Offset is greater than the stream length."); + BmpThrowHelper.ThrowImageFormatException("Invalid fileheader offset found. Offset is greater than the stream length."); } if (skipAmount > 0) @@ -1132,4 +1274,4 @@ namespace SixLabors.ImageSharp.Formats.Bmp return bytesPerColorMapEntry; } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 9fbd0b5ad..4e6ec4502 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -51,10 +51,19 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// private const int ColorPaletteSize8Bit = 1024; + /// + /// Used for allocating memory during processing operations. + /// private readonly MemoryAllocator memoryAllocator; + /// + /// The global configuration. + /// private Configuration configuration; + /// + /// The color depth, in number of bits per pixel. + /// private BmpBitsPerPixel? bitsPerPixel; /// diff --git a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs index c0814b1df..4f862d929 100644 --- a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers.Binary; namespace SixLabors.ImageSharp.Formats.Bmp { @@ -21,10 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp private bool IsSupportedFileFormat(ReadOnlySpan header) { - // TODO: This should be in constants - return header.Length >= this.HeaderSize - && header[0] == 0x42 // B - && header[1] == 0x4D; // M + return header.Length >= this.HeaderSize && BinaryPrimitives.ReadInt16LittleEndian(header) == BmpConstants.TypeMarkers.Bitmap; } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs index 219d37ca6..f456f2ba3 100644 --- a/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs +++ b/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs @@ -8,6 +8,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// internal interface IBmpDecoderOptions { - // added this for consistency so we can add stuff as required, no options currently available + /// + /// Gets the value indicating how to deal with skipped pixels, which can occur during decoding run length encoded bitmaps. + /// + RleSkippedPixelHandling RleSkippedPixelHandling { get; } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/RleSkippedPixelHandling.cs b/src/ImageSharp/Formats/Bmp/RleSkippedPixelHandling.cs new file mode 100644 index 000000000..493fe366a --- /dev/null +++ b/src/ImageSharp/Formats/Bmp/RleSkippedPixelHandling.cs @@ -0,0 +1,26 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Bmp +{ + /// + /// Defines possible options, how skipped pixels during decoding of run length encoded bitmaps should be treated. + /// + public enum RleSkippedPixelHandling : int + { + /// + /// Undefined pixels should be black. This is the default behavior and equal to how System.Drawing handles undefined pixels. + /// + Black = 0, + + /// + /// Undefined pixels should be transparent. + /// + Transparent = 1, + + /// + /// Undefined pixels should have the first color of the palette. + /// + FirstColorOfPalette = 2 + } +} diff --git a/tests/ImageSharp.Tests/FileTestBase.cs b/tests/ImageSharp.Tests/FileTestBase.cs index a056bc474..4f8475738 100644 --- a/tests/ImageSharp.Tests/FileTestBase.cs +++ b/tests/ImageSharp.Tests/FileTestBase.cs @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Tests /// /// A collection of all the bmp test images /// - public static IEnumerable AllBmpFiles = TestImages.Bmp.All; + public static IEnumerable AllBmpFiles = TestImages.Bmp.Benchmark; /// /// A collection of all the jpeg test images diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index e615dbe56..c4dfa724c 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -1,6 +1,7 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.IO; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.PixelFormats; @@ -20,27 +21,26 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp { public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; - public static readonly string[] AllBmpFiles = All; + public static readonly string[] MiscBmpFiles = Miscellaneous; public static readonly string[] BitfieldsBmpFiles = BitFields; public static readonly TheoryData RatioFiles = new TheoryData { - { TestImages.Bmp.Car, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, - { TestImages.Bmp.V5Header, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, - { TestImages.Bmp.RLE8, 2835, 2835, PixelResolutionUnit.PixelsPerMeter } + { Car, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, + { V5Header, 3780, 3780 , PixelResolutionUnit.PixelsPerMeter }, + { RLE8, 2835, 2835, PixelResolutionUnit.PixelsPerMeter } }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), PixelTypes.Rgba32)] - public void DecodeBmp(TestImageProvider provider) + [WithFileCollection(nameof(MiscBmpFiles), PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_MiscellaneousBitmaps(TestImageProvider provider) where TPixel : struct, IPixel { using (Image image = provider.GetImage(new BmpDecoder())) { image.DebugSave(provider); - if (TestEnvironment.IsWindows) { image.CompareToOriginal(provider); @@ -60,6 +60,174 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } } + [Theory] + [WithFile(Bit16Inverted, PixelTypes.Rgba32)] + [WithFile(Bit8Inverted, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_Inverted(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFile(Bit1, PixelTypes.Rgba32)] + [WithFile(Bit1Pal1, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_1Bit(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, new SystemDrawingReferenceDecoder()); + } + } + + [Theory] + [WithFile(Bit4, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_4Bit(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + // The Magick Reference Decoder can not decode 4-Bit bitmaps, so only execute this on windows. + if (TestEnvironment.IsWindows) + { + image.CompareToOriginal(provider); + } + } + } + + [Theory] + [WithFile(Bit8, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_8Bit(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFile(Bit16, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_16Bit(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFile(Bit32Rgb, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_32Bit(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFile(Rgba32v4, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_32BitV4Header_Fast(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFile(RLE4Cut, PixelTypes.Rgba32)] + [WithFile(RLE4Delta, PixelTypes.Rgba32)] + [WithFile(Rle4Delta320240, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_RunLengthEncoded_4Bit_WithDelta(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder() { RleSkippedPixelHandling = RleSkippedPixelHandling.Black })) + { + image.DebugSave(provider); + // The Magick Reference Decoder can not decode 4-Bit bitmaps, so only execute this on windows. + if (TestEnvironment.IsWindows) + { + image.CompareToOriginal(provider); + } + } + } + + [Theory] + [WithFile(RLE4, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_RunLengthEncoded_4Bit(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder() { RleSkippedPixelHandling = RleSkippedPixelHandling.Black })) + { + image.DebugSave(provider); + // The Magick Reference Decoder can not decode 4-Bit bitmaps, so only execute this on windows. + if (TestEnvironment.IsWindows) + { + image.CompareToOriginal(provider); + } + } + } + + [Theory] + [WithFile(RLE8Cut, PixelTypes.Rgba32)] + [WithFile(RLE8Delta, PixelTypes.Rgba32)] + [WithFile(Rle8Delta320240, PixelTypes.Rgba32)] + [WithFile(Rle8Blank160120, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit_WithDelta_SystemDrawingRefDecoder(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder() { RleSkippedPixelHandling = RleSkippedPixelHandling.Black })) + { + image.DebugSave(provider); + if (TestEnvironment.IsWindows) + { + image.CompareToOriginal(provider, new SystemDrawingReferenceDecoder()); + } + } + } + + [Theory] + [WithFile(RLE8Cut, PixelTypes.Rgba32)] + [WithFile(RLE8Delta, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit_WithDelta_MagickRefDecoder(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder() { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette })) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, new MagickReferenceDecoder()); + } + } + + [Theory] + [WithFile(RLE8, PixelTypes.Rgba32)] + [WithFile(RLE8Inverted, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder() { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette })) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, new MagickReferenceDecoder()); + } + } + [Theory] [WithFile(RgbaAlphaBitfields, PixelTypes.Rgba32)] public void BmpDecoder_CanDecodeAlphaBitfields(TestImageProvider provider) @@ -106,6 +274,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [Theory] [WithFile(WinBmpv2, PixelTypes.Rgba32)] + [WithFile(CoreHeader, PixelTypes.Rgba32)] public void BmpDecoder_CanDecodeBmpv2(TestImageProvider provider) where TPixel : struct, IPixel { @@ -141,7 +310,41 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } [Theory] - [WithFile(Rgba32bf56, PixelTypes.Rgba32)] + [WithFile(OversizedPalette, PixelTypes.Rgba32)] + [WithFile(Rgb24LargePalette, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeOversizedPalette(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + if (TestEnvironment.IsWindows) + { + image.CompareToOriginal(provider); + } + } + } + + [Theory] + [WithFile(InvalidPaletteSize, PixelTypes.Rgba32)] + public void BmpDecoder_ThrowsImageFormatException_OnInvalidPaletteSize(TestImageProvider provider) + where TPixel : struct, IPixel + { + Assert.Throws( () => { using (Image image = provider.GetImage(new BmpDecoder())) { } }); + } + + [Theory] + [WithFile(Rgb24jpeg, PixelTypes.Rgba32)] + [WithFile(Rgb24png, PixelTypes.Rgba32)] + public void BmpDecoder_ThrowsNotSupportedException_OnUnsupportedBitmaps(TestImageProvider provider) + where TPixel : struct, IPixel + { + Assert.Throws(() => { using (Image image = provider.GetImage(new BmpDecoder())) { } }); + } + + [Theory] + [WithFile(Rgba32bf56AdobeV3, PixelTypes.Rgba32)] + [WithFile(Rgb32h52AdobeV3, PixelTypes.Rgba32)] public void BmpDecoder_CanDecodeAdobeBmpv3(TestImageProvider provider) where TPixel : struct, IPixel { @@ -166,6 +369,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [Theory] [WithFile(WinBmpv5, PixelTypes.Rgba32)] + [WithFile(V5Header, PixelTypes.Rgba32)] public void BmpDecoder_CanDecodeBmpv5(TestImageProvider provider) where TPixel : struct, IPixel { @@ -223,6 +427,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [InlineData(Bit8, 8)] [InlineData(Bit8Inverted, 8)] [InlineData(Bit4, 4)] + [InlineData(Bit1, 1)] + [InlineData(Bit1Pal1, 1)] public void Identify(string imagePath, int expectedPixelSize) { var testFile = TestFile.Create(imagePath); @@ -281,4 +487,4 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs b/tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs index 65989556d..95a47fd7c 100644 --- a/tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs +++ b/tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs @@ -82,7 +82,7 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks return; } - string[] testFiles = TestImages.Bmp.All + string[] testFiles = TestImages.Bmp.Benchmark .Concat(new[] { TestImages.Jpeg.Baseline.Calliphora, TestImages.Jpeg.Baseline.Cmyk }).ToArray(); Image[] testImages = testFiles.Select( diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index d8e8719ba..d041f4854 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -231,8 +231,15 @@ namespace SixLabors.ImageSharp.Tests public const string CoreHeader = "Bmp/BitmapCoreHeaderQR.bmp"; public const string V5Header = "Bmp/BITMAPV5HEADER.bmp"; public const string RLE8 = "Bmp/RunLengthEncoded.bmp"; + public const string RLE8Cut = "Bmp/pal8rlecut.bmp"; + public const string RLE8Delta = "Bmp/pal8rletrns.bmp"; + public const string Rle8Delta320240 = "Bmp/rle8-delta-320x240.bmp"; + public const string Rle8Blank160120 = "Bmp/rle8-blank-160x120.bmp"; + public const string RLE8Inverted = "Bmp/RunLengthEncoded-inverted.bmp"; public const string RLE4 = "Bmp/pal4rle.bmp"; - public const string RLEInverted = "Bmp/RunLengthEncoded-inverted.bmp"; + public const string RLE4Cut = "Bmp/pal4rlecut.bmp"; + public const string RLE4Delta = "Bmp/pal4rletrns.bmp"; + public const string Rle4Delta320240 = "Bmp/rle4-delta-320x240.bmp"; public const string Bit1 = "Bmp/pal1.bmp"; public const string Bit1Pal1 = "Bmp/pal1p1.bmp"; public const string Bit4 = "Bmp/pal4.bmp"; @@ -256,15 +263,22 @@ namespace SixLabors.ImageSharp.Tests public const string Os2v2 = "Bmp/pal8os2v2.bmp"; public const string LessThanFullSizedPalette = "Bmp/pal8os2sp.bmp"; public const string Pal8Offset = "Bmp/pal8offs.bmp"; + public const string OversizedPalette = "Bmp/pal8oversizepal.bmp"; + public const string Rgb24LargePalette = "Bmp/rgb24largepal.bmp"; + public const string InvalidPaletteSize = "Bmp/invalidPaletteSize.bmp"; + public const string Rgb24jpeg = "Bmp/rgb24jpeg.bmp"; + public const string Rgb24png = "Bmp/rgb24png.bmp"; + public const string Rgba32v4 = "Bmp/rgba32v4.bmp"; - // Bitmap images with compression type BITFIELDS + // Bitmap images with compression type BITFIELDS. public const string Rgb32bfdef = "Bmp/rgb32bfdef.bmp"; public const string Rgb32bf = "Bmp/rgb32bf.bmp"; public const string Rgb16bfdef = "Bmp/rgb16bfdef.bmp"; public const string Rgb16565 = "Bmp/rgb16-565.bmp"; public const string Rgb16565pal = "Bmp/rgb16-565pal.bmp"; public const string Issue735 = "Bmp/issue735.bmp"; - public const string Rgba32bf56 = "Bmp/rgba32h56.bmp"; + public const string Rgba32bf56AdobeV3 = "Bmp/rgba32h56.bmp"; + public const string Rgb32h52AdobeV3 = "Bmp/rgb32h52.bmp"; public const string Rgba321010102 = "Bmp/rgba32-1010102.bmp"; public const string RgbaAlphaBitfields = "Bmp/rgba32abf.bmp"; @@ -278,25 +292,32 @@ namespace SixLabors.ImageSharp.Tests Issue735, }; - public static readonly string[] All + public static readonly string[] Miscellaneous = { Car, F, - NegHeight, - CoreHeader, - V5Header, - RLE4, - RLE8, - RLEInverted, - Bit1, - Bit1Pal1, - Bit4, - Bit8, - Bit8Inverted, - Bit16, - Bit16Inverted, - Bit32Rgb + NegHeight }; + + public static readonly string[] Benchmark + = { + Car, + F, + NegHeight, + CoreHeader, + V5Header, + RLE4, + RLE8, + RLE8Inverted, + Bit1, + Bit1Pal1, + Bit4, + Bit8, + Bit8Inverted, + Bit16, + Bit16Inverted, + Bit32Rgb + }; } public static class Gif diff --git a/tests/Images/Input/Bmp/invalidPaletteSize.bmp b/tests/Images/Input/Bmp/invalidPaletteSize.bmp new file mode 100644 index 0000000000000000000000000000000000000000..afb120bbf956e58ac817c15b379cf9076ccd6678 GIT binary patch literal 9270 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 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/pal4rlecut.bmp b/tests/Images/Input/Bmp/pal4rlecut.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2f32d1d7add527b6d6d80c4629aadd24f2437c9d GIT binary patch literal 3610 zcmb_e&ubf35FYPp-%3`jYP7Ls$!TM$ftHd(mbDF%7aB!Al@X+S^gx2FHJ-vOJH{Unk%+sA8$~lVv zT6p~$<7bT97;}^&1Mf!*L{3%@Oyj>ZdNQ8H(y9c>VL>YL=h?m1b?1fZ& zuT9q8XuY}hkgRRG?m07-M{EwW%N@7lb`Rz^$vi$vGudr!=X1-nwAW^buR5?bn%|)6 zc1up4SP2dUfhA{q1G0}D#@XB^J4QiSH})(zGE8PWUsx6_vfgkfXi8IfG#YrE?|K>! zGtI;27?C_{dY56U08@aIqXTP`HlxAuu`4TLZLw#2kK!E-H@aha1?@Y+}a-effSGMxwwcG+mFfKu&eYC2b{Rdxu^Ix3JsW~cXQ*;1b2OvYTSznNU6C0ELYpplHcoYl4h z=R{^_=cV}?EI1rY*OJlt;zEXK)xlxf%FFx9`{%0YbI<5P_N5AP zBZ>*T(cm>LvVn>XdN%k9o;`cS2bh_`E%5ivhQHx&x4g1gZDi*vX9?81ZV#1DYJYDZ zPs!p+Uhl>7Xs)O)Am5rJnl&U3Y zN7W@>9HKP1)gCb0-$Mt`-aI$_A+{EE2lGTM6TT#5%@<-lLYKFMmW1z* zXKpMbk<+-s)9AsPZDGTkV#Cv@4OV?bV^u0p)>VRj!w?iAAc;US2xih8gnE|c5K8-L zqAu+v&)4d+b+4Jq>2GD&3rCm~*ZVZD*KJPpRNyO6l8Wz)gq;d%sS&slqCqf7IlhG0 zk__00LubwA(m2Dho(fVYPM%bVjuel%gY!zl@r}H`tz8Fj*dnv-r(hg4SfUan8#dto<28)TTIwJ|2}4Aq;~L9z|E&kwBuAN zjSARlgguo+3QfNB);(Wq5;a!`;o^Oyf5lG|?nWy%2c3A2!D*k=&X4-Jjy}1=XY`XD zF@^{=-h`Dj7}Qw6AY~hIWFrpIzy|AtE^NLTWz5&H&FRncTz^{BXD2H*Cwv+_?^CK3 z`_^&MN`VXb0kY=Ry?RZ@FLg7cZ4sN~^9uL-MTrb^n``=1Fcoe^+wTEa__5eKkmz#% z#&0y{SLb5HE4o^a{r=NpN#c%sT*76tFU7uHHzMdSvO;8R1wreu*J=s+ad%8=Kv&|d z0^?5XM2K`w6zdyLtsnx<6$&I$JOs)*6bg8PQeL7H%XbBpbbD zqKKStyv(eV8Qm>tB-svrkAyv}x4uC9c7bZ#Xg0mD86HNbr-OT*w#bY6QU9bzb`eZ= zx?L~qB8TtaKkOlMOCca61CdOsBkDmt=BuOhJ+h;F(cPR+OBw}!hoNENX?1633Ws1y zu-Jkn`kSoN#dRxE&nLY>P%Nx-B)Ld;q+3Y*=n!$XCF3fbdkr_M)k3v!+SG#_?jGv;$B4d$;age^*7eCf{dcDhu~C|>V+FO0BsB4z8}82zpm}U`U8LH51*6T zrCRavV*oq^#NUTIDA;Kei2p;bs^%Sgi_{-)PskcB-nZVV;pMra)z-9jF~`jXFB$RD he;a!t^=|kMv&^pfYvz#DpM5A{NY`focy)m=_Ya3`k@o-q literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/pal4rletrns.bmp b/tests/Images/Input/Bmp/pal4rletrns.bmp new file mode 100644 index 0000000000000000000000000000000000000000..58994e92baf9812eb805c04807ca946b07f11185 GIT binary patch literal 4326 zcmb_e%}*mo7JqcRtNjs(%MBPivtjH-+EtVTRs)hvOFPCsMYGaK$Tu!4A`Xbd&dDN* zl=!rW6P6E=M{{sbkHm~Mhl#8lR?LB@ffdky$Nn4a?{&4mAem&fOHuCb>h7xd`*^Q< z>#zS#Q~0-!-#?>&hyDb8hGL}Q_$}^RDb;6j&3||FeR$-v@br5e@lSVm>VV%nJaUI| z458mqO6n!kCea!ElZ>+kX|%-AaICibH5q%$7Lkzg66u|jxlQfISt(mu%LqqmPv$o0 z@owHi%Z(aQ0<$J~*6tvjl|<{PMaI!^yjI`E%(QGSlAENTy^l*W zTe6j&TcX9ImbB!&g||HYVNVita zl4c8wI~lgciwjAqQn)rFO-RyP>C6(NOBNYWBxa z7l7Ku%KnM5Nt^!Q?5xBi+*;h;96b-8sFwUE#s>Y#-`(4DOB1c_t}5&wSCf{fDYx*} zZ>c+0me2ktbr+70|fN#)xIIHhdMDxRp-@WclF@oExh+iklizgOdBdsi{;r_V33iBvi2eX!RC$m-C|NMc1^w`4Us^yoCmyYk{ z=^t#Z101;mv}4D49e;363sOT(aC;_l!+rDSxjey{?yiE*FE*SFXK&xmb1M%UrkKpl zMMzO9^*HCm@zF8ON@Sv>n7wQ6F$ywdAz|K z$dsjOIvU@g6mrD%PDEZSt4^_UgngK+JPXQO9L%d3aCUrzilb(;OW|y|kJL5xa?C@_ z=GZ?GA_>Gsz(eJbFdOy+ z8@58NNzs46tdQYeq1;#~z>V{S4DdXVi%>Z>RvnzhrR%A)l=R@vzmFZM=1$aCxueOYh$Hpwppc9hwr#a~47)2wasN2tYM3`*D}xosSrub6V#%`}A2xX7Gu%W>@S=S>fb-oXQ!tD%?Py$bLV|2ykx7 zvRW04dUb#A3bZhfhO|#Oy18G{!5`_MG#m1dIyxtv{%JPHafekk;yijTCLOb)`Eajq zcpNo?R$;G|BlM$s9Ayw^IPx@%7jcca9(pfr6I4?iPr4Z{k4wu3ni{pLq%$)! zJWI%AlnGP(fx(bJWZRsyP$csn8GRC2ndLk(m@eMW=n?KlY zY^gTBvb-L~_df?BGec!rt<`L==5_ts+rhT2ns57kzkkysGYkIPosR8wp#0U(Xc4;%%-{j0}}2bPqd7cr)i%;Bhfi%&g4U z*XnCuRo*$lhlO<#{*6z@4gIB=ZDtR1-Ez15g6|!akslL%brPZXF@*VFM@UAoh^kzK ziglXx>KDOna84FSvF($2Lq@ZS`%S%VbaB6X9bDl)stfN6dS^8eq8`?VU)L2GKgu2f zQ~F*H;fo?wGAksd z%sPqJ7XTbAG>l6Tq?-BUsD|VRZIsn`P?z@ zx#9tlBwyDR6S6@`#4_Rn(Inq?f02!H$c9xcZWUi`z1q6yC7+TWoW~moqH+0bZig0w Xe>D%A-yn!@Ur_QT6@%bGM$h~Q4Wl~I literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/pal8oversizepal.bmp b/tests/Images/Input/Bmp/pal8oversizepal.bmp new file mode 100644 index 0000000000000000000000000000000000000000..93b8187ca1351aa20edad1a8c1da1c8a1bf74631 GIT binary patch literal 9446 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 Nll3QGs>B9m{5Mp_Pk;ab literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/pal8rletrns.bmp b/tests/Images/Input/Bmp/pal8rletrns.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a2af88d87cbb042f233e1ace72d69d5fc7b7a82f GIT binary patch literal 9212 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 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/rgb24largepal.bmp b/tests/Images/Input/Bmp/rgb24largepal.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d5e418c2d41904a910afe101508025ab33915cdf GIT binary patch literal 25830 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 B3Bv#Y literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/rgba32v4.bmp b/tests/Images/Input/Bmp/rgba32v4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..9d644a8b1e3ca6fa444eaa00ff952f19f858b043 GIT binary patch literal 32634 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 Date: Fri, 14 Jun 2019 12:23:43 +1000 Subject: [PATCH 218/223] Fix 925 (#929) * Prevent overflow * Cleanup huffman table * Search for RST markers. * Fix Benchmarks project --- .../Components/Decoder/HuffmanScanBuffer.cs | 92 +++++++++++++------ .../Components/Decoder/HuffmanScanDecoder.cs | 14 ++- .../Jpeg/Components/Decoder/HuffmanTable.cs | 48 +++++----- .../Formats/Jpeg/JpegDecoderCore.cs | 6 +- .../ImageSharp.Benchmarks.csproj | 11 +-- .../Formats/Jpg/JpegDecoderTests.Images.cs | 8 +- tests/Images/External | 2 +- 7 files changed, 103 insertions(+), 78 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs index dd5160414..13c89c82c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder private ulong data; // The number of valid bits left to read in the buffer. - private int remain; + private int remainingBits; // Whether there is no more good data to pull from the stream for the current mcu. private bool badData; @@ -26,10 +26,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { this.stream = stream; this.data = 0ul; - this.remain = 0; + this.remainingBits = 0; this.Marker = JpegConstants.Markers.XFF; this.MarkerPosition = 0; - this.BadMarker = false; this.badData = false; this.NoData = false; } @@ -44,11 +43,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// public long MarkerPosition { get; private set; } - /// - /// Gets a value indicating whether a bad marker has been detected, I.E. One that is not between RST0 and RST7 - /// - public bool BadMarker { get; private set; } - /// /// Gets a value indicating whether to continue reading the input stream. /// @@ -57,7 +51,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder [MethodImpl(InliningOptions.ShortMethod)] public void CheckBits() { - if (this.remain < 16) + if (this.remainingBits < 16) { this.FillBuffer(); } @@ -67,27 +61,31 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder public void Reset() { this.data = 0ul; - this.remain = 0; + this.remainingBits = 0; this.Marker = JpegConstants.Markers.XFF; this.MarkerPosition = 0; - this.BadMarker = false; this.badData = false; this.NoData = false; } + /// + /// Whether a RST marker has been detected, I.E. One that is between RST0 and RST7 + /// [MethodImpl(InliningOptions.ShortMethod)] - public bool HasRestart() - { - byte m = this.Marker; - return m >= JpegConstants.Markers.RST0 && m <= JpegConstants.Markers.RST7; - } + public bool HasRestartMarker() => HasRestart(this.Marker); + + /// + /// Whether a bad marker has been detected, I.E. One that is not between RST0 and RST7 + /// + [MethodImpl(InliningOptions.ShortMethod)] + public bool HasBadMarker() => this.Marker != JpegConstants.Markers.XFF && !this.HasRestartMarker(); [MethodImpl(InliningOptions.ShortMethod)] public void FillBuffer() { // Attempt to load at least the minimum number of required bits into the buffer. // We fail to do so only if we hit a marker or reach the end of the input stream. - this.remain += 48; + this.remainingBits += 48; this.data = (this.data << 48) | this.GetBytes(); } @@ -101,17 +99,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder if (size == JpegConstants.Huffman.SlowBits) { - ulong x = this.data << (JpegConstants.Huffman.RegisterSize - this.remain); + ulong x = this.data << (JpegConstants.Huffman.RegisterSize - this.remainingBits); while (x > h.MaxCode[size]) { size++; } v = (int)(x >> (JpegConstants.Huffman.RegisterSize - size)); - symbol = h.Values[h.ValOffset[size] + v]; + symbol = h.Values[(h.ValOffset[size] + v) & 0xFF]; } - this.remain -= size; + this.remainingBits -= size; return symbol; } @@ -124,10 +122,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } [MethodImpl(InliningOptions.ShortMethod)] - public int GetBits(int nbits) => (int)ExtractBits(this.data, this.remain -= nbits, nbits); + private static bool HasRestart(byte marker) + => marker >= JpegConstants.Markers.RST0 && marker <= JpegConstants.Markers.RST7; [MethodImpl(InliningOptions.ShortMethod)] - public int PeekBits(int nbits) => (int)ExtractBits(this.data, this.remain - nbits, nbits); + public int GetBits(int nbits) => (int)ExtractBits(this.data, this.remainingBits -= nbits, nbits); + + [MethodImpl(InliningOptions.ShortMethod)] + public int PeekBits(int nbits) => (int)ExtractBits(this.data, this.remainingBits - nbits, nbits); [MethodImpl(InliningOptions.ShortMethod)] private static ulong ExtractBits(ulong value, int offset, int size) => (value >> offset) & (ulong)((1 << size) - 1); @@ -149,22 +151,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder int c = this.ReadStream(); while (c == JpegConstants.Markers.XFF) { - // Loop here to discard any padding FF's on terminating marker, + // Loop here to discard any padding FF bytes on terminating marker, // so that we can save a valid marker value. c = this.ReadStream(); } - // We accept multiple FF's followed by a 0 as meaning a single FF data byte. + // We accept multiple FF bytes followed by a 0 as meaning a single FF data byte. // This data pattern is not valid according to the standard. if (c != 0) { this.Marker = (byte)c; this.badData = true; - if (!this.HasRestart()) - { - this.MarkerPosition = this.stream.Position - 2; - this.BadMarker = true; - } + this.MarkerPosition = this.stream.Position - 2; } } @@ -174,6 +172,42 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder return temp; } + [MethodImpl(InliningOptions.ShortMethod)] + public bool FindNextMarker() + { + while (true) + { + int b = this.stream.ReadByte(); + if (b == -1) + { + return false; + } + + // Found a marker. + if (b == JpegConstants.Markers.XFF) + { + while (b == JpegConstants.Markers.XFF) + { + // Loop here to discard any padding FF bytes on terminating marker. + b = this.stream.ReadByte(); + if (b == -1) + { + return false; + } + } + + // Found a valid marker. Exit loop + if (b != 0) + { + this.Marker = (byte)b; + this.badData = true; + this.MarkerPosition = this.stream.Position - 2; + return true; + } + } + } + } + [MethodImpl(InliningOptions.ShortMethod)] private int ReadStream() { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs index c28733250..c50812e25 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs @@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.ParseProgressiveData(); } - if (this.scanBuffer.BadMarker) + if (this.scanBuffer.HasBadMarker()) { this.stream.Position = this.scanBuffer.MarkerPosition; } @@ -684,15 +684,23 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { if (this.restartInterval > 0 && (--this.todo) == 0) { + if (this.scanBuffer.Marker == JpegConstants.Markers.XFF) + { + if (!this.scanBuffer.FindNextMarker()) + { + return false; + } + } + this.todo = this.restartInterval; - if (this.scanBuffer.HasRestart()) + if (this.scanBuffer.HasRestartMarker()) { this.Reset(); return true; } - if (this.scanBuffer.Marker != JpegConstants.Markers.XFF) + if (this.scanBuffer.HasBadMarker()) { this.stream.Position = this.scanBuffer.MarkerPosition; this.Reset(); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs index 21ed5018f..4685ba289 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs @@ -1,20 +1,18 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using SixLabors.Memory; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { /// - /// Represents a Huffman coding table containing basic coding data plus tables for accellerated computation. + /// Represents a Huffman coding table containing basic coding data plus tables for accelerated computation. /// [StructLayout(LayoutKind.Sequential)] internal unsafe struct HuffmanTable { - private readonly MemoryAllocator memoryAllocator; private bool isConfigured; /// @@ -60,13 +58,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// /// Initializes a new instance of the struct. /// - /// The to use for buffer allocations. /// The code lengths /// The huffman values - public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan codeLengths, ReadOnlySpan values) + public HuffmanTable(ReadOnlySpan codeLengths, ReadOnlySpan values) { this.isConfigured = false; - this.memoryAllocator = memoryAllocator; Unsafe.CopyBlockUnaligned(ref this.Sizes[0], ref MemoryMarshal.GetReference(codeLengths), (uint)codeLengths.Length); Unsafe.CopyBlockUnaligned(ref this.Values[0], ref MemoryMarshal.GetReference(values), (uint)values.Length); } @@ -81,33 +77,31 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder return; } - int p, si; - Span huffsize = stackalloc char[257]; - Span huffcode = stackalloc uint[257]; - uint code; + Span huffSize = stackalloc char[257]; + Span huffCode = stackalloc uint[257]; // Figure C.1: make table of Huffman code length for each symbol - p = 0; + int p = 0; for (int l = 1; l <= 16; l++) { int i = this.Sizes[l]; while (i-- != 0) { - huffsize[p++] = (char)l; + huffSize[p++] = (char)l; } } - huffsize[p] = (char)0; + huffSize[p] = (char)0; // Figure C.2: generate the codes themselves - code = 0; - si = huffsize[0]; + uint code = 0; + int si = huffSize[0]; p = 0; - while (huffsize[p] != 0) + while (huffSize[p] != 0) { - while (huffsize[p] == si) + while (huffSize[p] == si) { - huffcode[p++] = code; + huffCode[p++] = code; code++; } @@ -121,10 +115,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { if (this.Sizes[l] != 0) { - int offset = p - (int)huffcode[p]; + int offset = p - (int)huffCode[p]; this.ValOffset[l] = offset; p += this.Sizes[l]; - this.MaxCode[l] = huffcode[p - 1]; // Maximum code of length l + this.MaxCode[l] = huffCode[p - 1]; // Maximum code of length l this.MaxCode[l] <<= 64 - l; // Left justify this.MaxCode[l] |= (1ul << (64 - l)) - 1; } @@ -150,14 +144,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder { for (int i = 1; i <= this.Sizes[length]; i++, p++) { - // length = current code's length, p = its index in huffcode[] & huffval[]. + // length = current code's length, p = its index in huffCode[] & Values[]. // Generate left-justified code followed by all possible bit sequences - int lookbits = (int)(huffcode[p] << (JpegConstants.Huffman.LookupBits - length)); + int lookBits = (int)(huffCode[p] << (JpegConstants.Huffman.LookupBits - length)); for (int ctr = 1 << (JpegConstants.Huffman.LookupBits - length); ctr > 0; ctr--) { - this.LookaheadSize[lookbits] = (byte)length; - this.LookaheadValue[lookbits] = this.Values[p]; - lookbits++; + this.LookaheadSize[lookBits] = (byte)length; + this.LookaheadValue[lookBits] = this.Values[p]; + lookBits++; } } } @@ -165,4 +159,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder this.isConfigured = true; } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index fd0c289b8..bf7c8f9c8 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -952,7 +952,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The values [MethodImpl(InliningOptions.ShortMethod)] private void BuildHuffmanTable(HuffmanTable[] tables, int index, ReadOnlySpan codeLengths, ReadOnlySpan values) - => tables[index] = new HuffmanTable(this.configuration.MemoryAllocator, codeLengths, values); + => tables[index] = new HuffmanTable(codeLengths, values); /// /// Reads a from the stream advancing it by two bytes @@ -992,4 +992,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg return image; } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index 1e951f5d0..14ad5635c 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -6,11 +6,8 @@ Exe SixLabors.ImageSharp.Benchmarks netcoreapp2.1;net472 - - - - win7-x64 - false + false + false @@ -18,10 +15,6 @@ - - - - diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index 56496fad1..4a3ef9b95 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -15,14 +15,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestImages.Jpeg.Baseline.Jpeg400, TestImages.Jpeg.Baseline.Testorig420, - // BUG: The following image has a high difference compared to the expected output: + // BUG: The following image has a high difference compared to the expected output: 1.0096% // TestImages.Jpeg.Baseline.Jpeg420Small, - // BUG: While we can decode this image we do not return the same output as libjpeg - // based decoders and are inserting a number of lines equal to the corrupted lines - // below said lines. - // TestImages.Jpeg.Issues.Fuzz.AccessViolationException922, - + TestImages.Jpeg.Issues.Fuzz.AccessViolationException922, TestImages.Jpeg.Baseline.Jpeg444, TestImages.Jpeg.Baseline.Bad.BadEOF, TestImages.Jpeg.Baseline.MultiScanBaselineCMYK, diff --git a/tests/Images/External b/tests/Images/External index 42b3b980e..acc32594c 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 42b3b980ed07afd7b6603a5bfa6ffb91d6c8a124 +Subproject commit acc32594c125656840f8a17e69b0ebb49a370fa6 From 6016c11bd04a19fdd3203e9e4208f3a1549d7dae Mon Sep 17 00:00:00 2001 From: Brian Popow <38701097+brianpopow@users.noreply.github.com> Date: Fri, 14 Jun 2019 15:36:28 +0200 Subject: [PATCH 219/223] Bitmap decoder now can decode bitmap arrays (#930) * Bitmap Decoder can now decode BitmapArray * Add tests for bitmap metadata decoing. Fix an issue that a bitmap with a v5 header would be set in the metadata as an v4 header. * Fixed issue with decoding bitmap arrays: color map size was not determined correctly. Added more test images. * Refactor colormap size duplicate declaration. * Fixed an issue, that when an unsupported bitmap is loaded the typ marker was not correctly shown in the error message --- .../Formats/Bmp/BmpArrayFileHeader.cs | 53 ++++++++++++++ src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 69 +++++++++++------- src/ImageSharp/Formats/Bmp/BmpFileHeader.cs | 6 +- .../Formats/Bmp/BmpImageFormatDetector.cs | 8 +- src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs | 17 +++-- .../Formats/Bmp/BmpDecoderTests.cs | 64 ++++++++++++++-- .../Formats/Bmp/BmpEncoderTests.cs | 6 +- .../Formats/Bmp/BmpMetaDataTests.cs | 32 +++++++- tests/ImageSharp.Tests/TestImages.cs | 8 ++ tests/Images/Input/Bmp/9S.BMP | Bin 0 -> 2684 bytes tests/Images/Input/Bmp/DIAMOND.BMP | Bin 0 -> 2684 bytes tests/Images/Input/Bmp/GMARBLE.BMP | Bin 0 -> 49585 bytes tests/Images/Input/Bmp/PINES.BMP | Bin 0 -> 61377 bytes tests/Images/Input/Bmp/SKATER.BMP | Bin 0 -> 7242 bytes tests/Images/Input/Bmp/SPADE.BMP | Bin 0 -> 2684 bytes tests/Images/Input/Bmp/SUNFLOW.BMP | Bin 0 -> 51753 bytes tests/Images/Input/Bmp/WARPD.BMP | Bin 0 -> 2363136 bytes 17 files changed, 216 insertions(+), 47 deletions(-) create mode 100644 src/ImageSharp/Formats/Bmp/BmpArrayFileHeader.cs create mode 100644 tests/Images/Input/Bmp/9S.BMP create mode 100644 tests/Images/Input/Bmp/DIAMOND.BMP create mode 100644 tests/Images/Input/Bmp/GMARBLE.BMP create mode 100644 tests/Images/Input/Bmp/PINES.BMP create mode 100644 tests/Images/Input/Bmp/SKATER.BMP create mode 100644 tests/Images/Input/Bmp/SPADE.BMP create mode 100644 tests/Images/Input/Bmp/SUNFLOW.BMP create mode 100644 tests/Images/Input/Bmp/WARPD.BMP diff --git a/src/ImageSharp/Formats/Bmp/BmpArrayFileHeader.cs b/src/ImageSharp/Formats/Bmp/BmpArrayFileHeader.cs new file mode 100644 index 000000000..e8afb422a --- /dev/null +++ b/src/ImageSharp/Formats/Bmp/BmpArrayFileHeader.cs @@ -0,0 +1,53 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp.Formats.Bmp +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal readonly struct BmpArrayFileHeader + { + public BmpArrayFileHeader(short type, int size, int offsetToNext, short width, short height) + { + this.Type = type; + this.Size = size; + this.OffsetToNext = offsetToNext; + this.ScreenWidth = width; + this.ScreenHeight = height; + } + + /// + /// Gets the Bitmap identifier. + /// The field used to identify the bitmap file: 0x42 0x41 (Hex code points for B and A). + /// + public short Type { get; } + + /// + /// Gets the size of this header. + /// + public int Size { get; } + + /// + /// Gets the offset to next OS2BMPARRAYFILEHEADER. + /// This offset is calculated from the starting byte of the file. A value of zero indicates that this header is for the last image in the array list. + /// + public int OffsetToNext { get; } + + /// + /// Gets the width of the image display in pixels. + /// + public short ScreenWidth { get; } + + /// + /// Gets the height of the image display in pixels. + /// + public short ScreenHeight { get; } + + public static BmpArrayFileHeader Parse(Span data) + { + return MemoryMarshal.Cast(data)[0]; + } + } +} diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 294b49ed7..1ceb35283 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -1053,18 +1053,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize); int headerSize = BinaryPrimitives.ReadInt32LittleEndian(buffer); - if (headerSize < BmpInfoHeader.CoreSize) + if (headerSize < BmpInfoHeader.CoreSize || headerSize > BmpInfoHeader.MaxHeaderSize) { BmpThrowHelper.ThrowNotSupportedException($"ImageSharp does not support this BMP file. HeaderSize is '{headerSize}'."); } - int skipAmount = 0; - if (headerSize > BmpInfoHeader.MaxHeaderSize) - { - skipAmount = headerSize - BmpInfoHeader.MaxHeaderSize; - headerSize = BmpInfoHeader.MaxHeaderSize; - } - // Read the rest of the header. this.stream.Read(buffer, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize); @@ -1169,15 +1162,13 @@ namespace SixLabors.ImageSharp.Formats.Bmp { this.bmpMetadata.BitsPerPixel = (BmpBitsPerPixel)bitsPerPixel; } - - // Skip the remaining header because we can't read those parts. - this.stream.Skip(skipAmount); } /// /// Reads the from the stream. /// - private void ReadFileHeader() + /// The color map size in bytes, if it could be determined by the file header. Otherwise -1. + private int ReadFileHeader() { #if NETCOREAPP2_1 Span buffer = stackalloc byte[BmpFileHeader.Size]; @@ -1186,12 +1177,36 @@ namespace SixLabors.ImageSharp.Formats.Bmp #endif this.stream.Read(buffer, 0, BmpFileHeader.Size); - this.fileHeader = BmpFileHeader.Parse(buffer); - - if (this.fileHeader.Type != BmpConstants.TypeMarkers.Bitmap) + short fileTypeMarker = BinaryPrimitives.ReadInt16LittleEndian(buffer); + switch (fileTypeMarker) { - BmpThrowHelper.ThrowNotSupportedException($"ImageSharp does not support this BMP file. File header bitmap type marker '{this.fileHeader.Type}'."); + case BmpConstants.TypeMarkers.Bitmap: + this.fileHeader = BmpFileHeader.Parse(buffer); + break; + case BmpConstants.TypeMarkers.BitmapArray: + // The Array file header is followed by the bitmap file header of the first image. + var arrayHeader = BmpArrayFileHeader.Parse(buffer); + this.stream.Read(buffer, 0, BmpFileHeader.Size); + this.fileHeader = BmpFileHeader.Parse(buffer); + if (this.fileHeader.Type != BmpConstants.TypeMarkers.Bitmap) + { + BmpThrowHelper.ThrowNotSupportedException($"Unsupported bitmap file inside a BitmapArray file. File header bitmap type marker '{this.fileHeader.Type}'."); + } + + if (arrayHeader.OffsetToNext != 0) + { + int colorMapSizeBytes = arrayHeader.OffsetToNext - arrayHeader.Size; + return colorMapSizeBytes; + } + + break; + + default: + BmpThrowHelper.ThrowNotSupportedException($"ImageSharp does not support this BMP file. File header bitmap type marker '{fileTypeMarker}'."); + break; } + + return -1; } /// @@ -1203,7 +1218,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp { this.stream = stream; - this.ReadFileHeader(); + int colorMapSizeBytes = this.ReadFileHeader(); this.ReadInfoHeader(); // see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517 @@ -1218,7 +1233,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.infoHeader.Height = -this.infoHeader.Height; } - int colorMapSize = -1; int bytesPerColorMapEntry = 4; if (this.infoHeader.ClrUsed == 0) @@ -1227,35 +1241,38 @@ namespace SixLabors.ImageSharp.Formats.Bmp || this.infoHeader.BitsPerPixel == 4 || this.infoHeader.BitsPerPixel == 8) { - int colorMapSizeBytes = this.fileHeader.Offset - BmpFileHeader.Size - this.infoHeader.HeaderSize; + if (colorMapSizeBytes == -1) + { + colorMapSizeBytes = this.fileHeader.Offset - BmpFileHeader.Size - this.infoHeader.HeaderSize; + } + int colorCountForBitDepth = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel); bytesPerColorMapEntry = colorMapSizeBytes / colorCountForBitDepth; // Edge case for less-than-full-sized palette: bytesPerColorMapEntry should be at least 3. bytesPerColorMapEntry = Math.Max(bytesPerColorMapEntry, 3); - colorMapSize = colorMapSizeBytes; } } else { - colorMapSize = this.infoHeader.ClrUsed * bytesPerColorMapEntry; + colorMapSizeBytes = this.infoHeader.ClrUsed * bytesPerColorMapEntry; } palette = null; - if (colorMapSize > 0) + if (colorMapSizeBytes > 0) { // Usually the color palette is 1024 byte (256 colors * 4), but the documentation does not mention a size limit. // Make sure, that we will not read pass the bitmap offset (starting position of image data). - if ((this.stream.Position + colorMapSize) > this.fileHeader.Offset) + if ((this.stream.Position + colorMapSizeBytes) > this.fileHeader.Offset) { BmpThrowHelper.ThrowImageFormatException( - $"Reading the color map would read beyond the bitmap offset. Either the color map size of '{colorMapSize}' is invalid or the bitmap offset."); + $"Reading the color map would read beyond the bitmap offset. Either the color map size of '{colorMapSizeBytes}' is invalid or the bitmap offset."); } - palette = new byte[colorMapSize]; + palette = new byte[colorMapSizeBytes]; - this.stream.Read(palette, 0, colorMapSize); + this.stream.Read(palette, 0, colorMapSizeBytes); } this.infoHeader.VerifyDimensions(); diff --git a/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs b/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs index e39a2af0e..661275fc9 100644 --- a/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs +++ b/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp internal readonly struct BmpFileHeader { /// - /// Defines of the data structure in the bitmap file. + /// Defines the size of the data structure in the bitmap file. /// public const int Size = 14; @@ -69,4 +69,4 @@ namespace SixLabors.ImageSharp.Formats.Bmp dest = this; } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs index 4f862d929..3d7510bc2 100644 --- a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -22,7 +22,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp private bool IsSupportedFileFormat(ReadOnlySpan header) { - return header.Length >= this.HeaderSize && BinaryPrimitives.ReadInt16LittleEndian(header) == BmpConstants.TypeMarkers.Bitmap; + short fileTypeMarker = BinaryPrimitives.ReadInt16LittleEndian(header); + return header.Length >= this.HeaderSize && + (fileTypeMarker == BmpConstants.TypeMarkers.Bitmap || fileTypeMarker == BmpConstants.TypeMarkers.BitmapArray); } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs index 6da5f73e3..ca90020d8 100644 --- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using System.Buffers.Binary; @@ -51,10 +51,15 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public const int SizeV4 = 108; + /// + /// Defines the size of the BITMAPINFOHEADER (BMP Version 5) data structure in the bitmap file. + /// + public const int SizeV5 = 124; + /// /// Defines the size of the biggest supported header data structure in the bitmap file. /// - public const int MaxHeaderSize = SizeV4; + public const int MaxHeaderSize = SizeV5; /// /// Defines the size of the field. @@ -272,7 +277,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Parses the BITMAPCOREHEADER (BMP Version 2) consisting of the headerSize, width, height, planes, and bitsPerPixel fields (12 bytes). /// /// The data to parse. - /// Parsed header + /// The parsed header. /// public static BmpInfoHeader ParseCore(ReadOnlySpan data) { @@ -289,7 +294,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// are 4 bytes instead of 2, resulting in 16 bytes total. /// /// The data to parse. - /// Parsed header + /// The parsed header. /// public static BmpInfoHeader ParseOs22Short(ReadOnlySpan data) { @@ -406,7 +411,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public static BmpInfoHeader ParseV4(ReadOnlySpan data) { - if (data.Length != SizeV4) + if (data.Length < SizeV4) { throw new ArgumentException(nameof(data), $"Must be {SizeV4} bytes. Was {data.Length} bytes."); } @@ -457,4 +462,4 @@ namespace SixLabors.ImageSharp.Formats.Bmp } } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index c4dfa724c..a95703609 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -343,7 +343,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } [Theory] - [WithFile(Rgba32bf56AdobeV3, PixelTypes.Rgba32)] [WithFile(Rgb32h52AdobeV3, PixelTypes.Rgba32)] public void BmpDecoder_CanDecodeAdobeBmpv3(TestImageProvider provider) where TPixel : struct, IPixel @@ -355,6 +354,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } } + [Theory] + [WithFile(Rgba32bf56AdobeV3, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeAdobeBmpv3_WithAlpha(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + image.CompareToOriginal(provider, new MagickReferenceDecoder()); + } + } + [Theory] [WithFile(WinBmpv4, PixelTypes.Rgba32)] public void BmpDecoder_CanDecodeBmpv4(TestImageProvider provider) @@ -429,12 +440,35 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp [InlineData(Bit4, 4)] [InlineData(Bit1, 1)] [InlineData(Bit1Pal1, 1)] - public void Identify(string imagePath, int expectedPixelSize) + public void Identify_DetectsCorrectPixelType(string imagePath, int expectedPixelSize) { var testFile = TestFile.Create(imagePath); using (var stream = new MemoryStream(testFile.Bytes, false)) { - Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel); + IImageInfo imageInfo = Image.Identify(stream); + Assert.NotNull(imageInfo); + Assert.Equal(expectedPixelSize, imageInfo.PixelType?.BitsPerPixel); + } + } + + [Theory] + [InlineData(Bit32Rgb, 127, 64)] + [InlineData(Car, 600, 450)] + [InlineData(Bit16, 127, 64)] + [InlineData(Bit16Inverted, 127, 64)] + [InlineData(Bit8, 127, 64)] + [InlineData(Bit8Inverted, 127, 64)] + [InlineData(RLE8, 491, 272)] + [InlineData(RLE8Inverted, 491, 272)] + public void Identify_DetectsCorrectWidthAndHeight(string imagePath, int expectedWidth, int expectedHeight) + { + var testFile = TestFile.Create(imagePath); + using (var stream = new MemoryStream(testFile.Bytes, false)) + { + IImageInfo imageInfo = Image.Identify(stream); + Assert.NotNull(imageInfo); + Assert.Equal(expectedWidth, imageInfo.Width); + Assert.Equal(expectedHeight, imageInfo.Height); } } @@ -465,8 +499,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp { image.DebugSave(provider); - // TODO: Neither System.Drawing not MagickReferenceDecoder - // can correctly decode this file. + // TODO: Neither System.Drawing or MagickReferenceDecoder can correctly decode this file. // image.CompareToOriginal(provider); } } @@ -486,5 +519,26 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp // image.CompareToOriginal(provider, new MagickReferenceDecoder()); } } + + [Theory] + [WithFile(Os2BitmapArray9s, PixelTypes.Rgba32)] + [WithFile(Os2BitmapArrayDiamond, PixelTypes.Rgba32)] + [WithFile(Os2BitmapArraySkater, PixelTypes.Rgba32)] + [WithFile(Os2BitmapArraySpade, PixelTypes.Rgba32)] + [WithFile(Os2BitmapArraySunflower, PixelTypes.Rgba32)] + [WithFile(Os2BitmapArrayMarble, PixelTypes.Rgba32)] + [WithFile(Os2BitmapArrayWarpd, PixelTypes.Rgba32)] + [WithFile(Os2BitmapArrayPines, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_Os2BitmapArray(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider); + + // TODO: Neither System.Drawing or MagickReferenceDecoder can correctly decode this file. + // image.CompareToOriginal(provider); + } + } } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index 178e652ae..7412f70a1 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System.IO; @@ -14,6 +14,8 @@ using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using Xunit; using Xunit.Abstractions; +// ReSharper disable InconsistentNaming + namespace SixLabors.ImageSharp.Tests.Formats.Bmp { using static TestImages.Bmp; @@ -262,4 +264,4 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs index ab72214f6..da17dfb98 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpMetaDataTests.cs @@ -1,11 +1,17 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System.IO; + using SixLabors.ImageSharp.Formats.Bmp; using Xunit; +// ReSharper disable InconsistentNaming + namespace SixLabors.ImageSharp.Tests.Formats.Bmp { + using static TestImages.Bmp; + public class BmpMetaDataTests { [Fact] @@ -18,5 +24,27 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp Assert.False(meta.BitsPerPixel.Equals(clone.BitsPerPixel)); } + + [Theory] + [InlineData(WinBmpv2, BmpInfoHeaderType.WinVersion2)] + [InlineData(WinBmpv3, BmpInfoHeaderType.WinVersion3)] + [InlineData(WinBmpv4, BmpInfoHeaderType.WinVersion4)] + [InlineData(WinBmpv5, BmpInfoHeaderType.WinVersion5)] + [InlineData(Os2v2Short, BmpInfoHeaderType.Os2Version2Short)] + [InlineData(Rgb32h52AdobeV3, BmpInfoHeaderType.AdobeVersion3)] + [InlineData(Rgba32bf56AdobeV3, BmpInfoHeaderType.AdobeVersion3WithAlpha)] + [InlineData(Os2v2, BmpInfoHeaderType.Os2Version2)] + public void Identify_DetectsCorrectBitmapInfoHeaderType(string imagePath, BmpInfoHeaderType expectedInfoHeaderType) + { + var testFile = TestFile.Create(imagePath); + using (var stream = new MemoryStream(testFile.Bytes, false)) + { + IImageInfo imageInfo = Image.Identify(stream); + Assert.NotNull(imageInfo); + BmpMetadata bitmapMetaData = imageInfo.Metadata.GetFormatMetadata(BmpFormat.Instance); + Assert.NotNull(bitmapMetaData); + Assert.Equal(expectedInfoHeaderType, bitmapMetaData.InfoHeaderType); + } + } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index d041f4854..1019a5b08 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -261,6 +261,14 @@ namespace SixLabors.ImageSharp.Tests public const string Bit8Palette4 = "Bmp/pal8-0.bmp"; public const string Os2v2Short = "Bmp/pal8os2v2-16.bmp"; public const string Os2v2 = "Bmp/pal8os2v2.bmp"; + public const string Os2BitmapArray9s = "Bmp/9S.BMP"; + public const string Os2BitmapArrayDiamond = "Bmp/DIAMOND.BMP"; + public const string Os2BitmapArrayMarble = "Bmp/GMARBLE.BMP"; + public const string Os2BitmapArraySkater = "Bmp/SKATER.BMP"; + public const string Os2BitmapArraySpade = "Bmp/SPADE.BMP"; + public const string Os2BitmapArraySunflower = "Bmp/SUNFLOW.BMP"; + public const string Os2BitmapArrayWarpd = "Bmp/WARPD.BMP"; + public const string Os2BitmapArrayPines = "Bmp/PINES.BMP"; public const string LessThanFullSizedPalette = "Bmp/pal8os2sp.bmp"; public const string Pal8Offset = "Bmp/pal8offs.bmp"; public const string OversizedPalette = "Bmp/pal8oversizepal.bmp"; diff --git a/tests/Images/Input/Bmp/9S.BMP b/tests/Images/Input/Bmp/9S.BMP new file mode 100644 index 0000000000000000000000000000000000000000..c889ec75ebf2269ea5625decfc0090249d2ee1e8 GIT binary patch literal 2684 zcmb_e%T2{F5DXF*PN4zL^uP(Y0}W723ZbM|1SO<{FrRhSc0NxCEG5t0*%{BSlfdiC z=aA#|?H!AU;c@uF?=!9^Tpze@hFjc+;rmWMy4~mWa5fRaZHmbhiwS|tgjYLt_f}N04 z*N1hK4<J6Y$wKW10@oQ42q zu~&t&Tt^v<)Wj8ZlyH?=kxp=t#Ill8Q~x@?Ip3x}bcg3lV{yJ+{qCQe819??kQyRz z6`e|d3LqsOvLifOql^vz9B2BvHw8NWHC)eZK1MB{t)YOTJO0%gCdKpL?!UH%sNSCz zFRjrYe*ch={#BX8UBqwCzbai)`PAhsTDOZ=t&tSn*Z!h4ib5conEto#f5(S_$h;ML zRX?JkiJ9MTPPA2X?MFyz2|P90>S`?#YbDb+1W{uv(Smj)*L>qgbLzc>Hir|=dHSn#s{;M)5E3yO}qr??~sfn!q>(R#S3id literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/DIAMOND.BMP b/tests/Images/Input/Bmp/DIAMOND.BMP new file mode 100644 index 0000000000000000000000000000000000000000..fff96d00e63cf94eec0ce7491d222c45cd96f443 GIT binary patch literal 2684 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�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 literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/SKATER.BMP b/tests/Images/Input/Bmp/SKATER.BMP new file mode 100644 index 0000000000000000000000000000000000000000..ad0e24d2834f21d5de65e33610293f09d3752e08 GIT binary patch literal 7242 zcmeHLzl#(x6waZQt8Q;$rEp+pDdOQVjT{R$f`5Rme}h}e!CHxhApQeZTP!jXhq2$Y zJWz&lJ6r7(!a9EMC7IosyqSyZ5Ag1C+$8zl_r3R$NwPDudwW|cbszs!c1M?R-By>? zC)DThe^=d9Tk0%YYRvy*uEyw%sT>>}RKP3s_1zAt`TI&$RCd|#W0irYuDeNFo& z34P*GVQ$uWuS?6q6%)>-5S(dPJaLJ3L4e>h1G?};=LcBe5;Qn8*y~lbgfmMBc#v9g zzAO#3jq};6JWXdvYDB#j!FFNg5L_ooQhqE%o~02B^w~TS20%Ix_~Oj-*(ewQyJttW zkGEPUqk;{s3&m?BK1*5*?q+h7fZFsGm_2~(e6zQ%2hhpN$r9l%&9NhvM@P-am8q(t zGoCl3dWdCYe7CzcWAM7owI$Vgj61E(G{&9A@Asf~-rF#})|D~hd0<6887(?WY~jba zM*H~=bwk{ePVtj84?pZ+?Rt3RJ6HqxTH7~i&3y44w7;#jee*A^D{0s6+aj5O;qhN6 zI4UMOolFE1plhOLs^ClwI!>9V;-R;RCg(Xca%%eCYstVG$-vkZF*kb7Fr6AT7EOH; z{p!xY(WpZ)PVaB_p*#n@nui-`Zan$*+&0k+1C{E9dymx!bt1GV)ELdnGRz*w`7?+)0Mg`J%>|Em^KR%3GJDX_m7BVzG^pUkY-%>3+;HYQY}Mn8JNnNsVz zs+BpFsL_vJAiG>H%8wFy=_fgP*tkXH){MCW-<%Qk#8;=K09G6H-D$}n5RqHWN~eVY zh4%wMNB~9G0P-OxUD9^~kes-scAWq%-y5(DuU)F3t5sq-{Hp2N5M0}~jM zz&QZ5$jj5}5BHy;;Dh~}_P^x6jL%Owz}cYQAJzG^I;NTzc{zXrk6$-@U*VI2EmKJ; zK*cM2w2Pt}cx|6QAw}QXrvQbw@?&m!hO++JJ{n|xZ6AC1SH8Co0g`@i9|A<)lk+0R z`=QHe4dVUMv*!ST_vO^XaKDW>-H&~H3c&ZLBu4-s=Oj4{!0iE_{3Iu0{7sWG@L%D( BsFVNz literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/SUNFLOW.BMP b/tests/Images/Input/Bmp/SUNFLOW.BMP new file mode 100644 index 0000000000000000000000000000000000000000..852355224f2476cd640731dfa0a9716eb5bfc5af GIT binary patch literal 51753 zcmZXdJ!oXxdZzc_2` z&OC{y;DFm;(S0-Lw=oqgFmxigfhxG(l3>J9RC}K1{njq&cve;Iy?(y${eIU^?NXof z$N%lW4#V(2`B?t=m;Z(9{~G?saPvFE@Smyw%kaO4|1kVV2XFGZ$?b;Ljpf(B{`Ert zGAy}qr$+hX;4(76{5x;BU;g`h++TzMtWUt-?6?d!yHCSE|MNeK`+c|jI4mEB;bPca z47-bAxfq5I!{*bl`!Fo9+zp$%VRttycf;^~*nA&$--pHPvRQ_mZPJ% z59gZ?=erN*%ZKyf3q05-`t(= z?#`FH^WppX=KJ~X`}y+yd|1vm%lU3OUzYP>*ldQ)Zb0B>_^{c0*z7)RmJgfZ<7V@5 zv-`MNK5mAK&E{gWyVxujo8i-D^J%mDv{^oFhP%z?ZnL}FEO(pX`)2cfv-`eTzHf$Q zvspGfjG%&m;bw!q_~rwZo85<-<-^VJ@n-Y!X7}-C`FJy2+-xpxb{99x#mz5%@r&R6 z-QWGa-}}8Ee)!?{fB*OY;1B-b5C8BF|LBkY=uiISPk#B!Uv4&=KmF4`{j)#&vp@gy zKmUur_=~^%%fB4HFMs{lfBiRq^EZF{w|~3bExXDq0!+yX2*MI%j z`}_OD;qdhIw7XjteEW$Q-7KGOhP#{1-OcXqX1Ti=zTa%V-|W8MEZ=X2-3Cn;!b{4u&Cqs3TZT4#Xqyjh_n|Ex+VHV$KDOP* zwtQ^EMcZ7o-9=k2+VH7uKDFJawtQ;CUEAEX-CbMm+VH(?zPH`?wtR2H(l$%mEp4HK zy~raZNA3ESrmEcd;xN%kT;REW1z3@@X0Fmd)Mr z(@#JB-QWG)U;WizWtMO;DKkqlQy!1o!|`<<58H7(93CGZw~vSP(cF%gIR5dl-7>V@ z9=F@&@py!W>+#W{$HRPlg<#%3K8}ZZetn!7f^d9%Tpkxl#=`{7)4a^%R-ElPKOQH* zCNYq-osU81LXiagSsA<+u#b7YM&@)_4#&gm^tc_Bv%r2tdnHn)$NOdbxMhVqD%`)YW@0}3?9%kB*Y3ToTBFthJ}odFdUaBeSqg@f&tFhy)mQ!0;o-}jtD*;Cm>M#xS$K*2xM?l&^;ai0z#lr1(ya;EFFia@p{~Hr3DK1 z;5_)jJm3lfAuvry@%-_TN@$=~W8~q6$0s<6kLB?=zv8>q9(6He8QC5T+Gb|vW!@J8>LWAaxq8piu^!T;0t^)<-I z6d&K9v4%Y{EM{iQ5m@zvOHR~5h_TUwD3y#>nj*{232m@sdYm3v637-_Fs2;fV6BN_ zWsl)x*fnB=Br52LQJuXQ1D$3jQK&G6QpTJ`WKuApWdY-*0TOeWoWl5s_!vkhj2?3; z0Vz~hnWjBTj@QU*XuTe;4@@kk4|5;-8JfTKSY$pgGcnkXpt;3=p9Wyy&H#IoQnoEmuj=%V9zyo{CCWC&Eu z93$r{tZvv7r@LB%h;`6BF$4f4NTx6*o`i@<=BYsGXm1T2v$Z(Ya2o`mz^N1INSZK1 zU}D}s60OI_`#ySPw*kWVm_inKMz5+vPek_%H|Hq%u8mpS$T{sP2(Cwiq@j5oZ|I6i zFvMksLqT{!CW>}5lu<7hR>AS%uzfVB3mb6J_Jtut2h;4xdYQD)9&$>*VGr;sA6PvS zo3=1u`a3ZaZExAr$t}#BSxzUkJ#MMPwCX}~We-Boak_V=CvFV$Mid1TBZFC@rV*bI z)zpB9P+V`5v5&7=Z<(aZLP`P<6w_E#c5&9xM@&>LDY`OfrFV?2@)%JWE>a;E`L|c2 z%E)0rC)NVyER1AiS;VsE0#Hosr_izrhMOu)t

>P&~3#%8J3|j`WA?>(b^iTfLSp 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 rr-AJ>OvZ2tHpVZ z-^MRWJq)y221fB@gc_49QdiQPwKJ4z%g>C) z7sI;((B#b>YE!+Z0l$1y)-u2Y0>1a(d>u+RckLP+YW4ZuFt+|rWM?90BJ9Kn`jgY$ zq%sRiD9Se!Bvopsk&;f6@@!I-ql0NKN-&HX#Vk{yd!uyKJU|!7%cDOsO4gX*! zBO9@bX@hvxyidqF?<&&10UXe zaFI|N{mUN?fA!OCP3(O3+u>pCQWx(3cFRALF#ofupUne0eKjUvT3`vB+%f>G{$EVU zGRyBD-{Uw-hJSNq@$sErgoaj{1&GEpk$aQ~{CvfD;hP;8Rx}yIxJcNSt#yRcM;{Xb z3Lh$J*~cc~P0jkF+Ai%Jir`T>Am-wG;U6gI=9-V{RTiZ$pt~ZWg*Gxx8mF2g1J^iv za}gPTg{qu8|eFv67&VDfh98F^*6le2uN4M&Q)LGbw45m6l$e-{*-% z+6O+7s$Slj@So4ZuM7RY@4*m612}e9-<;fka%xxSEvUafVdu%PgOK3%-u&mE``04^ zE!{#guQ%BT_T%CH@%`iP3p}^C49lc3&kQ~uzUu$@_?G%rxoSMKtKLc9R?|j?c;%*t~{!*C1XAtw(3?iYEOsUV^$a$A$9u*bmUA!}`(J)P? z=6$j{yhzV(0EoH)cL|9L{cG7t7HwoJueLN$xv(g+JBwYRqF}RysM1Twu^?O+6KP7= zlLcLjre6QeC;lA6eo`~QhV<((&1HWrNw>dtH7dCi&E3)O>VBTFZ|F7ypw*+lZO#Ho zEdFW@Z;kLvSNc;?1h+ze^Vu(f`wgE18)7wn3pM&}mv`1Yzct`h8{t8zmnhXqHaXQzhH2f9at@ zXVpL+P5hgd#Ql#sdJ1zB!p$OMgM+`EHV(6%)KXFWm=og7Cfk_>0)yMs8l3p>Oo7*6 zHmabnUpq)oqpaq+b6)4~?5}&QanU0TUCRpr$7im~5xW_~eP;(i6Ii#9J1esQFkJ%p zXutjouf6~3?oWN-#>3((jpT$kH|Hh>-xtKj=Fs{4?zE@*S7!cx zUBIeAvxEtrmZ#~XML_mrR332*)wcAhg;D4?7CO+PtY!!q=}0t$Fvtu#Ccgv1sCBeH zQ80l0n8%>XAB*SRYi|+=|FYiW<+BJBE><3YQCMw;5lzXZozDu^xZo`FtV_c&6upv2 zJuz9EGt={5Uxkb*$5q)>B)t|joQHzQB7bwjC;S=#(vr<-wB9bz$ z4rXuF=8$h6O(FVI%f$yL(M10kJw6?rtO6?Ut0s!|XhX>?(2hZqwUysoBJ6R^02{}S z|9KG2ES0O_2XJ;i<4+r@V)niyvdt<}<3x$bCs8EuZoiLy0}ifj^f;Dx5D)S)9?zkC zdN&(PXx^ABQmGMghY;nwnI&Q+^*f*Qu&RslT{2SE^qOeOUSmhQ!D@ipj^ojVD8?n7 zq_<)k*qCrbgoOH>m~g$Z^o; zQ~beT`~--zQ?8jR`tY~o|3324^Bv% z`dN*q%Jqh1f!Y6rI9QRw{ViiM0d%t{-&fNTFbioVpvb@tdIs-QaHx`s1mrP7bwz;` za&`A+pJ*c7g+8N^o7Jxx@?!!(9juyntO@c0Y$lLJP?h@Yv3z!u_7tJCq~TZUP3g`B z{%t2C!rp|>cS|L8gYomO+k0x99&2s8PEV~{)<{i~86mMV+{8?&@i#c{th(W)6sqpC zLC*AsG}>1pGbFjOZ(jeKYpvshhK1$t+}Sg|n;5#Hdv0&W!yV%Ny%u!u;QtmXZl}cYvMW^lL?d#lf!xJ|qzl4O4%|4`080`SSGqRbOU- zhqV9VZuqf?0}H_TXl@wb8yM)d!=JVQM&ecjf`88ejvg9$+0LmXV{r;|jpS1YZDbsy zqph1%CyQm;23$4}mIEWdSX{1fy($al{sd}yt2>8WR}R^a#@2&4u1F#VUXdC}0Fev9 ze8b4+j_j4~8rAJk5?~QYhvT=&8jY=Da<4HfI$$It^caYgcH5o}zC`&&b9kf1!QYQ= zu^(o4ozh{Pb3UX;D(Kgj>HPeBZjx_f&O|@+|JgpwOJB&Cs{+O|mAe)B zS4PsXJJ@x@m20?v&ugdGH7nDTd%PaFw;OMgw?WUt1E;{?{hOy}Yq>{O&@K7Hd;id> z3jnmU1JJ(jA;eI$k^je=S1k{ERM3oKqEAf!S}b0--?y*;F^s*>Z4zgl0YulZd+~F8 z-$2;K1~v}~f2Wc8rCkNfkme~JKCl{<8P6EW^e_%HK0%>4CO;h%7NqM3SuP_rwYX2I zGxem*Od=yu?-)aorYg9>pudZCT|V4pe-C3oPBEC8>Lc^%(%Kn;b)b5Gm)jp@RmQDz z`@>Sh-DfpfMhSUzBY+o{$o~i{L35bz{9tE+8}#SFS`23-2bT#yJpha^cLV>}0~{bb-u6Hjgf@}AnyX+wZq6R@a+QB< zVQ7wN&tTj$Kh_m+zBBzCdhp8%GkFOA;?8pLjo%$`letyM`SCm*u0cE@jj7XggdeAb zsA?rFA-e0}CHvQA8OW_dULL@kEX$d4#SBAs%xcO~JM|AXgJeE^`C;1vB(1#%dB|N2 zq^q^SRtcp25V$t@47#UE=b5{DFNZ;`GmC9byJI!5+dc0Eq+Dpm>i>Ocr$fxp&(icX z9zOFpsaaXr zI4BMQJRyE`51keGazivDDb zyemFkw4*TeQxk{K?A=rDtA@MGBOSMPBKO{r^w`l1bmU#L$}^&d;>g14MoE3;C}yWR zlt=`fPt4nMesmZ5>+wJg&jY=lIiv7TP@?)UcK1)qHFJz_w>&h~ISr$u32~Gq0PIj|D=Isc4EHY=t4oTAU)DH0|vL zhmYot8phGg5-lH0SeCVKK$u#{ysmn zG}sINtkOYL?M?SxG=#9;N;;ORl|41Wh@etOI7`ej%hNR7Qud?1WV(P(Q-6SEo+MD&y{Mul0GM9&IL%Z=SqpS~{} zcWydg!P7@qV`1*k1mPxrGyVnfhADloSeu2wySIHR1lM4E^Wk6r_22jLw?F-Ujk@~R zK3Qp@pn|c}@J)m%0et0haooltyXqu!RyI$z8gEfHCsa5mSDG{bBh~KGoDY`0v%|;x zO~2#s;&Jn>azHs=9^VS@JsrZ;{lEu^=uAM@{PDdY@bzgHkz60jOyT&^hOjPA4aDc2 zb%q;EE+vo8XZr@sfdBD8Y7QJ&;4Qv~_3_ZGqxi>Wrw_%H?gB_Zp5Ht@3j_K|`m84d z%99(XGyOO(FvoL3gdV1NdQ(zv3X-jGKrucHs8P>~AQSSY$AB#?&ov+C1?}vcE6KMP z2qGyZ3E*&_NjBGXsnD|`iY|yx;dz>+|46C$H@||vP2lt3sdGn~L6#P0SmZ9fO;_1! z3`MvZ3~X0GPn+gJ`XIkQ%yyeG{ZpKcZ5iO|8y2>6MdbI#7Ur(;=Vy4JMtgx_wzal< zb8Fre04(niJ)V72+c!I393TH#aCWn=|NO%wI4?J6Cp|3oD8B2yzRA=!Q(^!7$xl1E z!qWi0_3~@@?q`KQy!BmEj~k#oKK{~ECYrqc&@$wpCxNBkp!;SP^29N(4fj}t{8)pY zsEugMVFumT?TQNH6iAlxBns!0QvfOgkwrdcq@5~U+X9-WHMYBfe&gK^UTLgDG?XXX zb_blhth(ll-J2xx{)FB@3N=06U0wh0AOG!2hO?mrm187rgp$*87dNto*Z)^(U+_PU zus0D@YZ#kL4ITgG-~aY6r3AS6-31_=+t@w7_2oVO$N%ZWPdO<00t_?5&7JxubN>g3 zeB+4zLHCQ7|9BRazrA5Ne*y387FZo{-^{=c-iS#CQrO9dZ`(Q9nc3m(W~=aj~wobT)qC`^5XXVVKRUF{ie(Vr%C70;bf_72}Nvbu64GG4RT{ll9ME&^1?y( znK1Rd)ZG5V|NZtK|5joa5FYX4Y3<@d?d<9t1Sapp1I69?E{~85>BHd{>qP&a$Fz*L z-+u7F9v&}kc6vO4HFplK3<-QoSM?g)E3L^*4+(;l zPSLU&DoMW;W;*Fs#nz+7`TiJ0+FN0XKx*cHWfU6dY1e1R5KgJ2qUyHo_}GsTR8f`6 z-O={`&urv`_;NQE@V9!5QNt3@Bb^+XXRVN>@lXH$ zux|hM^5!?c{i6yqRowb*Ct44e7IPAG`}BV7-&G;(Th={z68|Sg0t0sP4o<*$`SLsU z{+`EbT%UKb?(xv`*{%Gi|9$sP9*VvBdbGI<*M3U&>3!ena}gm@JP|e=ZdR7p4+ET& z@XHdj3)&fGs6 z0+iK3KhSG6Een#FRG~o0w8_hj!qq?EQtw!S>?MvBD7u~6P9;h0m>Z2=obmy%-%v){EJBaamSdB&zIphrOS1y}@i~>=9L>W3JDiUXw=dpxgD_a0 zkI&Da{+R`!;e^j!>S>a9M*8^P41nyOh7YYSR6# zQrpPBW@vSA`1sDeL&DYx=7YattYvY*jfFRQ>-_1VNxLn8Ch>uv>xT5!9Ry)af(Ao| zqWQpms$kEj)#vV`u2FOHZlz~f^RYb~_~#o7 zJ0C6>Y~Zba?C&cYA>r|f6}4+)VnE>K?$0d$lAAo=H{th1(Vw!Q!`pr<*bhJo70l=B zzx;HzF<^Bdvs(lEZ2s3PwvWfpo-j+eXPXd0$K$tIB^+J@dglM40Jyrkw-gxEbK&jX zsV0PT3ghY*31?|kb+UE#(H6=SiTpe$h+0r{jZ=v^8m;Ytp?}s21FW=ve<2j>vP?97gLM=u>wrB(xMK5|!ubuw% zIU1?!^`egq_kr90_g5Exy!nS;e*5`Pw|>M?_;)pOa~s?y<3p&=kM4@y;MBdFuO;c- zotz(T?##MhVIUNTxF@n6Zf@@E$Rg^3A0rMt{|v?jJga&=Lak<5mU4FSz;K=r;n!v4 zL~)mr-SB(<0}gBk($5wX(ABXGf;&Gw{*2mXM-zaliKwFg{n4thXU|~W(hi~>G?pW$ zuhQvAfu*skr9_25L3!gX9`24XsCORvo*<4cOBwAGJ`D@@8+5twhAl5&D*Y~q1l21< zq|R`CR@zbxxO-(@^qx++{ ze@6#*e?9^w$PfS2KXARz&*xhoVC07u0GSVWQ~}fM=6GlZ_tOybH6l_GKDFQ8nXY}y z2Wo?3R(C#T2nC!Y%fRPst*@cE;SKxx?7Ln+$jq#woq(W`_`n41IlLKzVS}w6nL&OJ zT&}CX3<8>xq5}IsM1Mty{jmc?q+K@^8q6Tmu8&#vyC57>m{}XnG?vmf#`bu^syFC& z1Xv3L?j8=s;cGq1IBf)VH1<)4H!uIwME_#?&^I@vtTnU3f3;)A7`Gs(JGNyrUUa7h zFkJO{`(OSBN-Pa}-TZL(?!*7r@58?1|6Kh4_O}loh(BuT7aqEepW12ot+PvPNc<7E z?*S`m2JU+B27b_Z>;L>%@jaR4O%gA=GCMqboGa_VMijAtXg2vo;AUlF!ou}~Uxu-2 z@GU=-abhdq{N^jP_4&r{1(-pAI}aR~+*zYlLu5Vn^|5Wp?i(BqbAQ=Ah&LHb4-tdC z7o0;qwdCc1R4|M9$rlP*BPdTYW|3V)I9L9oR@r2(bngcUf(tUf!R;OZ&u>1z4D8O1 zHLpT~>A*V92iMfZRG>7^M^Y9?Q%^~VpV&F*I1jsDH+i~tN! z91xp(Z~h;;?q^4?B)juG38A6psv{=5z=~BZXIlv(;hE?~Jwu`vDM1T8!eoF$1Ov5T z5eYRjSLFuIjHg2jJw!tw^j0F&>SV1rpYJgbX0}>=-Tk`#Id<&W`5im<=U%`5^jTPD z683r?Uw;!2JUDZJpHbfbGd@DCnAvy_g9POr*KNJVqnyH_Zjyzr=6@%|5Hs)R0=}9p zB8Kvg1Nzd`@c!=ir$5*MVj2El)WZf|e)aid{~BdpK&lrbNxJ~;9<>Qgj^?WFRSEmB z7T_CA@q;+eGt0s0JWQ~tjUGMcNhphPsVrekWX2Ft$>}`Lm|K8#+=|{P4KBc?GneN*YNN>75pN z5}a@D?!JF>cN=?lcGQsHnAmBKs`eJb{|x#sV(+h?{_E-G-StmKM0?TN^z`t~6r4K0 zd~4nI-}=M$y7aRXo3IR1Sz1@v!z?3uFf4hrkfCl(>|-8)%km&TEIcMRkH?zjGVsHYDx zn*Wj{?h9;78VUMC-Jf&#R?D04)o*q1!L3S1ZxU9RdhedJ$Au*FhJIuMG01H8QCNwY z20}zv-YBnt4p1M{r)5JIWNi?hCo#(?Cyt<@;4Gvwdnq+Z8cK-#n_zjJL5wROWgVkh zkAGd(9|;j%@-0Lj78vEayL9gl){R^C$5+4p_?qCTuU=L3e}BBczIkCUI&+XU^V>$(0O;KYQUVTD#t z4$yCFD!~&HC~5%P!BZX#Ac_ul{tD_vEUoE(IDGRrcP#<&HMu}@__BL~P8>gzdXXe1 zBZsW*%NOr5B7(V~bZ^+7DS(cgA861wBcP7VuFQl0b-h2>a|Lq>bXG&H%~6%k2owo? zx=*7Nehw6xGL_Re%>?yR6ZLWOEJ2QUr*r-I+U-g|i;U5zh^QH}ec&{@F7cwgDWdiA#6u-${|? z3C~}C6^nPUzE9?Slxk@A>FMqr$347F84lb9Hhw{17GUIu>$}76`Fghr8t3y#W{@{_ z1vmp+R31P~7`9Q(_kZ}tdeem=xzC^9LT_UqveVn?t;LdMRt`Qpe?U1W;VD04LR*I# z)do0gN#S+6vYSuFc02#`T+s`jrO#&qKw|<+Qcw@p@X4t*p&U$QsyU2MO?P7v=|dgA z3lbO~S965SN>+iRy8off+vCh;Y7--p%7@I7q0D{!wEfc6Uw-`I`bgTF>%V=-`uD&8 zjOgk2Z?0Hl&8Gy~q(zVU_;L5V(0B%b(-*dXzJdXL^Tp9#4*(prl<&TI*Bx1(_qz@h zP|1$Ux$}oz2l2ZjiINHg8s=K@+ZU4CCODl8Br0uQ_q;`a_IAh8-eGe(IGF(Sv^cv4 z)#;`~V@p#<(*|2k>}7r}_!WC_ZMYeLUOnhhtqQx)Hb=^nG98)@X+Fb9|7Otj^@$Yl zp5*vcw55cUQ9k`^K|lvoxec8Voy6(oWzN>#YV(I9VEAi#KKe^(G|J(0RBrHjFQB&c zv${vhtto<+mEligizu$2zWh3|-Elvq{`5T^?>(KFB`n+!<9&7WyP^2so}y1QPNhyk zC3o*~#8ht$_pH0KjQ(%#tj2Hsz@r5}oqOUNJv_eFSL^y;exvWcbEC$Wr`tgYd{8oM zTgoeM0MD7^yDGJDai75(_Yt&BptLze4*~4Tfg#4AZeqcCe8c(AepDounD&3#ek{ze z)Pd;gGa_UhHYUhzJK%7u^UfS_Jp2>ScWNRq)BHTUy^z+2bs^$RuTHFsIn>7!(y@nz zEp-fLc1XKa7T8=sLwz%}v!s6Wd0uJJBuui4!fW^Roz}cytfgoSWJ9UST!k5kZiTu$ zjMLcUYl*JnM%av_#&Yc#^)afBfG;zgGo6X%Z9u}2fVc|Gn-T7$<@sZgEE8BO;2@ELpL69cVk~S zX937Ko{xsv3o>d~J&>x`_1k{eV?EjA@{sR9d@_2+%d7#W_l(f@36nQp2>P$LtDCIy zAWTZ6cij~9EBgzqraMFZTU_@P&P**I4&zKN_*X-Lu2#4K!tVn!V(KRt(Z)1GTqvL` z&>(;?chP17w=zc4&>q-Y(ojx+sC`WLYNCaK^bQb5Av*E-1E;fIKXV1NWhtYwSA!FV zrIuCzVdcyp2LJymOyEbRiXTuunT>((zgDlV&d+2HAHL2=;6H6YnhE}U$MbC)F0c8^>#L{rSO(K-zv0?u&Cx}| z)4NmSxo)X&_QWZ>M5qou=(26%PQDX%?+~7PLL68AZcw$2$e+J_mihgYzx-?YXM~uQ zzW;i9O1L`)p#6x)i@ivhF16p&ujh- z5o{aq4an*pelr$*Mh{2BsT(TZf}t_^`E%21q5E6of7gDph_C2~1SVZ?@4}IX&}F~S ziT4BmNvU^-e^lT*Gr+gJRCDdAM3u%g_QiCX*tI&~@(<59kS;Rb>&(g+0qi0mYCZ{b zdm&#M5p8bBMRg{}jX3ZcgsI?kexhhkpY( z*!2KM^{t`VC;NBkHjK9yoBUlJ_enPMQ$!sZ(OxM2bxrtBA8$2QXnT&BJ3jpM=K25q z_~@3`5r_ZCk0fTtc5Qt8XwmXb7d%*`e|h)vbpOtl-?fRryZYWcw*$;VsomgrMt6I_ zZ{K`jw7n>9PaK5+<0;$&|Ciu zjFEb!IGKkw1%2Ahgl}^9O)g=5H!k^((Crggk;L!$x7|OGBYXgRlmXK*0kvlpM+lQC z%pDA-zmcui%SE@H04B2?SZea>l|@OnN30V?A3T01<+21A_}2!BM(S^$ zo=#m9`0+GPaaUoFgYbsoyZ#9Dc{& z%_g({vup6y0suEx1_66uAE)*ozR3vRW*`PBrcs>-&wj-9?Y;gFmwn^m-Lr2H{cx|| zVB-Xu<*6;`vVa~u-bEh0T`Gvfx%{Ht7%8|tL}~(t*z6P_+PS!Gd{;mGx3=FsJxvet zY~XCla2_I{h*NWRc|T_zWE1*+#ts z$&aV&f!AX?pWPexKhqBn&BzYl-PX0P*HeA%a5%lRXV^R~MA!8df`5F5%sv4Ze?V|& zy~akhRc9_wbbkp$ySw+tZ?^%G*#9~#IaRtc zmOVfCc+314|tIy^PMf=o-T+xkO0fDkuJuSk9PMSlj<9prAvRU)6v zJyNp+j-|P9_YUrktK+KO<2M{jhSm?> z!mX3B?(s+0iMn#xUDK@GOh$GxzJj1>F1tuRABB@&_9M4tKnJ{tn1J{6?diw$>oO&V9^mysq_Z#_ zAe*MkL*qPN9{j)Bc=7E#K|7SCm!j0bl z;|2d5jMBv8G0>Oa*%a*p`L`MACGwM+RI{g~HLnR}W5a6=wE;x%n$=+Nv0F&h-DCbC zM_Fn92BXg#juN@sTpU11sm5)0=N)vayLY*R(_IVyyYId+@SfiJsRbDq_R?+tyB)95 zm;Mi#2Cq=^{pY+&He91tt8U@ymV6Y~@XLuTlAnCBO@Q&RLUVv0%{8&aRMhEKg-`uh z;9&2+8w3nWs;Niw=~s{b11iWrV|wjfNZ)-Icdt23FhQoV8(Bt>Y>Cj2K{fCZSJ`NU zi`ZT_U$wl~qA&R25?0&I@2j=vqBC-r9mPuTEGC#G7&*=%1>sJc*^K9zzyKz>vM^tL zAGa8n5#oJP+5hV>(oP;j$xN!6(em~`5qRzZktDHs{>Oh-;WS*w^D7U{G$zUTYwbgMu#ye~8CSPhEZcjmd`T`nyo~gcB+~KXq1emq` zzPf{(!>8FUrh>Z*-Yk}me5crGVm6`c>(93dxbI8P!l0=$9W$*j{Vne2fQ6RaJFj`Y2 zT2oZ6KhA?>m{RQ-uyt2db(YIXXSE-m|E``pw6$lTi+mwvX>gr)Xk>ywAF}k$BrT z83Au=J>PX{PqoHF5&%Au$#-L7_p&fyD{L5YT)yU%4Nq{#*e8C63(D}WB z$MEd<3zb{_nR#^cfv1+&pP64rRWz;drJW@O=)|plL%vj}%(1*|w$z8yD6Cxa(ey?WbGhRQ{^^H5^ zVFAy+4)tA4?R8Xj*Hb47$>W6lEGqbkHqpmVJn^?;#pZXHg{Fv-O3#c8J}4Gx3s8T? zAZk#r?Ai8Djg8>E1k4OjiJnV6UrWEa^3?&IIrRTE2`f|?z^ZQo5y#(LXl}FIS0b~) zi zzuj4v83klmkxRN)RzceRX8f=X-qSlXL>sxYO20THpwwZgjqAj{x_#hPh#}8&Sysy3 z?Fg>2ZrrX4af?dN_uz|MUOxEqZ;E{C+5q$5kYpd;85!`|gG_@%|3>ug@C~8wUjBA> z{v7(ghc{0%ehZvxVv}utRebhD_={D5&rdckKuS(vemP9AEKMF|1uAuS4C>bcefB26 zz=tTKxIWi5c@G}D?f@%&#oWeD@AZpj;*-8PDlF#Z8w3xwZebav-aA? zxob#F-QSxTG%ReR z(#7$`IHw@TnHV^-(HwyD4Dg#Efp%izp~*uue~=z?}<6m6@(qw9s6@WXUI7tJD4MufxC=rOqd>?8iW>_<%o{}`8=kV8|+iz_Sf+v~?~yGpC48QXKW z&M)5Cdb{iJZhjQ59#E_3De|s2yz~g8J3B*T7c;jN zHr+@+I6DW0YO1cB66bG%lGa;K-_|lssL*lSk^6r%WOw>{du*JNPNS9+&mc4gpox>+ zV88~B@_ivOB!D*W&NF?wM5F(Yds>SM2aX2N*gpEy|6L;7^Tpex5!F3ohKXR$5Ei@s zPmK*Wfc~|{N}(I)=9sSqSK+M$J)={JtZPIb;X!uhZLa zBd?K{g7v>tSD*9b zw|BqQw0d8+pucs$fN{o~9h}Vn%*xH&b=Sv_{-Uwp@Wfo*An>he927$myTwCHH6RRL z6+NnR2_f)ognU%yI#nT0ahqWZ3%|+FL`pl;%SwiV zbCf#qC%@90=a|bo?y9gD-<#z0gj3v_!OhVHyT`C>_P>_m3Y$qpk zt!@>{EO3lN6PY58_GG3bFpeud&b;rP<(EnQ;amDJ82p#J{+q47X21Pl_y6veR9Pm5 zT_%_*m+7CHdJzha>6JED)t!wACV*12=yImR+gM$J1J~oWMiG1=1e|6E@k2Te*uY@K zG6H$TuvrRmtX04AdzrR*nSi!j-~E&QiDY!LeLedEn6$Q&Unq{=dNZcSJj9qBA(CT~ z%fB?`>hY1S-T^b8iJcc@$88to?t`ZH^tpZ&wAKoNMc;iLGZ<|;Z)87y zd_O`+j4g`#(kiOM{P;k0tEuq+*KVXB*17wL1S+ztzok`>0)zlQQ zsjDJQtjc8rM;G*3Y}KC+&;RM}h-2>d-bDao`;Q*cX9e)h>HZdobuE>`peMj9@wx42 zjl)MB*iJ**=F1GY?sVFzn1Zv$8a53Tl4TAEgcD+?E1IM9n$UagGI=#o$${OEU2KTcjcGQ*74QaDY}Fym`!fGs#s(* z3DCE-t(6^+>*r7(UDDzj=<@B-ML>Se2xK5`lw~Hq$}5rb^~`;|PX$>`EKQiX+^06~59Z;H0l2TxU@4blp7>Npm~O5`4#t8% zy^=#ReYYj0QCP2RWe1JC>4k{cKC-gQ71`!}Zgb#pIDOH*9*zFJT?INlH+3;dAW_c* z%hEGPWsiZbJ`D}`0KPmDXZm++re|i3YN~-V4WODz;*$7V>A^!HF8~3`_|DaPH^!GZ z#vwRFI=_R@9Ea+BH;D> zSOC%QK7K6**(?#&YMEiwNTPkzT5a2cZDYCyd{5#~|(rC+@_y!Zl4ebo}y!a{~kR zc!f}x$qBHH^QfIh&j4H`3a?-gXqwkMH7tqJdKb@CcPd)pETo*Ze#Sq!<{}}oRWP=( zJ6?b4|NlxB_w9VHg7Xo{Xi-X6^;5Ml*W5`sR+ql$UjuQ2%8H0$~y-1HO z;$|lIF88nh+i>r~{D98ce$~GLS&e;8F23Wq5VS+nmH9aqEp5>;j(3C;n0d!0+UKQu z5>B_0GHoA;1&_?D&bre<#!zcsKTon4^`r4G5AH>?6zt0I%6-7!=`UusPIe>&$Y|r*8FOa#Tnt*>6hjt2CQcpfciTV+{HipK;-v8>AGxu>g~(N9OA-yn+2{o*V}h} z8X(-nKpBaZb|kfTf!$^Fa&iI)M2mXE+OjS^OYoL^#sisc&k|=lD0Rp^cP2WpbC$8Y*Ck!HsNv4H%_omV362Hh)DMO3ozSDgvJ-8~P3c)Ac{_WtBzHlQ- zR~=lf_!_`EsJ=`5CI_Z0h@O8w13heO$ryq!g2jC&1bd$~a{+eLuVhcZm3GNPaQ z|3^Z7{P<^e%GymzNm@0Nr~Qk+_m3a{f9@vB)5x6m7HXw=Ygwfs``F*BPH}7-7HPt#w>lYB)F#0>B8~5n#93)4rG9ApDgo{RUHttX}ocbI~(;wik*UlDLi5#Lnt2PWpf6@QRGg~d{9RgwwUto{QC% zt?w!Bw5CJQga)+n!g`)IxSKsn$;vtW^77g5LhPYOhnnHU&N5 z5WDK4;s1InNe%5WU&sA&x;z75C~v!M>or-rlOR14ilA0A#}PcD zf06X3pB9l-Ffv9>2FCHG8D?#xf~*Xw1FiQ{PpAqsKYj z-)Giy^(qc%V93t5`2C+))1`!RitSDP>0E?OsINMwaUy6^YwZ~`Rsc<7z-Zb}<3~cR ztfP{~HiSvY{4$udKR)vt5boesZfG%xub#URp-lipx$WVs?mEXBCWXkDcdP#KoFarH z$~cVD$c-Qgk!`t62ZZ(BnrxF3uzfF$S!&o{GVAnCOApa4@}JQ5P2JftUScCAW|D|Jyce(zm7%c-l6>y_@i_EaTNjT`M7EVi&)CH~6jkC$5Rp z15|LFG2yXg)4?j=G>=m4<|=vBzX7=6rpNAm$u0dZ6H{get8=PBdMFSQf~)Mb+%PbEFImzsBnv%QpjwQ&-rxp>Wb!)^Bh%gK z^VtJ>eDD52PpoMS`|`)PE)G{0hOOMH0P9_8iRwx(|1sRLiT-vbgV^lm~93*kGZVB3BSF5 z^zq}j)!XxY>Ft<)(vZ_!{+TOD%QHZxy^>L2f%&6u9cl|%krcj-(-*yW<~{AK^&?Nd z^UK=^uRe3V?eOB=-4~wc>z5Zs)n~W4?mBkWBBCxLMC`M|8uP+~>$FPB%vWlRoCtI; zKr3ch_`)6L{CqaCiFc z^yZKr@6h016>zV*tn=dNccPXMCqdZ2P>h*m65=XII#@2v41rZA&I;xLuym&uhszn+ z7>KZp-cd&|-&6YMk-b%0hI2mqj%2YNc7w&58~Zo@x6S|VaoSCprjbem$>-5eQN5?u z-{dSW{rCjOZyLai^P~g^(Fx*Us z|7sYRxP?z@n{uJtVbskHa+O_qY%YR!XLUv^mnrRVfmNcs3(?v!i9LUx0q{WJck;`! z?mzGov(w?EyzR=vA@{`qOahVyYeOif?@d zVKxxVUS}~PFWk)XV3n6+-7>5(ouQG?E3f%D$m8Q zoVD|`gmBXf6Z3)Fd!qLfAnKaKK<0TfoXr+oktwjYLmyB~nqOvy?4lVem|I6%{^J#Z$=RZ~) z70Os5uL^HW-hQHbjbyTu={S=O_RBM7o^xxE{?Fik{qc_rNlMm9>z{M|&E|nAU>#D< zZkQ}JEKTmW_WbHR%8fX&=%XeYTDa|;ayOAK z&;B;#L>iydmt!^qDmF1Eds9E~|KNvV z?pP)4^FQ1gV5%)Ip!R)%VZ*!4qHcebKTVC6914&#s}bW6i~;p9Vs;Qf`vzs95T#6A zef+?l`pbtdkXGpB0UT1074RA>kV9ubsKu4w(?r8iM3KC1f}NY`ETn|F0;%{{#F0h4LCLc z{PfS(>d6(t=eLbY7!Q*v?sUdUr+rvZ8r{qHp$Xwt40@LuQ#68^JYIAzo-nCCTA}58 z)!bt#jy8fM0k{1fecXQ3ovl9q9oi*}w{``L28~m`+9xyaBk#{j3zSgmRd zbiICM0@SJ6{fVd#I$t9c@@4$5TdrySASf*5EFm2_P485nhI?rVs0Ps{1Ph+!I8Dyw zAr5u#+v=+HOv~0**|1$}o(>k#$Nvh;vCWHjpSf37kP*BZ5+l4j<=OxkeK}8s8q>{Z z9KcVjoN2D6OULW{_{nFys9UIARE77Chu@|NLrNNLI@OOeIo!KO)d5JmqF@ah-}L}g zcUX+3*U%x#P9OUGaK&P28%8al9T1x7U%_nCci0iK+`40d^F;V}GnK@u*MIl>lN%G> z5v&WpckUY1f|SPxfI-Xquej36mqO{ zjbXY8&IY`?>vJEs;b8+{D5qoIFkIEP2+2l%P*U-<>YG)hiuLpacO$)xb$CBN@(85; z%oNK$`;R)63ogI^@$l6>>a_w`4eoxyf;8fkP~t$<%JV#1H|l9XZ>SomBUveXWfYa( zcC=(rFBKcfG4mmm#5vhI8HpLharNA2x~5e(^&%EGAMf@$*-+E4c>ZP{R9 z9sUhcFax0$dQ{-tg^lQohHX0fh5sK-5F;AJFRb(3Ki?$KU0hQsvJ@0>OhCij{&s=i z4d6t2^#POAJgrorwx{arBdS-= z;q&XeyU$IS>X(#}5C!6GmMz*yBa!ffWn(T~FI3tUtl5MxO;u2|-JU>Uh!m2z@njsS zd1y>;%H~AkBJ(fqY*O95_-_ehy<$8#xn$wH)eG@^I^c^gR{S=;x&0P$v8^~MyfwYi zp;q=qAXhFL;X8_wTcD{`8s4P{Oya;>%bEC{G*+O72W?Mrz+Jw)#O|w@qy9gHD!@kM zXZ-)zd~>6v>2;Mw%#~_?vH$*^iN)?Ms`yDfR zje81BrVdyT(&G%H9^_g4c z%m-;Ex=1h=-IIl4VjWg!jLH=S0}UTTcvm{x<<{ zm2&E70m9GR$#gh;t(d~qn|MC{6D%(P@^PCFDpKzd=6RCr(XoCZz;iEa zf_(5_&b)|4=c8M?(0I?<=!(Yr2P}LHGIqkMl z3F^O`rGJd{ZaIHzLQ(qEsAp|&ApV~>2|f(Gei2bi_+NATKf0>k+e~ncZtSUx{$uz5 zpL(|cUF$4GVytM`<5bA-(%?#Cnr3@F%^6OSR$`D9X&LbI(TIAi*!WiIX?eF$7)aiY zadTm2+N--ty#7CQ_I4$$_6fHCZip%LbfP=c)Pr3LzgP4#;PwTF1zz>{sz|az6T?k( zB?Kd=JMlJZaGo%U5sVDkK@Q!E^PY=+Ir=dPiU?PJUe8~`g1)`=0MkREJjdW^A7s>G z5B(R&-Uda8G64@QQ=03i)EGUC>>odVw>65A;NYumsq8M~_t9Sl%`;#I+i4{QZd<7< zzCzYt3RKK1eXH!|n%YdA=Qmf+Z1sj^xlelrfSkEBaJbK7>(L&D(iZsqI-cAF(T9hf zT4n3XyGyr%3S+mN9_4`F7(cj@Oc`VY3lk9sueo>^BWo2IiH2)Rh#we^#o%MS?^mFn z6lvCS=Sib43y^dEL*USD3-i>g5IdzD)cb{kUf(%P6mu)ZE&kA;-@_WQ3Pv+5I+hch!GfsyhHI zrD9(Nri6Y`Ke{z7G~;V%`*~A&;L{7@uSkL?-*of2vMg%lHDkMiRqGVWQ#lXOMYobV zIo333E>1BI2J2`@g^AEUrvsQbS^1{5$=^T!y$8p8P=Ni3e!Jl2P{HS?TOAtX(UG6EN*x_vt)moC%vAkpHI0DI9tmr_(xF!vmoc3w{tGINxY3d5vC%NeE!;o({_uZ&b3V4Q@P3)k za!(J6P57CYyh1cnMl#`SSFKyWcmqngQ12jvG$F<2U)#;McBmsnZO;tuV^V z_nO?gvb3!=(2cUBtS&_#TX4i$`|6So6Fu&8Hi+SHGuL~Y{M9zcVp?lcK2+4EO>&*g z{(tP*(JogXpx*k$FyJE5J9C1U&u>F}+Q9=UQ+S#ya54UpastyGjFMaGDVMERZ=^%L zdt)%ec7FO3wgpLf%mXw5*a)%#jXFyz6_-9UL72WD_7aXiU;leO3X2|@LPpkeQ>P{L z@Q485CXgeG&EYEabU*wv=;yf2(vMI7^k-yx-lE@8WG$=o`Z2P<9s`$vDN1iz}?+nC3Ujjzp?x?QE?gjwt_Knq6*(R zk>p4qCui1JU7O6gR88agCsbw(64FTUfa60qZ57Apx%NhcK@SPwV0(^e41mU#T;UiL za6;|8F>`*c+9PS;jUZN+nc&(FcG`rux*E$`WNQ>-0kuDrT>R{e4^)V+2hlP?$fxo-M9kKdb+L^;G;$Y3LfzaVJFHNp+`-V zh@%{$wCPkRnsik-VE1H91i%+1KPX)8gXbrpa#PZ9Jmo7qGfn#dCmWVFDEuhs`MXo= ze!mWMks@dHmDyoWooxoJA?6m!RYP0~H@35}z%QC)GaO81k^(;MjCjo=6J1}7xjhNxQ*IQ`&gv%HQ5qEBcR|u1!u2@ zSuI%xjm28@yRkcg9;6kG3k^3UCuzc&f+8$lDqFFlPSDXP6GE0Mxm zH67jjKEPjS3=msdqO7D7Z6-=dW`lT;t=n6YVx^0|mW_WYPnO;a`p%&5mOtMYB#c^{ zSc!@$>+b0rMxz~{@cTh+5e%P3*7G{H_k;T{_Wy3X6Dr`LuVaMdzd3%GM%e(ET^@?n z(#WT$4`TbVps$bGqfrebHP?+ZbDM`P^=5*%`M_f!KKaA_i^E&L`kz}mj>$NZP9Hq> zBa+c9WyGy_N7gBX@wBSZ{W4<2GpaQXRyO--W?g>NV8}p(vI!w4ugcQ^o{mitM(FevYkjs#3bJ71)-;vsG0qhXk4nruzc3Dhfl|{v*MzYlLz{gu^5L&GK1N%tc(hkXh;Xiw0RZO zhL!>ZK8uGp=vN;nx>jUgFkMtvIi%3VhFbjj$^&w*r$NK{XFiC~{QMke{{$BYhg)GD zO8)Zu!~FtE@cctFN@N7TXh8?8r0m~R#1GCjHyx}pBQ2iiA54gH_=nn) z!_NgsSq*G03G)p?Yx>9t(Y?ORx|n8bw@W$fC=Zo9>!>*f%M$WVy1ny~ z(|3Srn(EU3=CjW&sBjt?Wbwk%)5?%Wvr4%fd2!&dmEo9cc08RWpBbw?%jec9FW#M8 z5)`mMd<#AdFo|?5O7y6j{fUmmQ2H-blFwmnnDmuInU2pd; zT|2fnSlZq4plt2QDYTb+)iq$$O3E)J@DC3VzTb^19X+{*NJ-lGH2?S9AIbHVpQi*5 z4Epw9Xh*iSPSgKmy3%|QI1y&~nlkS%pin#w8U8JvUiNeamT;mIglc9QyG9;@wm8v-C4 zF4(D(nW(P=eC_3r`O0}}#zN+KXqB53_^yNBhu-}YTRx~*8OW)5%w!UU-O+F0P4`UYxFX=k0|kL=h?3S9%7Pqx39xA!Lz7FUmL@@s*5-2F!u)}P9f?eaj` z1^|gZDc2PG1bJ8cpK+-D$ZyT-=JC_7TJfRms12*YtX?LNqDpsE$?`E~^~@XT$D)l$ z9Y7P94P;+lDju_(+;pBfc?oT-H_H)JW*3x91a}!_rQq>@^7X9&L4W$v{*^Cg@QnuD zBJs}rhGP%#s?ZDy(i0)DrG08(JliX&zcbcHcCIsnjABIHT3K4>wQBb{duS$D+9dG| za_Ko|v5bOk0XSRd%&*A%?y?tX?P?dB2QY-0wWz`K+*Dt;CSok-G<8+>80S@5P7HlMK!3lO9N#pd zMWQF$iCQ2Q|V6|K<{g0ji-;LD(skh z;{M|L-+NGvApg^j|AP(q^Kezt7LolF%m%>1uU2kkrUE|oI6o7eEyoD!k2jzBg)i7m z0S+hgsJo1x)D=mvhj)kGuWl^q zz+WJO0qRnpt;>-E=X^2h*$47cMs#yeMq3>86i9jdwkn*qbC;XJQ~FVjxQ`7S zRhtn~iNRO#>?MFzax?)*tl=9=3*5awINflp>B4nr@NPt&5+xwMA-enj+Nb_2vsVil zw|`j;-okbF=d6U~&p@sYWt!aPAow~PbXeuCq?p%DUzg{`dfcv)= zp!bg`vGBS6-N(P~i`dwPQ{2=0dbsW6L)?kd(>I^;{MOK?yLX0CeF#zIYJ#&;5B+n6 zC2&_s;4Ib%vTHSH4VYubLaS_~+Qu%Ru=~K|Tpf>%<@m1*f^rv5{`^4i0|Atj9tJH# zT&zI7e+O`^I-_9p^S&bav(xhzwy$R{aM%A%AM9A~S2BsR^6|7)Z@xN7 zwJpz3c7;r$L^4!(H_JzS?lw2OxDp6sFmM8JVVC<$%k6u^%mI4w1tW*xroFi0kAAg- zGGTCT&fp8#d_DfZ9y!a_&K$UqN zDb?LLz|zFWRmo!-Q4c*69Lm;)2o-6-@1-YCUls-H*``1cFY4_(HK+1E0WDTa#`9nk z6J6(dF2{i3wvDN_ODI~pDmrQ;+>aNS&FIq2`m0O)7hfN!2Zv*|ke#qU&K)4?Uj8!j zrNlL_vL9|J`RCoH(rukkVcPr0cO1a2)!9Xyl&o3TIB_8wlP3u5^~mpY3kQMkInm{Q zHNcJObrM=So$sKVqlr%D(v4!ZO5a*x)KHukRwIJh8){EExOyd3tt2`42P!9bwV3?BAvddQ!sNy?hwb^w zk*L9O~Xum_@#)`{)V^(r7T~xhhHblBbBYmxO1%U)!)K@rPn8E0Z);0gfk!@e02f(J#z5v?YmFl`**L~-CNUMEJn1aAO9}N9zWjR z?s2<|35u9b-LXKuHEEF>Xmd+_U(Lh#_n=~E1$;jGtuN_waE=i@$MYw2YxaAcf=3TGc%{vaFV%wGPtw@zJfMmCP zaZl*GZVbH-eD$F{cIv>`tYdIb2x0+uwuGe-AKG%s?xpBhUdgo~(Nm%G{!?biR4LKLmu5s1-G3X8-(Rd7r1~sx9zEN9Hh#!Izq(j6aKfU^3(6U9t_}n^PDxN zx;3cBiR$C+7Add|%>PGf4QAQILt4t8T5fciuAG;}o!B{P1Pwl|Xhs0%cS??>p2i?8NGtM<$8`ggGpUlc6CJAcrybD1>VvL8; z*s|sh*<%wIyVqR;Xa;L2yR~67_w^0&m{ALWVVfcgq~C&z$i=3X>dO;=ecDk(I>p9aSd(VRPrhQKgu4^2LW&*An() zo(t54C0{INCw_SIZ4RaM6vh!3~a+z@+p<4%fa{lMRi zUWQSB{u49WAmLK&S#&B98RJj9Rbn>;&3si;P~#@cn{Dg0pTvn7n;#k1bfoAIVp5b$ zIRYjW`|TV{Q#a)&gE@MHXrj*fz)e16xc@@7uug;gfg9ir;y(5?sAe@IoPw?7$(}Li zUSc*WN+eFE;f%>m-;HYHFIkIy0-EhX`hOl>JNmT@hUA#He4%2a`s(x&s8{57hUv&k2$9 zyCi;Ff0~iX9TWa*iwFJA9NLCD72q}h&oHC9a{9=bVn}cQJn_a_^7vxqfZ<=Z(!3&y|&g#n_uZU4^5jvvUm~9JpsNa|JnUN zv=?9v)8J5{0k$(pT6?BGVsVie?kn2_E8hi(|OYg3Liqt(cVwF|@O^^KSct0ArT)y8)KhzP{l-rua zKy#}E#!3BYvhZ59`x3DBTsXc)hQ`Ul$<-fvJH30$0FHaS{}gzQ)dS04;=i!GdTP!5hr1?F&+lHo{lVQn zBik;~Tpe5YqtT|L9>_SG)gP0U;4^)%N1~i2u-!`o#)tJgFu9L6sIZL-nMWYB#Zct7 zW^O6I`(7F2i#J6yM#fBP7vttzp2YIykQ!wQ^nXrbKp|2f_ZMCe?%mp zH{*nMmId`KMP@NZ7V3)y5c3@3&M-^gJ~gT$wI; zZm!#C?<}5tRzwSiMyndKHP?oZ7G}|mxDKKzT$oK%#FHKo9%uCX^71rAk5J*z{gOh&Ncpn5E7>y#& z>Ra0xe~VSZ(3{>=ZbdsTTLeEX#j$w6-|(L3gsBkPDWjo%AJ2-t)^jgN+aDZuxm|6) z`2WAFP~+0+55K?jfCnpRzov5;2nI$KC7RRCLQ4o?~lz7f$_mMFxk(kH9s^m(3g1m$pG0;yJEf0rH{u%3a_-D{caQiDn9KPC*rQ!4XnvDnodlFPx$nY zKZtz7KN!@wk4vilKV!QmYf>Bcf6{lpbi+r)<;@&FWwEM6Nn&+n7%*n2=H^u>y;Dkc zkY!?ZWo7rqzVuJk*OkT*NldAZ*yjIrLNRF&Ez~eSsWL0SdL()>^3QVQ^)Oh4YM&~luM zJCmzEo_J2qLz|(XJ2SZnMkwig+1`C0Ax27MLMdQ0@%WPO-x$~R*N3~mw`khW&Ug28gcy@{;7MECP6oBCas}Id zV^Q-PE=sBDBuLLt*_)c8()BDd(Dd}CAv=mQuA%Sj2V#vNLTeJ2kT@jNxCdmAU+A|tEE3lG@CR!e%}Sp zAv(RhfE%C|tu1m&J5K)}JIF>>I=WV7DTzgndzj!l-q>!<@ZVOL`cq)6UJX{`{xP`p z|NiH5cRE#jny|u`9+U8L9`z8|hyRZD&^WA)GTQw5^w??l3)OFL&icOxKe_eC2Eg6z z05#Gk17BW2Mv(baQyZh|S|k`xkZH(p!h3Yrm0l%RqAW@6d)K15)}J#8VVXz@_4k;T zHi)PxRGnpq=bEjV5K1SZC%7U(UllD@_6kvWO^bq#^XA)=PTTi1qah7Pr{C-&H-j;D4KXY8q;)_jOEHEo#z=GwsN1bK5?lH#5MtM#EnhIX7}PC3N;ttWe#UBlN44 zZ3oOgfhn-=tugN(k&u+{R z6~4W?{`NNYrAVZ`HvIYjG-ut^kLP-IH1K9aE^G&q>3zqT)hIq=mi~dD1Wuv0cV;I+ST!0! zVkCWa8k)rlg_uBvGl!P(zNV@~8XK$~vPh>E!b}ZmOosYmw@-QQ1cHkz_XPaOE)ZrZVt~n}A669e&+yl3xpo8Ho;SB?<{ii2ua<gSyCWmkw&H#cQ2vVa!YdJH6lsoMVls8gs><=HBP({vDZxiJTa!p8 zlo^q4r=!;GJ?&FfRtMpbxOIgicX3U_{$%iBDuKVqXLJ33p41Jz;M6`qJ$ZC&!qPECKsF7j zG$y?}HOSPZBa)C^OlT@9ANg43CHWJ>rBqHw!qnG*)f9BdXHamH1J5B7jpW*^cXXb` z{#i3e;cofSV0k*}S`n7a3`Ea6M^Xw}F_4eT6zS_#efsM?PE=wu#Ru2Pd&A}#UFCj* zv_Aljmjk=0tTsHALCPuCz2*1)%lp@K0sshHrY1KJONjgfVmBc?Kji-V)lYSnx>XWy z+;^%ksf`aCsi6_Z8JW~2vh8+MRqP_=R%kr;_TFS=m;RlW&b(HZu^f?T~~Y%&M_2X5Aj`#tdI^oyH)BUsC`TY&NA-Z|H`6(DsNbMdbMXFKe1cg)zAb-?-_h30Kt0Om=e|&~}w~ zRMK@|uSJgV3Lm*YYi#Z0p{`^H_kb)-^;QOvg3SQk-X$Sk=dvdKvN-rNi#f}PdgDJ0 zTJ61$=nH+cA8>SF(=%Wc`}OPskJ;{?EBE1{5j`qucs`v+z6iRJ!+fR0VWL)C3(k2Q z5S`@FB*;rfb!973S6a#@cV>xlq|Ue=uYFhu3XGlIFgJ`kt;x)~;8>XI*EFtE+1?eK z%A7Dkw`0MyX(w?ydDL>JOLv)irg|Z))YQ^f_E2pynbF8)eLArmNiFJIN6BO8x2^wI z-I%H-dMuI}z~)3}BB8a-V@V)93WtK^#%du+FXfgxBeEN|kmNF)BrabjaE{yAHllaD zBYi)HL{D)geuN7DrU$zOh^TYVg8I?_fdu^0?KESc@*g5|xNEHA=El6g%cW&6XDaT# zGd!AqQbPD)p+`-JM3zD%M6#D9H7WiT(=0I7xEM(F{cubdo5)TZs3nF)Epd>x!+BUv zjwthPcwq)RIm*s zXc{Kwcn$iNb?Y-%{L{LfO?y0h-j5;ini10pWkF;1jtb)PsT zRM-vC603Q(n|Q6}m4TxmLs>50*gIXh^1O7J_X{3@&_% zn5{*vTEfG#x!vWr-clsV(IVaCIs(8 zrp9;|s1MSUoWGv75nBbX6l4?SO!i=@d3#0CT%j&Z?H=zyd5C9+Zu*h>tFK|SZ53WC zo%K1l1XoT3uU$VBba|1XXlMq`J{}kZE-54@Nlm5^!hDWtNw=-13TC+u3!;r#6z8DP&OelNY#!9NC+?6 z1v}cV0lNIUmaKXdy)2P^TpaNdle)@9RI@H)9es{ZjmNZht;e>Ar}R;p*}CI4)7?th zt^3&K>hcg!gMkzed0sKHcrAe*NLMVl@f%6-7x#@bFz8!mqng7!R3 zU;a3QdMP$GWZSg~LlK*SXrN1LWKG>dgBOrRk1C7|j^%h~tt68uvK4=fW1crmrNtp0 z72KrTPUKWWSwk^1Zx(eNq)d1~1daSU##4Bq4QN;~HAMjjy{Z`2m;If@t_+IVT_#HH zz)Zp1emh4#@rhGCze>?r8)SxX8fc-bZ-(Upcn(3Z{_2$Kbz+1&ar&|X#{!I^{D4ol z;=KyZr0m1DE4PJB+&z>t_`A6~eGcg+e4oNJq*|hjL4W&d2-&lolz8>Bi@v}9=x3pW z>(a@bAbGHiov18>EP*2S}Wl~RXXb@ zF@1?DK{tI2W2_??!i52`Q}j@l*k;@w)T2VHIKu+2oWR!X4zYnyX8gLARIB>PFtaD) z+|ZHX@f#6gkXZ!o&h(Yp#xo00@5M4w+*ovCduITFn7;=Jz56~-IQM@pNn1iAd*CcK z9mPf|ca@*|#N_57Bn`vu>J^)!kiA*o1k+DvRj(;_R%ZS))|lQf<``ssF9lzPe@qdJ zS`OUH$*VL;p>=3aa%@{uDmHupMyjK@uZ|_Ogex{j$`fv!$q&oXrh?A2)hm1vR7}c) zTuSe;it;X|b`*>#e^8xR_?j}s9HBG^t|I$9!BW-e%(fb5lvCM&Ti!rluGcO&sT*{a zjNq9D6A)``g8ronwv#DLb22g)gCteKoDxOPgmfBi0G~rm%c~}(c4n~3kyhB%v+2!C z83qy(3o()en_}X)nySqr@ZR!r>C+PLLdlA*>u!o-sMWIo_@E#>7Q+0>+?p|eCTI;A znQUJ@1h(4?Tsj1m9P$A=u8#dMiF#tx2r|QHicezEkyE`j@+f1hq%Rm9v%mn)1!*1i zP?3Wc3oZz6=F+--3}GMaJQ6kwxor4Qb_35;IuuU(GGT$?x%p1?l7eOI<|uazVFF9U z#$n~6c-S*6)u&X+^C?&8xaDeypHi2bK;^}6f8@PDnK?Ag*HObD*tYoDi=mzHkkSZmk0BqsA@q@2+Z zjaK?{xL4uQ?Fq9NjchM3Gj1Z%ZqCkOV+khRSQkc?NJ_pD7)`K;^zch@nLIppp@Le!_w)U>ji zZet~Tty#ObgC!#X`AUDi&+E8E0&H4cz9O(f)17f=T$O?+CJ23%B>mq$%=f4J8HS^& zPVY030R2NajqdfSn5Y5#d;CxOA+!MiMGoM59ky|aMlbL;G*lsx0 zc$6!_75~hEr2!t2m4txRi(5B1BgdVCSk0nJ#WXv_(TO?;|D8@fZIpy^xRKE0*4U!XMekkM$}f&!DF zp5L)dZM->-3GpDw!~CwolQEJY*2ZbmB-TYdxHa6<8&wH`P?3NR4Y;Qq(fLheID4mj zUm5LWE2WtD(vUqVpwmT7X!p1eqB}$+SObdR5m#prHl_c#(u^kJQme18e-)|#PbKFi zfgJt@IC<*xAAV5X&;JtRr(cXjxi#9Z328~WcBwLSrxG#JRq3{VB}%Vj;0OngHJX^B zGXbOWfgoNj`V^nt8Vy0D1u==g-bDOHSe%^XP`>1y5{lkVlRXB5DoA?I@3L@0&Il}B z6O_c>$+c}jHX&%IH}35iv~93uDZItWjD%&#sg;@07SmZ?729P@%5#A0wfuRZfwyL@ z-gSOmKP;9pfWaKxzb$v$H4 zjBu7|fgMkZ+Olhg?pjty3O!cVG0uL)Qx8hRwL+F}W-)8G(X2GNYYH_X1OfGL>#7=< zE_F>u7Te+Bh)wJq1DI&`=5)+1rph)5#&Ut)_JRUg2UCDaXt&`L^jU{Gt0l9@A++U$ z`!-0KLg}3Q3oTup4V=&QmvcT`r)x~tlEG3`D5XK7>EbGAuP7EmD4ouIYV@Qz_h3ne zHC3oX2{~hFLOhQW^NWDJdMhW-x*l%nkvzQfI6VaPR1)BEZMM+%PJlGN=e zdsB$&T^-4zZQC2irz$9^7SXE5H0@;Vm23haTV9wt?WsVJNuS&JC3{B_i}?(pR9G^Q z3V9P~w<+JEDqu5=Yj+UK5N+ncI5?U$t*zDP)KhHHU-p}zHGU|x&8y(xK4FnF0E8Yqcqi`4{8lA_g@R>?IELgNakIGv_o<c!i>tTdV+mEcnrjU*0km0HDh>mYJW*mc9u}E>z$z)$z(SyPDLOMZ_BA`i z*wpOAClQK0O3gN3e2AMsu}I_@EpiLJ$$Xq@ok9yNkayPesU}O15mNQvI_w4giD$LR zyx$e8!zO-1;!29}d8~@9n(i-|}8vsZY zSeNYtCh+|mDkQhmvQpntpmGx}*2Y>dhcw{Zlio078+I+REoUK`E?Y8^pi3pK$Sf{pY!89cJly|^2aG|y6Oc?K6(XHZJC$o zOGEjS&l)2Hf8V|JG+qvU-UL{df=DVr$g!B(j?R|`zj|0&nd>bMYQC^ zo}BU=xXLHdtR*bl7cbYI)6^I9T`XflJIrEGXjMs-?}S|e_VfF)1Q8xmv~|(Sf1>So z#bsti;M{cMw*(_ZT?a1I6QC!tbS>>`;kgESQNl?ZKa+iAK^ep1EmrMm{y&h=-9kMk zaQ3w_hx)Ly*Z>7ZT9ZMeh`Z!hq3BZbF^OnV5E;$lkv#F8BXLRzjku`3oVE%-yfAaX zeLZhp=a#V9>LuQ#D6)_L5+8LPad*1|l~knmNw2QiYgU7nWfE&feeG2^zrc#>a~F;i zE=R$wWQ-iOVmQv8k+c?mtF+^Mjo!!E#weAeQPX%HQ~6oiM84VS6c^Y^Lq!1abZKeH z*vJnDjB*Zj=05p&gjH7)`1CAwJCR{E4dc}rfgx>reqN-hKeHKk(5OIE15o!%Y>`H+ zTt^^5(&Kr;Lo}ez$+S#xmN?TmYUJ4)Q1VO=8HDKMugbs-?K+#an?U()!>ILLY7Jm; zRYWEpSrTaKn7a#5!hUYphc_?2y8i0)a^P=FKiSp8PAP4x?4LeBbVAgf#G^dbWFe1B@u5sQ(epsc07q7vZHMq9} zDAO5JFGpNWcxQlh#7XNU)ly-)pTy&AEy4+pjtW7%&fd6jWO}MO!a%|8_l1tM7~k>r z5lRyY;Ry*(Tx_9@y3@$la9@$BfPGDgrRiQ!93VyKO?fN)Q()Sd0WY#8*^A4q#OmZ& zQ>{R%dB}>kYznU+k|D-FnHIsN>rjhBJzt*x|NV#k_g_EVs>Qv+{p(XLtcZes0)$ht z`ELH;aIQunE!g_-qem!Iq!VhMjUFpH%Ye;Nj-I1P?i*n0F<~rqppx>){Ru1G)@7sV zyZ?3>wIZdL=5|OXjY{|Z)#bO^R7B`Fh&B^j4fz)-rSBdY$v*bZ$JABV&oST#w>7JN zMTwfpV5rO}#_6cK_$GL=ld}D$aTnxh=`amQsElWJ3KU>Ykk!tMZn6NcEz5NGw6l2e z{P;M(rP@(5#5CuOR?iMUx^7JC`d|#!NXPFfm%m-kD>nG+cfK}V20ohszx>b7k8i%J z-s|hX?4dVwOK9HZi2-57u!N&Zu*GE&r2Znk_OC2E#b={cE!qf=K#QH28yN~Zuxk5F zbe70DdZlAu*KR;blQ+$gK3UN=4TxEl9^)2vRkhRMr>?o|((Na5GP&X6bQCNMOg2Q*NLEmS zXy%|Ol}0tz`p|jwzHGE^zSnlcgrRn1YWXM5B+ipmvUIYd$xKuL{2_3f3bx6>ww9iK zmiH2Bz%4RcH)pL0Hs=-1qzg!k+gYN#pr$)y^?vxoGv(%WrH)UDpbr)fidx`Re4c)8=E@--R8b>?L;%Q+ zMn?E|6m1&U$=J{eK;az0@&}j#GhwJmg)7G(_GQKxWDcuTALavZ!kdd`3DRW7+AD8& zv7H&Bw2zK}Ls;tQRg^9PD5$$pP$4W9nu2EP2z2x*EUvb&4&q+D5!U`TZg45N@9nwA zDpGJs*Rp(aek=JWxezA2U9j1g6ut6`F05yp4loO|rO;N0Dr(QUzC6^k`dT|U0Mr$> zU!X&zOs3LPU2@N}O{;YDb(ED>{X5Le3PO3bDi_66dThuWTn5!i8~6gjPcAfmM*OwM z>tp)hnCt9X8wy#6a~G28$>QAAG(9UIFqJ?sNLzRA#h(0?|HjI1j2bLuI&1(8MEebf^-sA-=Ir9dFwhzLALDKjzu^DkyLV$qt6s0nqmOjo%x7vWg=oM zy4Iv(EDl1{%KcjPd0F&DwT8!oN2I*OrD&svc{?TQmJ*G=%9Q4YQLaxgrZ<))3k^;3 ziHKXIOPv6#YS%ms1BTQIZX*3&V%VZ_KRawmGSS{ zVR6kH&AVBfgo-3+9_?dA`%XNz@@K- zB>Jeksozn7<_C2PP3Dy?$ZBwT54M75iXiO)6 zcdsXge9THcucM=!;Z-n0mne@;1;|Q(ZakQy?qaZLiXtN~bnQi3GQpvXw$~{S=m(*7 zS_s0b@{G82=qPQplqt)bNJ*&7GS(H3qq|s^BC#-TKM{*%mxC;t+K|E8D%(&XdsGk1 z9U9H(fD?A5ISr4KG*k!Q&I{cqu0)S=pR*1S8&5BGCv3Ct-_7%&W%XdYE_i1G3U}Rc z3{qN6DFhMt5GW`H_Q!~W1S`lNW=n}_kL0F(rfhML1m`sSeT>hWFNXf+JD7+6t*zFD zIz^`?;u!bq&0*G!HrRX~7{FWGkGE}FY33Fyph^OccwRX^bL8RL#H`w;cp)cpKS?h^ z`#NEo3$PN$%sFsUFDWT@iD&=CgMm)K;Rn`mZQB~@?E=|D)KR(4pvw>!T`dS?-fyH> zKWI5zzbS3fEzu%qlq%(X0&7=VbtbDjgGI4^PaLfXP1wOgH6zQn+I7xz982pIx~)sC zJ$+wXIaa4Thqxw|Xi6!KvO?5Lu6`ipQm9smX9*Gsq_y)9^)6r>{CXA4N_he2r3gIA zH`l}O>zy#AKv*<@*lPnl2|p3)1guqr?u~=?TMOUPYUocSJ&|VUn>OKBA6I`KJ{7huuVN@45~fPGwy=we241NrS~j#4yOU5K=-5dt#9`#P&^^2^P;|pkFv?-7(z38syni-`D*%zNW zUa-UsYaqqpxJ#zp6e;X?!5uW@EJ0B0b_(1%sEk*A_*s2u5Wta7ef*EX6KgO{vtEx6!-=RXdt`SXA!QU(-8 zs1A%rur*9w?(azF31VFW=ZQ{(3;VqzSb($jIL>{#GU^ zrdJ$PC$}$lhP_bD-H@H2&o~#YgXI&YkuKqi_6!ZHG;u5UAQ&JzZ%4akdZQ}=oA6UZ zWCKYJ3z9e*{JOS({yL2qkLt!KP+k)RpRLq9@aH;*qvgvvNcQN^%~){cMZSAezZZg)q(YuJg2fyxi9LAi z)}CxHUYb;w2veGg8HdM53Au*H^Qw|}zSw{Sg3Tw^UrSEkocO=@-)1(_#YytSjZ##8 z{67fK+UhH3zSZBYzhH(^ZsO*_5ckGRkv?DFX-+@A76j5fB{i6 za?g9QA#ayQ7K^S}5Wrl&FpkB}0MM!ZO1KYfn)RV)R$`mbjl$RwCzwPg z05>PHhYO;=U18s#7wEtx&1K8vw8#sBbEz?PSo3BT9~LsMvfJA&U!xAR0v~2nV3CCc zRBIvzlp=MAMLCDXC8s11zd{uVR@L^_YwZB3UcMO5W_kU~486u#3=GyRg|mU-uN?jD z8mCK}1K7uuq6#M!%bJc8r&dx5N4JNr70|)BxMo;&;wL9MOYXTKcb#EYcytszP<$={ znTEYJ>RfGT#bp_>-|0we)<)k`!A=X~W!RFW{3#Q?v}{loEu9gSI^j)upcT)t>^47z1N zZ7mnCi*3j{>mr%UEX=Q9Y+>XJVNARrC4l$ySnQRd^wzJAdhp8=BVoW3gCU|ZApHHr z_JVK1CoD3fc9{ljo5MXB3E*Xv7i;hZ%dXH06l1q4*|V4F!st6cX2kd~(4LFjRNrS9 zI5Q}@zt9wzzok^1gTFfFTmCk5Gk$$l1Fc-H+g=xTTfPK`CQB33(Y8${BY z*(DWb@3wz{GNlC{$U0)4lmQ8TOrn?B*Y#VtJ8QoSP#eP50fXjUFb1nm)V%<;RB3(} z`GYs+y*1aNV+?Pkn&fz^KSC`b3L3}LpK6@U$wf{&;cR!6wspN?)=ZGu4z2GsvosV{ z<7_{;EbH{>RbwlI@zmT(7_*KlsoM`ee*Gc09X$NpteZ7s2t8Jft8Y=5gG1@vyl4gP zvFC{7scu*~ec4uD$>8@8n5N!SGR|*vh;f_$);G&~8FE9f70#;PW+6##_LmKe-+vKl zndqyabL^YfL`LB6Qynh&=CP2OD_m_|IOeH$i+(eM?vf@;Ah`!=b-m-MP&G+s^4*l2u zj)leJ+SKpj*Ibw{Lo$otF{RI}{m}9y&5B_%;C?$4F|+%JN!th#q~8)_XwG@TBPj`m z9Q0c#4oX=tH|0{{FFg9iS5P)u!5^>zey$z*(1Giw$-HrNOQ4I0nUK^c3dN}ld(>rS z+ye$3MSX~dC%!junFC0Vzqqi7;z!7cEBrO0^PksXQgcOU>BC@B388_~uc%=4@`TQ} z44^uP(wFo-;$H&91Nu3v&tiPPYFfZ)IC=V3)300Kb}xyTa!Fzc-4QOUE*}AanXuwo zSKY3b^iki)0pHEsq=rE$i#{q^7VizswYUx(Jp7aqU5oSNyH zOM0SEF^*QqGtaA<0VaYC+;H7NSiI-(zG4xLskw>8>H0oZjpiyW%6!GmglnV^OK!`9 z`rN3?$l`LN6_44OkBNy8TcW$KYUJwu{fzGa_NSf^mJ*(%94}qZQ5iNd=21}mC^gHyc-c{w}bJ~+UCBnX06m{lB4Kb(J6%H z6EG4pJYX!h8R5-G*ORsfMq}&R6EgJtR`cYI7K}?&qi1=BT6PBB=dG78>NIT{PpJMm zS`%yd7&M!P14*wi-bwmC$w)$rrGlPGO~zbQ(8v05cVEX@`Q4G`+fdu&uK48Sx6s{- zaYAz_S)WpKB+{LxY|ALx%{ra8T_LuO+*tJ9hKz6EY7OtfjsRK`9yNS z&D+uqaThF55#`6)-n1wlv#qrWi}U7Qj%O1zasK>{!#O8t6Os-!!M--in}sV$O4>-h z51LFWaU}?vaqKA0c_cBraCg4PH@b!I6IL+!^*l|jExBo0LKIvwiZJ=# zN%YPKd|$B6DGGkyrXuL8z+ifFZa=RY61}VU6Q8x-&7dCmph>FlQmZMs%Q0{3w);O_ zisHg4alj9b&GD{8eSAd4l*pu};)M;cQ-L+SF-#SEhJi#!{4_2-OyN*P6)O1pU~#t_ zlw>t`W4VR>YymoGD!YciQj>lkEW;&XL{qG~F_u;z^lC;H-87OzD}ZZCLlo)H+OQ#3 z%Z%u}lP z!>FKij5UZ}6TKHGVKB!#$opM?YC{<}oK`sgu&bA{-^{+JNTbHjK z?tQ*?2dIHgqjP?;?VZWf>9jCn-j7>1K>NL~s%_&^2kv zSaF)r1pIY5pDn9n3@qdmuru8p_CLpxp0HwQhEcW1&C|2hV3gJwRp&3)+(07AP2gkl zEouc-d2~IWvR;qIr7xW!mSazYSYrJe&dz+j}Aq72wVUNa^+l0$-wx9uL4C z41t@w&0n72Sr>>Vk;ra1>X$3^HjkMwKu7@w(Tdwx$1a zG2tle=toJRmYI0jg);cS?FU-%0G+~>!R0}hHUpPFPD{X)XXt3TAKYrYL5`u%02;A1 zoV@7Amf#2^CZ!Wkqw1yS%lweD$JUfyG3ODX4xHXaQ+f0Zo%~@t}e=SfVMUiUq3E~PAL_e zcfQXAf_txj1{2wHrPmJ=u{DCBYf#==S z=?Fy2zp^%zeKiA4?7uLl?cTLdC&;6U`% z6Bh4C19pZ~CUulUCDn${r+jOV$clqZ8iAlAi3dOuo76l=YnK4LH5Q~T{<(2jQkX?8 zs*KFAxPB$k1^EQ%zVlah{w_uV&ZlM)K)!oqN^c?IZrL!oXsR>8QKRQVi}}4Hz;IWc ze?4EbTMJfppL=HHvWNax->-QgEBuG4GD1~M)GgK<*^W;ogkO>c*^}bpYT%ePh%I$u zsZWf#tQ8sqX9aYd0C)re&=nQaAr#L_vB+XjFZKi*qRNy%uDmrMWc;lNJOR@bHA-8% zNf2EW6*k2s+y?zNnQTDg;f&3m$#GYh2He~6J&w*-CkgBqREP!`sHa3GQ0Si6^^k?- zXF;{kKl%uyiPK)p&cKMs|KrjL8#9RvDf4o0@$ zG97V813zQwb0U08n)#?DfNQ3}t=|>ffQ$}&?#dr`dKzlO(=R*zLFaa3avH$i#m%1% zI>$oElL4P9Nufi2h9Xfr|D0r9eCdngg}6ugeqDo(!fGT$DZD$=DtK-0!y~Tn&v8 zZ%?tF9;7k+ArX)pFXU?yaK&Pm&orO>`VM`eZ=W#~PIo`h!sE(jWA zpwIn#KEF@hFvzeT7LNw=DG*6Qc*LN5iE2g)P3QK+0p90@o7-$h%hJVj)CqX*fU|{V zaqdxIoGS=}?Rk-;EQ|J_h}x)^3uGPvsfaPh@@(-b0bcztPMR&ujZxis3r?>;qpe$W z>%v0O*QAg}-5QzimPdge6Rq?CNRyEo+v%b8HxZa|S&9UEx10=j&syPo8CO0jgq1JD zZ`0O4{|fn;Gtc#D#C{cy0>67jc5&&M`pGhVZ~~q#Wn~mzU;a~E2Uhl3|X7*gF z^=HvsZ?jDQBu;c(7*Sr`v_jmR9K!`=&AE_T{8A^}ak)=zuGTpFY%uZ1*n1=Ck#lo0 zZ}cF$@8AF(o)lm=+T@53v3#SFOgU8P&nMu@LfAPzjdC%Mp4?}efAAR4eIugd?nRGh ztx89O1uJK7;L)Ncf$ZAMBf9yS!4Zum3l_l|=KFY}F!M8mfYNMH?4f=~iC&X{sAjWX z-;*C4Eek;hH^vkr=!kY0;FQL(yg{3A#I^yi<<$JPulYJdJd`wJq77!}{bvn13*yPAO-zI#9pVFuihU3y30$mUJ6IMJQ$&KEm2ZOT`2{YX>B5TL4R3tO<*kB4CI*A z(tr;Ykj2ReHQy3MDABC1die|K$vJOS`UUA73K$Q3;Buzh!zpT&dt*`}7jN*+(Sc&{ z`vpK)#ye69B2C3G#1~Ldg_N&484#bu!=hU*-l#`x*T3kdJpjH{2X3vP#NHFjVM0TC zLhfr+HI(BPF5jLxknPRW5Z&C&8a@U-|JRpeN!&5W42-3%sMNF_ZHN)vLY1-%7-jM| zNekC4(-M(5!kXv*U33=QpZN$S5v#V|t20iy0@VFT4Bz15p;H(H7r`Q$t7{15T4B)S zyrPR#gkHeW=qqmne`&cPxP!qJZ}jR@Owf=6Uaqmp{28{@*1SC}fLCBFtmIs>Hwqp+FQ9OxF zx27KYeskk&@y(Y4S=K_aIh|sHhG%mu1S0FiDMbHh=J5faHiOCbSHPS!N1cs;d|+p$ zC2k9~KI+|BUI9^Gzv(ltLns<1cg%2dNTWWV46%)DhPC^#txv48Ow#~k7f`-f-tyAn zsxlmyzm&q#GZQyzq85SC!0c~f!?Uh@9{9vSOIH%jd&H-VAr`FUHY-#bSwK&Q>O$pS znxTUg1b;waU(2mu7>SYy;h1<%xuScR&(%S_@24h~yf6WT`r<5}TNx>k1bB^UhxB4g zDF?ay^jm0CTR`s`y>pzg(ZqD-J@~FuC7MJy?daoyM+DlWAISnr+$7SKqKXdJl2vQ2^07=b4- z0X26*bf(6%18FK&(C*KOQFM7QmOs9rZUvQgJxB2@;E2b|IBC>MK{J}ISG=K1vJ;!X zF(cBAMit57ABGjTK3U))Y$6N;g|HMT$o&Pts4HdL)BQI`nxP9Y5y~lpv|eH{7Wq?H z_AQL)BMN9{^VJ^mH^&#Z#g?_vG?NohFm=F+nmMEHdXF`LQq~ykU7u_GI8M z6Uv{6i+PM1=cy@~v{8|jcV4kF^f&LYzrh#N23xOC6-Xq<59-@4A9%2to1mAIVu^1* zPvnMv+0KqC#J2~ch`4g*v#tmD2XK&yXj@7F^Aj7g!eW%I1r{+X&`i=1j(3ZJW5cry^zO!^PE{DISAX9rJLc9_EFI?Yp|%vdWzo;&9{|t4om6CW&k|Qofr36|s`eph zh7yB>6V5W@VQxWcF}$mp21&R#25~-fDN9eV^!W@TKefC6DpLAE!%>$y=9)chWQ^F-EYtH0gDU16p=yMEBk;X` zA}DL&nbPJ8T@AffU*{vOlmxU++?G)?8$&^U@^arhtsrQ6TAK?`G8^x#>N?@o_u>MhFC98u>GA8~=RXRpYi=7MEBcIx zxX^$%Fxq5o1xVmK%+04yL^(Wz$7A4W+Wq^WbxP;I<601ij9s`>1XpCq7G9f!8hWs2 z$hJU*m@L6i9!|%TbFfYq3C;?~7L)tGS^p(r_hF-&y1NHF3AGg6VEqi4H8Xe9aiL|- zjYOpRzh5TyclbnZ5i8)tH>HiFsHJS3)l;3!R(9(+$}Ef)<2`5GBM+%E5!D^Q4o0@3 z?*B>6h_MO__wkdxJ69h5nA@}txKXRGAD6~~BPUKJO9)GgK>{LUdhl=s<7`+qn?q-bs@-ymq)A3w0VC!LkM90yh{#Ab>hvrx=67OO1g+03Z5f2` zSg$gnCkqAQzw|_PW^1*c*%X@j%;DQIrT%Xk{OepG%UUOLhnPx&CDFG0WYF0u5LYq* zI+G+yZA&w$g`O?e;g@T3_UVK210Xu#w9$p>rLWT>5l>ieO+SYlW4=^f==eqF^AdsM zNku_D;HolEi@WE{fVuk<9x6%cfN12S(BAwNsMNH|pl}6mwD+{(+`Kk>wm7!{70BdR zikspO22XeHATx`6<#1eQL?wVmPCQc;@KjYqh<`(zcnZY@AD2#C@(h~KS6%evpjRRn zrL~u+C>O6Q=PoK`>GaQ z{9^%l%j4@R!SG%Du;*+~;&eHTL(J3s%EUum0i+J|5)CHUo)wb2M)n(_nm{`l@3w&Z*$Tz_?HRi02?Vx3Yyvl>nwH)TQ1qkz^a3W3ObB3^I^tDdo(Q!eGY_?$j*zi12E)_ z%udFhQ^QNN&Rv)Fw8GdW4!7iY#3*CJM&B2J0bQ@@GSup`F8Y%Ot8B7F9tK zbK7BVd@Ra4%7xsKf0Awv;T@H8UcsG+wFn0T?Njbrxnix`Lun8HxrKLD)_e`-e8eQ>bz{y`G7yVQ521?k*>!V`|U$azGr zBg8=h0D%$afvAG)y6rpybj_OE3?=j*c;xGY5FI~h4GS|n3*lT7-Q zL>t0{EJZpG9y(jnrC%n~nt)o%k1q=b=*e^qqP8G>)+}F2ktJh7hA7U9po`~oha2?; z#{#eShHf`l)H@(@?OqmymIm~vA;qo{V^2`x+Utok0`e;S8&W{ z>!^r6AAp2bQ?sG9Zj1|z>7bJ;Mf~motj?M6vZ`J)SN(}O6O!oO6GX81>)OzkJDq5Y z;SF{vXfu$^EqU0R>G7)Tf6JD<{`7&hN(t;MaQu+h=YyQo4!s+$43`yEZ@$fiF9&nh z@#Iz7dUOg_7`%WbieT$jy-6$rz9wiL4`_M79gB{+{wkkO*zaUfB#0+}iInpq)p;LbLzHJwu zf0Ix$pnhY}`nO+87o7O+nG3s9l2s%aa&>8#(i=vU^f>Hcdjj7wdc4n~$nHW{O__vK z`h4p z5LBmb>%z7JkLG=B13~OuQC-9_lF&o1!kdXyCH7iN5{uq??M6$A9QsK5sEG69{aq0g z34te=&vqnYGL4Qfg1S+LF@4E4k}?oOT?Ec}n&dh7mQ;2>s+vKw_ zbcL-seZq9qsJ;t=R)QTPe6sc*|K1fDOpZ|dKx}|LW{R$4$n-o$iXi4drKqNW-`|=l zH(6~B=m5-7Opa;*u-Ns3okFsfB<4{x+y|P~`X}>$iv@w9Q@wdSmgo(mb@sT9pvFU- z`ZWkW>R^dsFUsWF;Ug45-y;P33YDCzPsZ~P>ad!UfdCAwjq_Vz_4ZRP`mjQ^d{6~TijHG|EX6X8xV`bNxc))m1t>}`3aqrfW(klh1$=+@G z1KA?zVWLNWUqEsElQNRcr<15h_r*eJ$k3hGdC0&FV;{5mueEdG#ITPMVE4ffIa5beOe4?iqI+&21z5Tb)O(mgXJC}9XPW3 zEm8Tv5^a>?0MAa*@Z%h(FA)k2CyTELZ|ZyS!oSFu0}-I$ z-W$LOfG?qjb%s|nzB@|3yT593Ci$CZvR~^=f0~i+yvUhu6mS{E13vQ#Ni?_1;ro6D zr+`vL`CW6FgC^o#Mt!w(Pf7TslF;baR!`0ngkxf=K{&i>FE7l4T0EJ`vQa zVv_ecizMK%CZAa3%c6O_3t8@{?`nQ!xcO-0>nq<8zJAf7%_ic?zX(_ezeE|N=fkmh1`|xK1lV}!YRyL(ax(8IM^iOTp6_iM=ckA_;A0>7iDzvCQj%{AY-{MfJ zw)Z?U1Mk$N8S6KVi?vna%cvPT9J5jYo=vG}&1rr2_dgQc4d0#kJrO8v^zZ0kiJ8k0mc14lbOR3_Q%0D1ACJ=@!q#T{L(;kJbBPCg`FGv(Ke; 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%0A;SL1XGPK}44pRvdU%|=L6 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%0AJxGX#`{Z~qFSniwbV?6j@khX~ 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%0AO<-@Aq1`+<)lrM`<)LK;c&wl1K`ky+%^ku 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

)rC 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 literal 0 HcmV?d00001 From a842e981910a7ecce7a64a54776ebe861535d397 Mon Sep 17 00:00:00 2001 From: Fredrik Eilertsen Date: Sat, 15 Jun 2019 01:27:29 +0200 Subject: [PATCH 220/223] Throw UnkownFormatException on Image.Load (#932) * Throw ImageFormatException on load * Unseal class and make constructor internal - This is so that no one can new it up / inherit it outside of the assembly * Add new exception for distinguish between different exception - This will be used on image.load operations with invalid image streams * ImageFormatException -> UnkownImageFormatException * Add Image.Load throws exception tests --- .../Common/Exceptions/ImageFormatException.cs | 8 +-- .../Exceptions/UnknownImageFormatException.cs | 36 +++++++++++++ src/ImageSharp/Image.FromStream.cs | 20 +++++-- ...ts.Load_FromStream_ThrowsRightException.cs | 52 +++++++++++++++++++ 4 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 src/ImageSharp/Common/Exceptions/UnknownImageFormatException.cs create mode 100644 tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs diff --git a/src/ImageSharp/Common/Exceptions/ImageFormatException.cs b/src/ImageSharp/Common/Exceptions/ImageFormatException.cs index 89877b1b6..8b9dbe1b8 100644 --- a/src/ImageSharp/Common/Exceptions/ImageFormatException.cs +++ b/src/ImageSharp/Common/Exceptions/ImageFormatException.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -9,14 +9,14 @@ namespace SixLabors.ImageSharp /// The exception that is thrown when the library tries to load /// an image, which has an invalid format. ///

- public sealed class ImageFormatException : Exception + public class ImageFormatException : Exception { /// /// Initializes a new instance of the class with the name of the /// parameter that causes this exception. /// /// The error message that explains the reason for this exception. - public ImageFormatException(string errorMessage) + internal ImageFormatException(string errorMessage) : base(errorMessage) { } @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp /// The error message that explains the reason for this exception. /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) /// if no inner exception is specified. - public ImageFormatException(string errorMessage, Exception innerException) + internal ImageFormatException(string errorMessage, Exception innerException) : base(errorMessage, innerException) { } diff --git a/src/ImageSharp/Common/Exceptions/UnknownImageFormatException.cs b/src/ImageSharp/Common/Exceptions/UnknownImageFormatException.cs new file mode 100644 index 000000000..ca6e1fe6e --- /dev/null +++ b/src/ImageSharp/Common/Exceptions/UnknownImageFormatException.cs @@ -0,0 +1,36 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +namespace SixLabors.ImageSharp +{ + /// + /// The exception that is thrown when the library tries to load + /// an image which has an unkown format. + /// + public sealed class UnknownImageFormatException : ImageFormatException + { + /// + /// Initializes a new instance of the class with the name of the + /// parameter that causes this exception. + /// + /// The error message that explains the reason for this exception. + public UnknownImageFormatException(string errorMessage) + : base(errorMessage) + { + } + + /// + /// Initializes a new instance of the class with a specified + /// error message and the exception that is the cause of this exception. + /// + /// The error message that explains the reason for this exception. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) + /// if no inner exception is specified. + public UnknownImageFormatException(string errorMessage, Exception innerException) + : base(errorMessage, innerException) + { + } + } +} diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index 74b99dfb3..c4336c9ac 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -62,6 +62,7 @@ namespace SixLabors.ImageSharp /// The stream containing image information. /// the mime type of the decoded image. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// A new .> public static Image Load(Stream stream, out IImageFormat format) => Load(Configuration.Default, stream, out format); @@ -71,6 +72,7 @@ namespace SixLabors.ImageSharp ///
/// The stream containing image information. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// A new .> public static Image Load(Stream stream) => Load(Configuration.Default, stream); @@ -81,6 +83,7 @@ namespace SixLabors.ImageSharp /// The stream containing image information. /// The decoder. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// A new .> public static Image Load(Stream stream, IImageDecoder decoder) => Load(Configuration.Default, stream, decoder); @@ -92,6 +95,7 @@ namespace SixLabors.ImageSharp /// The stream containing image information. /// The decoder. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// A new .> public static Image Load(Configuration config, Stream stream, IImageDecoder decoder) => WithSeekableStream(config, stream, s => decoder.Decode(config, s)); @@ -102,6 +106,7 @@ namespace SixLabors.ImageSharp /// The config for the decoder. /// The stream containing image information. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// A new .> public static Image Load(Configuration config, Stream stream) => Load(config, stream, out _); @@ -110,6 +115,7 @@ namespace SixLabors.ImageSharp ///
/// The stream containing image information. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// The pixel format. /// A new .> public static Image Load(Stream stream) @@ -122,6 +128,7 @@ namespace SixLabors.ImageSharp /// The stream containing image information. /// the mime type of the decoded image. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// The pixel format. /// A new .> public static Image Load(Stream stream, out IImageFormat format) @@ -134,6 +141,7 @@ namespace SixLabors.ImageSharp /// The stream containing image information. /// The decoder. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// The pixel format. /// A new .> public static Image Load(Stream stream, IImageDecoder decoder) @@ -147,6 +155,7 @@ namespace SixLabors.ImageSharp /// The stream containing image information. /// The decoder. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// The pixel format. /// A new .> public static Image Load(Configuration config, Stream stream, IImageDecoder decoder) @@ -159,6 +168,7 @@ namespace SixLabors.ImageSharp /// The configuration options. /// The stream containing image information. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// The pixel format. /// A new .> public static Image Load(Configuration config, Stream stream) @@ -172,6 +182,7 @@ namespace SixLabors.ImageSharp /// The stream containing image information. /// the mime type of the decoded image. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// The pixel format. /// A new .> public static Image Load(Configuration config, Stream stream, out IImageFormat format) @@ -195,7 +206,7 @@ namespace SixLabors.ImageSharp sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}"); } - throw new NotSupportedException(sb.ToString()); + throw new UnknownImageFormatException(sb.ToString()); } /// @@ -206,6 +217,7 @@ namespace SixLabors.ImageSharp /// The stream containing image information. /// the mime type of the decoded image. /// Thrown if the stream is not readable. + /// Image cannot be loaded. /// A new . public static Image Load(Configuration config, Stream stream, out IImageFormat format) { @@ -227,7 +239,7 @@ namespace SixLabors.ImageSharp sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}"); } - throw new NotSupportedException(sb.ToString()); + throw new UnknownImageFormatException(sb.ToString()); } private static T WithSeekableStream(Configuration config, Stream stream, Func action) @@ -257,4 +269,4 @@ namespace SixLabors.ImageSharp } } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs new file mode 100644 index 000000000..df1f73c7a --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageTests.Load_FromStream_ThrowsRightException.cs @@ -0,0 +1,52 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.IO; + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public partial class ImageTests + { + public class Load_FromStream_Throws : IDisposable + { + private static readonly byte[] Data = new byte[] { 0x01 }; + + private MemoryStream Stream { get; } = new MemoryStream(Data); + + [Fact] + public void Image_Load_Throws_UknownImageFormatException() + { + Assert.Throws(() => + { + using (var img = Image.Load(Configuration.Default, this.Stream, out IImageFormat format)) + { + } + }); + } + + [Fact] + public void Image_Load_T_Throws_UknownImageFormatException() + { + Assert.Throws(() => + { + using (var img = Image.Load(Configuration.Default, this.Stream, out IImageFormat format)) + { + } + }); + } + + public void Dispose() + { + this.Stream?.Dispose(); + } + } + } +} From 692e244f9ab4adfd57e5c7a8636fd6fc59dc86d7 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 19 Jun 2019 11:07:36 +1000 Subject: [PATCH 221/223] Fix #937 (#938) --- .../Formats/Png/Zlib/ZlibInflateStream.cs | 6 +++--- .../Formats/Png/PngDecoderTests.cs | 7 ++++--- tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Png/zlib-overflow2.png | Bin 0 -> 16887 bytes 4 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 tests/Images/Input/Png/zlib-overflow2.png diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs index 71141a893..405eeafeb 100644 --- a/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs +++ b/src/ImageSharp/Formats/Png/Zlib/ZlibInflateStream.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; @@ -140,7 +140,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib offset += bytesRead; - if (offset >= length) + if (offset >= length || offset >= count) { return bytesRead; } @@ -249,4 +249,4 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib this.compressedStream = new DeflateStream(this, CompressionMode.Decompress, true); } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 70d191d74..5bb2db784 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. // ReSharper disable InconsistentNaming @@ -42,7 +42,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png TestImages.Png.Rgb24BppTrans, TestImages.Png.GrayAlpha8Bit, TestImages.Png.Gray1BitTrans, - TestImages.Png.Bad.ZlibOverflow + TestImages.Png.Bad.ZlibOverflow, + TestImages.Png.Bad.ZlibOverflow2 }; public static readonly string[] TestImages48Bpp = @@ -294,4 +295,4 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 1019a5b08..3c732c32d 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -87,6 +87,7 @@ namespace SixLabors.ImageSharp.Tests public const string ChunkLength2 = "Png/chunklength2.png"; public const string CorruptedChunk = "Png/big-corrupted-chunk.png"; public const string ZlibOverflow = "Png/zlib-overflow.png"; + public const string ZlibOverflow2 = "Png/zlib-overflow2.png"; } public static readonly string[] All = diff --git a/tests/Images/Input/Png/zlib-overflow2.png b/tests/Images/Input/Png/zlib-overflow2.png new file mode 100644 index 0000000000000000000000000000000000000000..12da8ee60e369c33fc7ac51fd5dd126eb76145b3 GIT binary patch literal 16887 zcmV)tK$pLXP)z^9GRH}9L;wH~07*naRCt`#ya{hySC;2V%uEA=!8B?~BW+89L{Z=h zij*LV6u5$m2(I83;1*zPU<4x&J7Ptwh=l}6Nswe2cG`xWS&4Ky6PZpYD$|w7r3;l+ zU5&0DG-jsf15D3g&}d)=(+%_&nBRLR;_@d@UKn-&2Xtp2sZHdPs0l7 ziO}-L5iDd9P`q!_EZE1zkO=mjatK5)_#+7hzo>fA>^Fyg5Y7I8g6S5&P%ydL?9!f5Cth-UD;O2{Oj__S;wI_dnd68KRS z&HR@LX7IDa0HD^-s@}h<9EfHj8=C$0=n~CNgYfq!LBq-?2BwQNTJ|z76YN6%0D_$< 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 Date: Mon, 1 Jul 2019 07:12:48 +0200 Subject: [PATCH 222/223] Add support for decoding RLE24 Bitmaps (#939) * Add support for decoding RLE24 * Simplified determining colorMapSize, OS/2 always has 3 bytes for each palette entry * Enum value for RLE24 is remapped to a different value, to be clearly separate from valid windows values. --- src/ImageSharp/Formats/Bmp/BmpCompression.cs | 23 +- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 227 +++++++++++++++--- .../Formats/Bmp/BmpFileMarkerType.cs | 41 ++++ src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs | 6 +- .../Formats/Bmp/BmpDecoderTests.cs | 17 ++ tests/ImageSharp.Tests/TestImages.cs | 4 + tests/Images/Input/Bmp/ba-bm.bmp | Bin 0 -> 9000 bytes tests/Images/Input/Bmp/rgb24rle24.bmp | Bin 0 -> 21432 bytes tests/Images/Input/Bmp/rle24rlecut.bmp | Bin 0 -> 16748 bytes tests/Images/Input/Bmp/rle24rletrns.bmp | Bin 0 -> 20036 bytes 10 files changed, 284 insertions(+), 34 deletions(-) create mode 100644 src/ImageSharp/Formats/Bmp/BmpFileMarkerType.cs create mode 100644 tests/Images/Input/Bmp/ba-bm.bmp create mode 100644 tests/Images/Input/Bmp/rgb24rle24.bmp create mode 100644 tests/Images/Input/Bmp/rle24rlecut.bmp create mode 100644 tests/Images/Input/Bmp/rle24rletrns.bmp diff --git a/src/ImageSharp/Formats/Bmp/BmpCompression.cs b/src/ImageSharp/Formats/Bmp/BmpCompression.cs index be275019e..27a0e121b 100644 --- a/src/ImageSharp/Formats/Bmp/BmpCompression.cs +++ b/src/ImageSharp/Formats/Bmp/BmpCompression.cs @@ -1,10 +1,10 @@ -// Copyright (c) Six Labors and contributors. +// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. namespace SixLabors.ImageSharp.Formats.Bmp { /// - /// Defines how the compression type of the image data + /// Defines the compression type of the image data /// in the bitmap file. /// internal enum BmpCompression : int @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Two bytes are one data record. If the first byte is not zero, the - /// next two half bytes will be repeated as much as the value of the first byte. + /// next byte will be repeated as much as the value of the first byte. /// If the first byte is zero, the record has different meanings, depending /// on the second byte. If the second byte is zero, it is the end of the row, /// if it is one, it is the end of the image. @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Two bytes are one data record. If the first byte is not zero, the - /// next byte will be repeated as much as the value of the first byte. + /// next two half bytes will be repeated as much as the value of the first byte. /// If the first byte is zero, the record has different meanings, depending /// on the second byte. If the second byte is zero, it is the end of the row, /// if it is one, it is the end of the image. @@ -60,6 +60,17 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// Specifies that the bitmap is not compressed and that the color table consists of four DWORD color /// masks that specify the red, green, blue, and alpha components of each pixel. /// - BI_ALPHABITFIELDS = 6 + BI_ALPHABITFIELDS = 6, + + /// + /// OS/2 specific compression type. + /// Similar to run length encoding of 4 and 8 bit. + /// The only difference is that run values encoded are three bytes in size (one byte per RGB color component), + /// rather than four or eight bits in size. + /// + /// Note: Because compression value of 4 is ambiguous for BI_RGB for windows and RLE24 for OS/2, the enum value is remapped + /// to a different value. + /// + RLE24 = 100, } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 1ceb35283..906fc53fe 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -39,22 +39,22 @@ namespace SixLabors.ImageSharp.Formats.Bmp private const int DefaultRgb16BMask = 0x1F; /// - /// RLE8 flag value that indicates following byte has special meaning. + /// RLE flag value that indicates following byte has special meaning. /// private const int RleCommand = 0x00; /// - /// RLE8 flag value marking end of a scan line. + /// RLE flag value marking end of a scan line. /// private const int RleEndOfLine = 0x00; /// - /// RLE8 flag value marking end of bitmap data. + /// RLE flag value marking end of bitmap data. /// private const int RleEndOfBitmap = 0x01; /// - /// RLE8 flag value marking the start of [x,y] offset instruction. + /// RLE flag value marking the start of [x,y] offset instruction. /// private const int RleDelta = 0x02; @@ -78,6 +78,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// private BmpFileHeader fileHeader; + /// + /// Indicates which bitmap file marker was read. + /// + private BmpFileMarkerType fileMarkerType; + /// /// The info header containing detailed information about the bitmap. /// @@ -167,6 +172,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp } break; + + case BmpCompression.RLE24: + this.ReadRle24(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); + + break; + case BmpCompression.RLE8: case BmpCompression.RLE4: this.ReadRle(this.infoHeader.Compression, pixels, palette, this.infoHeader.Width, this.infoHeader.Height, inverted); @@ -349,6 +360,75 @@ namespace SixLabors.ImageSharp.Formats.Bmp } } + /// + /// Looks up color values and builds the image from de-compressed RLE24. + /// + /// The pixel format. + /// The to assign the palette to. + /// The width of the bitmap. + /// The height of the bitmap. + /// Whether the bitmap is inverted. + private void ReadRle24(Buffer2D pixels, int width, int height, bool inverted) + where TPixel : struct, IPixel + { + TPixel color = default; + using (IMemoryOwner buffer = this.memoryAllocator.Allocate(width * height * 3, AllocationOptions.Clean)) + using (Buffer2D undefinedPixels = this.memoryAllocator.Allocate2D(width, height, AllocationOptions.Clean)) + using (IMemoryOwner rowsWithUndefinedPixels = this.memoryAllocator.Allocate(height, AllocationOptions.Clean)) + { + Span rowsWithUndefinedPixelsSpan = rowsWithUndefinedPixels.Memory.Span; + Span bufferSpan = buffer.GetSpan(); + this.UncompressRle24(width, bufferSpan, undefinedPixels.GetSpan(), rowsWithUndefinedPixelsSpan); + for (int y = 0; y < height; y++) + { + int newY = Invert(y, height, inverted); + Span pixelRow = pixels.GetRowSpan(newY); + bool rowHasUndefinedPixels = rowsWithUndefinedPixelsSpan[y]; + if (rowHasUndefinedPixels) + { + // Slow path with undefined pixels. + for (int x = 0; x < width; x++) + { + int idx = (y * width * 3) + (x * 3); + if (undefinedPixels[x, y]) + { + switch (this.options.RleSkippedPixelHandling) + { + case RleSkippedPixelHandling.FirstColorOfPalette: + color.FromBgr24(Unsafe.As(ref bufferSpan[idx])); + break; + case RleSkippedPixelHandling.Transparent: + color.FromVector4(Vector4.Zero); + break; + + // Default handling for skipped pixels is black (which is what System.Drawing is also doing). + default: + color.FromVector4(new Vector4(0.0f, 0.0f, 0.0f, 1.0f)); + break; + } + } + else + { + color.FromBgr24(Unsafe.As(ref bufferSpan[idx])); + } + + pixelRow[x] = color; + } + } + else + { + // Fast path without any undefined pixels. + for (int x = 0; x < width; x++) + { + int idx = (y * width * 3) + (x * 3); + color.FromBgr24(Unsafe.As(ref bufferSpan[idx])); + pixelRow[x] = color; + } + } + } + } + } + /// /// Produce uncompressed bitmap data from a RLE4 stream. /// @@ -545,7 +625,95 @@ namespace SixLabors.ImageSharp.Formats.Bmp } /// - /// Keeps track of skipped / undefined pixels, when EndOfBitmap command occurs. + /// Produce uncompressed bitmap data from a RLE24 stream. + /// + /// + ///
If first byte is 0, the second byte may have special meaning. + ///
Otherwise, the first byte is the length of the run and following three bytes are the color for the run. + ///
+ /// The width of the bitmap. + /// Buffer for uncompressed data. + /// Keeps track of skipped and therefore undefined pixels. + /// Keeps track of rows, which have undefined pixels. + private void UncompressRle24(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels) + { +#if NETCOREAPP2_1 + Span cmd = stackalloc byte[2]; +#else + byte[] cmd = new byte[2]; +#endif + int uncompressedPixels = 0; + + while (uncompressedPixels < buffer.Length) + { + if (this.stream.Read(cmd, 0, cmd.Length) != 2) + { + BmpThrowHelper.ThrowImageFormatException("Failed to read 2 bytes from stream while uncompressing RLE24 bitmap."); + } + + if (cmd[0] == RleCommand) + { + switch (cmd[1]) + { + case RleEndOfBitmap: + int skipEoB = (buffer.Length - (uncompressedPixels * 3)) / 3; + RleSkipEndOfBitmap(uncompressedPixels, w, skipEoB, undefinedPixels, rowsWithUndefinedPixels); + + return; + + case RleEndOfLine: + uncompressedPixels += RleSkipEndOfLine(uncompressedPixels, w, undefinedPixels, rowsWithUndefinedPixels); + + break; + + case RleDelta: + int dx = this.stream.ReadByte(); + int dy = this.stream.ReadByte(); + uncompressedPixels += RleSkipDelta(uncompressedPixels, w, dx, dy, undefinedPixels, rowsWithUndefinedPixels); + + break; + + default: + // If the second byte > 2, we are in 'absolute mode'. + // Take this number of bytes from the stream as uncompressed data. + int length = cmd[1]; + + byte[] run = new byte[length * 3]; + + this.stream.Read(run, 0, run.Length); + + run.AsSpan().CopyTo(buffer.Slice(start: uncompressedPixels * 3)); + + uncompressedPixels += length; + + // Absolute mode data is aligned to two-byte word-boundary. + int padding = run.Length & 1; + + this.stream.Skip(padding); + + break; + } + } + else + { + int max = uncompressedPixels + cmd[0]; + byte blueIdx = cmd[1]; + byte greenIdx = (byte)this.stream.ReadByte(); + byte redIdx = (byte)this.stream.ReadByte(); + + int bufferIdx = uncompressedPixels * 3; + for (; uncompressedPixels < max; uncompressedPixels++) + { + buffer[bufferIdx++] = blueIdx; + buffer[bufferIdx++] = greenIdx; + buffer[bufferIdx++] = redIdx; + } + } + } + } + + /// + /// Keeps track of skipped / undefined pixels, when the EndOfBitmap command occurs. /// /// The already processed pixel count. /// The width of the image. @@ -576,7 +744,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Keeps track of undefined / skipped pixels, when the EndOfLine command occurs. /// - /// The already processed pixel count. + /// The already uncompressed pixel count. /// The width of image. /// The undefined pixels. /// The rows with undefined pixels. @@ -1167,8 +1335,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Reads the from the stream. /// - /// The color map size in bytes, if it could be determined by the file header. Otherwise -1. - private int ReadFileHeader() + private void ReadFileHeader() { #if NETCOREAPP2_1 Span buffer = stackalloc byte[BmpFileHeader.Size]; @@ -1181,11 +1348,14 @@ namespace SixLabors.ImageSharp.Formats.Bmp switch (fileTypeMarker) { case BmpConstants.TypeMarkers.Bitmap: + this.fileMarkerType = BmpFileMarkerType.Bitmap; this.fileHeader = BmpFileHeader.Parse(buffer); break; case BmpConstants.TypeMarkers.BitmapArray: - // The Array file header is followed by the bitmap file header of the first image. - var arrayHeader = BmpArrayFileHeader.Parse(buffer); + this.fileMarkerType = BmpFileMarkerType.BitmapArray; + + // Because we only decode the first bitmap in the array, the array header will be ignored. + // The bitmap file header of the first image follows the array header. this.stream.Read(buffer, 0, BmpFileHeader.Size); this.fileHeader = BmpFileHeader.Parse(buffer); if (this.fileHeader.Type != BmpConstants.TypeMarkers.Bitmap) @@ -1193,20 +1363,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp BmpThrowHelper.ThrowNotSupportedException($"Unsupported bitmap file inside a BitmapArray file. File header bitmap type marker '{this.fileHeader.Type}'."); } - if (arrayHeader.OffsetToNext != 0) - { - int colorMapSizeBytes = arrayHeader.OffsetToNext - arrayHeader.Size; - return colorMapSizeBytes; - } - break; default: BmpThrowHelper.ThrowNotSupportedException($"ImageSharp does not support this BMP file. File header bitmap type marker '{fileTypeMarker}'."); break; } - - return -1; } /// @@ -1218,7 +1380,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp { this.stream = stream; - int colorMapSizeBytes = this.ReadFileHeader(); + this.ReadFileHeader(); this.ReadInfoHeader(); // see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517 @@ -1234,23 +1396,34 @@ namespace SixLabors.ImageSharp.Formats.Bmp } int bytesPerColorMapEntry = 4; - + int colorMapSizeBytes = -1; if (this.infoHeader.ClrUsed == 0) { if (this.infoHeader.BitsPerPixel == 1 || this.infoHeader.BitsPerPixel == 4 || this.infoHeader.BitsPerPixel == 8) { - if (colorMapSizeBytes == -1) + switch (this.fileMarkerType) { - colorMapSizeBytes = this.fileHeader.Offset - BmpFileHeader.Size - this.infoHeader.HeaderSize; - } + case BmpFileMarkerType.Bitmap: + colorMapSizeBytes = this.fileHeader.Offset - BmpFileHeader.Size - this.infoHeader.HeaderSize; + int colorCountForBitDepth = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel); + bytesPerColorMapEntry = colorMapSizeBytes / colorCountForBitDepth; - int colorCountForBitDepth = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel); - bytesPerColorMapEntry = colorMapSizeBytes / colorCountForBitDepth; + // Edge case for less-than-full-sized palette: bytesPerColorMapEntry should be at least 3. + bytesPerColorMapEntry = Math.Max(bytesPerColorMapEntry, 3); - // Edge case for less-than-full-sized palette: bytesPerColorMapEntry should be at least 3. - bytesPerColorMapEntry = Math.Max(bytesPerColorMapEntry, 3); + break; + case BmpFileMarkerType.BitmapArray: + case BmpFileMarkerType.ColorIcon: + case BmpFileMarkerType.ColorPointer: + case BmpFileMarkerType.Icon: + case BmpFileMarkerType.Pointer: + // OS/2 bitmaps always have 3 colors per color palette entry. + bytesPerColorMapEntry = 3; + colorMapSizeBytes = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel) * bytesPerColorMapEntry; + break; + } } } else diff --git a/src/ImageSharp/Formats/Bmp/BmpFileMarkerType.cs b/src/ImageSharp/Formats/Bmp/BmpFileMarkerType.cs new file mode 100644 index 000000000..4abcaa3a0 --- /dev/null +++ b/src/ImageSharp/Formats/Bmp/BmpFileMarkerType.cs @@ -0,0 +1,41 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Bmp +{ + /// + /// Indicates which bitmap file marker was read. + /// + public enum BmpFileMarkerType + { + /// + /// Single-image BMP file that may have been created under Windows or OS/2. + /// + Bitmap, + + /// + /// OS/2 Bitmap Array. + /// + BitmapArray, + + /// + /// OS/2 Color Icon. + /// + ColorIcon, + + /// + /// OS/2 Color Pointer. + /// + ColorPointer, + + /// + /// OS/2 Icon. + /// + Icon, + + /// + /// OS/2 Pointer. + /// + Pointer + } +} diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs index ca90020d8..4d7f78100 100644 --- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs @@ -388,8 +388,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp case 2: infoHeader.Compression = BmpCompression.RLE4; break; + case 4: + infoHeader.Compression = BmpCompression.RLE24; + break; default: - BmpThrowHelper.ThrowImageFormatException($"Compression type is not supported. ImageSharp only supports uncompressed, RLE4 and RLE8."); + // Compression type 3 (1DHuffman) is not supported. + BmpThrowHelper.ThrowImageFormatException("Compression type is not supported. ImageSharp only supports uncompressed, RLE4, RLE8 and RLE24."); break; } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index a95703609..dadce92d1 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -228,6 +228,22 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } } + [Theory] + [WithFile(RLE24, PixelTypes.Rgba32)] + [WithFile(RLE24Cut, PixelTypes.Rgba32)] + [WithFile(RLE24Delta, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_RunLengthEncoded_24Bit(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder() { RleSkippedPixelHandling = RleSkippedPixelHandling.Black })) + { + image.DebugSave(provider); + + // TODO: Neither System.Drawing nor MagickReferenceDecoder decode this file. + // image.CompareToOriginal(provider); + } + } + [Theory] [WithFile(RgbaAlphaBitfields, PixelTypes.Rgba32)] public void BmpDecoder_CanDecodeAlphaBitfields(TestImageProvider provider) @@ -521,6 +537,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp } [Theory] + [WithFile(Os2BitmapArray, PixelTypes.Rgba32)] [WithFile(Os2BitmapArray9s, PixelTypes.Rgba32)] [WithFile(Os2BitmapArrayDiamond, PixelTypes.Rgba32)] [WithFile(Os2BitmapArraySkater, PixelTypes.Rgba32)] diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 3c732c32d..754ce20ca 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -231,6 +231,9 @@ namespace SixLabors.ImageSharp.Tests public const string NegHeight = "Bmp/neg_height.bmp"; public const string CoreHeader = "Bmp/BitmapCoreHeaderQR.bmp"; public const string V5Header = "Bmp/BITMAPV5HEADER.bmp"; + public const string RLE24 = "Bmp/rgb24rle24.bmp"; + public const string RLE24Cut = "Bmp/rle24rlecut.bmp"; + public const string RLE24Delta = "Bmp/rle24rlecut.bmp"; public const string RLE8 = "Bmp/RunLengthEncoded.bmp"; public const string RLE8Cut = "Bmp/pal8rlecut.bmp"; public const string RLE8Delta = "Bmp/pal8rletrns.bmp"; @@ -262,6 +265,7 @@ namespace SixLabors.ImageSharp.Tests public const string Bit8Palette4 = "Bmp/pal8-0.bmp"; public const string Os2v2Short = "Bmp/pal8os2v2-16.bmp"; public const string Os2v2 = "Bmp/pal8os2v2.bmp"; + public const string Os2BitmapArray = "Bmp/ba-bm.bmp"; public const string Os2BitmapArray9s = "Bmp/9S.BMP"; public const string Os2BitmapArrayDiamond = "Bmp/DIAMOND.BMP"; public const string Os2BitmapArrayMarble = "Bmp/GMARBLE.BMP"; diff --git a/tests/Images/Input/Bmp/ba-bm.bmp b/tests/Images/Input/Bmp/ba-bm.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d2615bde3e6dd7d1b43e715183bf0fbdb0245058 GIT binary patch literal 9000 zcmbuDO>9)hnug2R*!ck#2qZK_EHYW#xHq&5a6=R`bCDw(8J5Tm0cqwMwnw{eP+dP&MkUa8)a1l(I@i zN;#EKDxp=vsDxFCNF|&~E0xwNZB*K-bfnTw<&?^4l`|@5RW4FFr;17ywJI7_w5k}X zqEi*6Dq2;Hs#sNtRK@XZ<+O4}IjdZx93PZcS}UWK)hgniPAHwwI$?Ce>O`ayPN$Vl zYn?VaZFM@*X{U2a=d{ilowGU@>73I=rHfh@jV@YUjC9fIiqaLWD@IqWu0*=xv{Tw? z?TmI-yGT29fUS)(Mp>gGWSN9A32hR_B&$+a!q$;8k+PAB2qQ|UD50Z-i4rzSL{Y*;X%(e) zlr~Y?M(HR@yC|okoQ`rP%GoFvML8E0RaDeb(L_ZX6{D!=qKb+tI;xncVxvkFRb1p$ zrW1*2Ymc#9v$D1LX>eW_i$BqLB zj5%daojOb1_~8ci;>8R9CkbDlQ(u4nwXbh|{q)mM+^<&+)Y`S{)@|6Zal^)qo2mET zd!PF7!w)lWE~al)TkCghJ+Sq_4s(F^=Ip5-&fY-4KW@B00DDnJ;&U0&9s%FV`1U6m z^lwlN^=li}HLP2^VIA!^Y~J|Z=Jyfs@9%$zfNXO%lkJ>6@|k?+g2Ut03;zM(7YE?~ z;jG7Bz%T8k1Yg=q1%6d8{Og2Y9Dx75%^rV6{y|I$2j4;UDv5wj1au={82%sOzlr@X z5m1l9B>WxlchG(S0hbVPiT1xBpwZ87XhEd*)JRl0m|p!8S+1MI?i7L z5Ply3>z@EVCxEX9$e#ed^#QQ{8ksNor$YW4cgOil0K%Uo>*^!V=Wq;irhP*de>eFH zKMvfu8S{GwVt(&H%+9f5??BrYHmsGZrR<^y8DyXHU!Wf0V}TjuoHxz{Hadi?*t$IABVxG zs`=ymCH{r^HnF?Ek36rE|0?WnLO=!qSpb* zX#bn%7Y71=rX%C|p@&}_c=Ss<_U}hP1_4Ifg{tx`W z`TXbkL;isude6Tf{?0Hz)zi|`auoi)*1k{v0{?ON-#Apws+yXHCi2UWKLK>-$)5mj z`T$se@UMZs8G#ub$UuJ*0apm%itx8%zNfInQxrn2FU@FO7bFWB$Zdp}bcB!4d;*~Ie6bY{D= z@Q)0SVE>}l@kjVio(%7=Ji7Aek?CS8({*i0L*KRG> zpRUUDOMjLC{O#?H?O(tzS2EdDc=KiJmwg1#C;SBrko*fmPwt$3_60G3{8z>KBY^gu zBU#Cx9T1)r{ET1mgC?{5SFSu2{`Qc+-17O$8x~+60(}12c>OOv=ea&up#Q43Ry9$n z6#SwwKSJHQwoHEyxrD#{i}wAq{H#CefAnY{2Ec!OHvi?a7X#?uw5sW?R8yuYlj8Ro z0!H%JMsAJ7{J*VV^RbNPY%?Z!{z9DpQ~004zrTI|7vWYm6X$=l4*`GaJC1-i?Eb-+ zpZuwe@QVZRUmFSeEA`u&^=sD9zS#?q{)Kt}X-|I=nB&g`AzvQ#_?}<#m+U3?xdU>^ zzmQk8*sl@Lg@7IeSollu-wscL-#bA2*xSr3|5eZ5kNqcNewJC71^+nqUl4xDeeogL zhhuU6fqy=K_}3$#nGyS6C=^1It789C!CxVN0w8}+KJUOBd2j%J4ZnuJ3x1SlE&R7< z`4_E!?4RTJ`770aqKZG3wqTYD^gP)+5zbi8ko8~72GHc+Mg9c9<&lxnT>jNhlJv9S z&+=cr`c!UXz=_}p|FVZS)wAUNT<)?47B~R^+g1EMf4TgDklf}+m5eD>Tf3_EZTNLps;jFf)6)aLC4hMU zEl6^90ffd&U*-3l|BhNP%U^+gSqE0ge{TK%wrTyQ^?TOu`S{4}{+r|X&wbh-cNA^> z^AbKC9cTZKv;Qv~M~ati;kSs0k38pmiTrD8Yu~Qb)XtsoQ-y-1ZkNKm-)X;T{l_2g zVT3ETz<=DyBjtEH(;o|vPlJ4)`^(mjkB*Q3_xObi7vgWE<+7J+^w+iQf8C|KcC!C_ z3O%;K>bJ4~zk7PmeBP;qMauF7V+m+1dPm-vs|A==ab*umyhUcYQ|qg9CwoF#OG^1)qXHp2cJH%N?o? z`?n$BAOd<3Fbe;51eC**mae3j-_yfC(f>{VMfqDUO!9lqYg}&D((ISZp8yu*zu-x} z35z2%xqkin%#84V6Gt$g|I%5@)ALnQSGx`VUGN`-f2e1uXB7T&;9vCpBaABR`%CuM zXRgl7O!Qyuzxd7fND}@j@5JJ1eikc#ew27$lA&tr$bTF8A0&SQ=ox~a0G9jymG(zG zKiNwO{{#kHJi#Jl{ZIP*mubIj_Oc$}e+T|;F@G=l&+*G67uS(<2;ibE)BZUECi=gF z|Kf?uT$~)7T>SUpb6);c@rU;y(0d1j9|3xs-nH{!S8q=*{H$JEX8$j(Bb4X2o<8PB zz=?||h+uG%^|!R(T(RQ(XZfr0FFm{c>h`POw`|%gW6v=e&@*Ip!2euEoIm_0F8`JM z^Hcd!SU;n8#_x^ay8yL}<+Atr*VWb5y#xQYgF6o%?Ct6uf`9b7yeesH2lmTF9-gDr{`NEcu?Z(^Dl(;UsqT6PTe+Y z*Dm;bhcIB2Dq{fruY?}~dt@AgU+kB`ea7>d=MxhX-%VVkzW*Nn$tesdQDOeQd-vkx zJw5LipC$h~_Ww5a|1S1_FZ+K8^`qs|voiU=`UCk-u>UWT|M%oSN&ZvJFO^5{l*#|z z8?uk{#{l6!DE#68{MSc4zVL66+DjeVd(784s(en|DVLu=7k=`mE(^an0RQz;m@oW7 zyxdXZda0mRWB+yp974ch1dR2L4*hLZ)R)Vz5kU7%d$(ZzUe^CH0yu{G=UD$`>@Po` zxsUx15bzKIj}b6ES(^HLN!*k9@Js%Zz2rW3$SU!NT9kj_5BU>76+aHl@#6qRd(U5; zf8Y=K6M*NZ^|Avw!oMB>^z_#t||3e24WB<_5*ytGcmqoy<*K_MXlt1f#LH@J+w4dYm4y=$r>%S`h>zx>`OG~ zpg;B_;1B|6e`xIR*csZ7`Su9#_7ec@y@2yyoj*@|FF*qD_9NgS0%-qm`tkG=+E4rT Q2$1ZULrsrd5Ic*u=J5JO7upf6L5xpYbZ6D)35yuy{>9Y8Hpw~gsTdCetWbK0`^p@)AU2%9^A!&oE zBItqVC!RMb_<&|2D~NhM6V=WwrQS*+;Z!V1u|^bHc?+%3?eU7IKNnALj)+v-ZJVKz zdY&oT0H*l@vmkBkcpH^SrtXB`F>>)XcD#*@-rF>(&7_GpC#4P_#}Dd6+P33uyGI#s z$8Az4(zYFM+cTk(oB>I zyluabI*GFGUz^^)HYoloU2FJ88b_8(HHoQS5o@dT<+IYm=gmZ0r z=h~pqtMsek8_9xDDbAdUn%y5n*^|lYBS%lNG$%7zW~!o?5?M#0a>`_ptc@)5HHMR! zsf>-R`S@{`nJn`aWF=E3YkQo@GG9SfGG(&1lG9|($5&d&$xN2wZZuhAI9W#Vbu?LG z>U4~F9>d8@mSQ+rk!2@a#Ez-G+aDA)y(TLYM0psV_Ah(7edB3zvxAhs^0Y|kKC>&W zIsP)UQQlk2Y$bGMHkvaFim|oKRzfc`+n9I^XX$Qp)c13r^rxeC+^4Tv_jT^Aexq}hd#m5*U*+EF zH~Ks7C4CV84EM96hOZX);j30ZBhoV;F#*TJv2mYjhIY66i+H`i+M2d%uk2T+nE@Vw zPnl1wX|f$^hk)M;T4y^6zYOQt>cPA=VB1=Dn=yQTZmv3pnVo%ti%=&TCH;D{Er zMI1p681(MANJal^j0LX z4^D3r8ETzowTejA87*;*NVho=1Dm6lxLpugu@RYc?zF@;F5RA`rrVKG&7Pz)JEgYj zYc(jSW1&+7%BZhRXGPW5seaJO99aD&qrIc{Tz>F=CV;E;kvj!rFv*>QnMq`}wT7cg zZ>gT9D(!WrVAMS)qhdCDH+>|-AJK8)rmvmVL{fme6e#9%r&dxdjMGt~S*vtVX{9>_ z=rp{`Gh3!rLJ#SFrK2=byY^qv%FDK=cTPA3*G%AXtE+NN@61u?rXCcnC(hA0-OsvR z_D<{|RBh{LP8YPQ%2;x0|BQI-IkkUQgiV;8Y2B$Hi{7Un?A7z~XJjr;5v6Ir7oo}N z9&-rQiTkinL3%mw>3VUxB($gUGqmr!D0fJg#A@|VpP(T>7r$<*MxR*>@f=s(i$!-q4551Vh1ZN5+EefY5XR-7jD{e`0V_DYy( z8uk*2siA}kRH+a~7A7OqC4bp+nhcVkmnLK8H3JQJ-4QO-b>tLDw6hs|)sBVwZk`0u z9`@o!4}A4rJ`OoL``Khf&}{9q$zUv3CKChDz}cJvWz*hi$oqCcI>R4A>9cP5 z{jKd%WcZ;xzRLkuuO$zfMHez2)8kiiVEA5h`qip|3{U#mcNQ@#iq50=SaUHP?|jWU zgIjJ=>XUz8n5G$9tuxB+1`g(S$5|r@v{T{btF z1CeP3%bv+ucP=PnLY@XyL|V`wvRED~d>E!CfqoXRj%ca@0hDD902 zY^wJ%kaN%5fUGt2M)HC0p>SvLc~@m5Yifh5OyE((zH7t=SG}3`2HKnE-FD=={q%U% zrW;Vs+}l%u`&i2po_$Q#gO8vjY8QHm>Ph+0d`Dbis8N2!I!aq_;))i^sCCNE2UX>b zbtI48r&AoM!Ph8f*zW(zxr*{*IWPJjuPE;w_5<6Yc)4x&S?^bW)}5F8rZex{H{EmJ z)PDOvw|-m0;x~N3_aP}yzD+qkQ;%!D5qr%65W82Jww%PD6D> z%qBP0XLY-87eF=sA8p6*V02fs){Z5clafPAO6NK=u`|Rd0a1| z$`}2SUb+|Xlq&f;?Z@l_gK}pZLoFR@zqtv~k{fsQmM4zstDuEYfsqn#WU+ysxGt1L z-I;W(5XX`9<8mmw7%Ii2!sp^MbcZwP(Mw^3yniEwBW;82=P0T*YKW^Y#*vQ#CdYm| z>KE?O;ntifSKv=`rpPny2kYT}&q|@|noQFv-`RhvZ$GohUL7z5{;fZ|(t+hv&mGGw zdrsK1dv4wAPZTd`6+A^lB}`HUQuZe`=wnd@OkwAzBVbvc9BB0XyTz!3u=w!et@5K+ zys>{CzU@C5CGCwH*|!((t8rV27vht{sn7B$I@IbqNmF%Qk)*4akfw>U>Pf3BU5KQ* z?i58v#F6`3hk;1Ju|ILMf4$VusO})gQF|e9`ILCM|LScFH4G>Hpg#h|v?@ABD!QmP zT-Pa9E?gbZJ)AjIZ);sxYwM@ApSEC%_e&(|I>r#27KWp)s1>9DVSkx*i*fu6(K^_Lkw7@8QU%UCGZtI@%>NFN5~90FG-5P}F>t1&H<=7l>YK z0+yU#(GK&s!@Ea&uf8hm(`4G!^_x2j1d0jbIs^8`y)%UfG=HQU?+aIv!d~Wx% zB7Iu@Gq)S({M0^-_wm;fe6K~~|6}TH%;ho7b)~my3FDRa*T&mR-aO`%?jqXxvQFvE zd;0--K8aRnh&BGnFV3fw8o~Kq|L}_4@$*<9>AosneT~R(Umg~)>Gt^%riXWp>O9L; zAEci*EBBFY4$j(krenxT9QndfE^i2W?x;RnUm{)Xs8**_Wx5@Y99675f7=gn6;|Hh zj~UYjYjg@&<6eoRt0 zFLyAnowvW9Yhwxsgl|8lROoaDuw;ykE=$$Sg-*Ar%?H;lb+u*+ralQMQ>pG!!DUmQk(ycaajdIK+~~{z8H+nH0g9ix-J*Kwt2uYd6{SS+ro^+Wl|Y4*q+z@g z#R5s49KNrszOn>F?8|SJKsYDgFygB|-)bc&bn5h?hZKVz0i^d1k5FSd^omFPcCEi^ z`wW;EHxB+od60Tk9#oWQWt~|`V$y@wSc%_({!YWcaH}&#h%qQgyGy2#GU+lYh9ZSX zfl{KJ%dYu&A+nFNaFws)_ek{Z*;6_UG%2l!>)PPK@lk@O=t(6`KoN8#7q((0i^Pb; z2`+N|s1Y9H_vRZdV^2D1Y?2^E*ocPj8F(8$?K(9yG!aIV(Xu7MIPCRX`5!qkPgF)V zbMKqK_vSh}Oia*)1u&y3ql-$@kuM!}QET*tuT{-)o^(%rR$B`%nJ3*-e^EZv)Q?g? zX^{EA)RPj5yRoJ|rcbK760cM&uVQ&TUsM^L>9-?|g5+~~NS$4M(2V|f%s>uf*n*4w zM2+$jHJm;~<{>t?KprK8xKZD|MV4F`gN8v=Z5orHMofaMq*;Exz`=Hj=(G#@&0Sh~ zoaie5TJlxzMPEXP_Dy~asXU3Pz@^#14*_CZ^k2ezbMJ}aoN?!mQ08^gZ+@}In?2w3 zd-PeKOEHR#Bp#(d-mz+pQ(>Uat`L94{VaBI-y~17yFb zu!lFeYHW#iah-JI(R|;x>+S38D<$(+sQbWq*Pcdbq-Ass#q56-0$R~S4e^Lw^h^R(6 zGM_Sa_oCVJPu+fRWCEz7_^bXc-#tZqz6-vjvSU*&to~YcMST~X?-R^q@|WDu%{OmB zkngnemo*oDOLs9FJacKG_mkJL!4}^I$3%m%w{lHkR*Z#-7HRfQDJHGz-0vD^&SAUX zC$>X1(pa0@=9J4n@YFPqe2+bsE;4vZTBQ|#pk`VTir?RbV&ar(l+n*K9Hvh}&ra(n zPQAHuxTuOqAH8&y18Lnd`=Zj33D=Rso89K6HW!T?KYTQLA1fAD=vuBsE8B$3#p#5l zS@qq1;;`Xxa5`Ca9Wyh`r*Qv0fZ$G@S@X^?o^s`QXF7D>4y~JWHy_m;FadXblskws zvD`sCa|iJ(_tan1NQ3NYNU|jLDG7Z-yYSdIazE=8d}^w_%}%)Kop6Ifuh2*SH~iF} zujO%yBgYD)K2r>>@|ZK7;&P_bTvjYPk1(pW#&l9{G&;>_)Y;Y{>C`M6O$4LSA`MvV zBQFuNkIAL!%=#fNWL&dPTU`KBt=@+^mqwg2a~ z_E#rRv1vJ4OFL}jJbA9WJI;0!EG@}%N9FvL!%IaTrO+q&Zd2|`%bDbb<7OrBnH;xg z*d$LX^KVIR45KvdnPl_aGhB|SX}ERVs9RkRd;!Ppxy|-Hec!uZB>yqeJcog!B*W2A zQO1JDw?5gjC{u%FPaZ6WS?7Xe8gh|lCqYj@)QqIr3G!nq{Updmrtp%8mj7xJnvpa+ zk^DSj05TGJiS0xwpv?;&{=pVS88J35c;eqh84(w0cA~cP&|cE4g2oHl7GCd+{K_P% zwtiaec?PJ7H3`auGLou^V-lMDI|&~(ap&gTfl>xH`O9sk5C8MYjhip!_f)h=Xqm8@ z15JK=dY1#ufoc+>CSK;i9XD@PN1KGou`4&nsG29uGHXTF{x#y?vtKj7y#-T*_R-)f zPJd!6{Db}7L`^(V6Z2a>zQ;mMEbdJ_0?=p=4mRQ36IX2$jy+M;G6Qck59z7#)^PfOuDm>k6?3y)DN)v!1E)|k1+ZG zn-4rciPi4?8#H^sRD;jAL1ywP7Y$RDO5UQJ5T;?Od<~Pk6z}TP_|xaHPULF}wl*^T zCNnA$I5_oEru^k)>LwR8ty;UZl%W`Z-q7jBH7vPLzgt#sl%ijY&}ksDAzOj=@z}Hy5248{Cl2<-Y z>N7X@$ViekT|GO4#Wtdx!K|zd4>NO%$RzvEfBE0$e|r5Ne*T)TPwktwqyKMzYVGG= z`iHmQ|L^%jdusdEo}b!o;`QTnXtbl-sU1)4T#?T1d}&Yfm7h!7@!CEtOLOBIFYR?| z)9%=gPv>@i;`No+*SXD{m!~b9_dz*5Kes21$jI$?>g+Wz9mdW`5{!LVGf*}cy=8bh zB;d%~<*K)&;z-9Mv`Hg8kyniL8#**n8zXN?bd0y(N3cWjUUX(_tbW566ga_Rn!n#Oa;=;9(aE z2=>1g_9OddAT$8#!XDHswwDJA*nz8<7vitH?!fQ~)TD@eCFIyb>T5v+R*IlhF%bhR zx4;VAUWCwx64lav2|n%P8IY>o_Zu@!J*4K_@2B7l!G-3gL3xvk!1}uYddyzRn+D}g zAmFwv>Srk+0;wE*TN%Fv4C!q@sBV7*9k=s7wI{vp2i5IokaJu1sXbIT1#hUjX7LBl zBJ?*+0Ac+drm5q2I8M^sQ8=E?)1bTwAgfJV_+d|f%tPe zPWwU_N4*Q0k=) z$vEgh3b>pj&Qmy$b)XmyR64K&ZQ`JSqx+u~yOLFxtO!6CPW0;|N#8k z$*y3&R$yih?CJMqXkGzqZg2FHi#X@LZ$I?$jT73VK2Zr-59x$MC8Qr3{WmKio$Aw- zU@m$+JgfwB(d%Jb2~m0Nla-+L#f}&;9nrpMJ~C1RFcg(=KAk%&iEl7*f84+I@#>4n z>gzhy&*Pg)2yd^o1J!DIikMa5wQ2CCtO~i(xicci-0%{!z%{hz`XEZ&;(b(y28kMp zPSyq0u|KYiP#~_6=ww|`9d7KB@TO=UXI*n;OB%V9#$2@9tN0J@xv}f>+WS*@?u}aR z_4EECTAXqp)PApySx=22EjzC|u6jiY%+8C(SoUK5qa%TJjZr49l!^UWI5~U4J$u1D zd%-<>!99DyJ$u1Dd%?X{>Cy_KtktajQEwuf$}HA0rNv(O=sgWFns+ml?^?kWZm(eV zt@?L6s*wiHj_BAQU6j6Bc)$Zk<*sJM_D<)CEnvppvOB8qj2&i2l_fz3jqOe~`wMOf zcvY?LV^`TDSx32M#YWwN_I#KX*-h-(9|iJo+|^fpX{1m8HoL4cTX|U z_Ys`|k}d|eE;%~s=!QSAFZX;24TX{b9zC&>P>^s!%m?mGPZPV!iTl_|yGjW;^gAsf z)-ct4Cs#2t$POd8R zA6Z@2tcri`k9?<`{7VH~Q&&E&(T;sMO9d4>|EYz89D6AhxW7(`v^6VvbHu1U-l_t1 zR}m^;Lqicpg#5UxunH<_H);Me)^2jEg|*T?YsHNE9QAU90G@zM>>{V&p8MIAdtm0R zArCJL)YHp^z3yixJ<)Kf-Fw&zc)oz+#=}0ihKNWF7XUGjomiD;xo!e3W0jsItaLxC z;`uH|HcZ~--NaM+jh_glS8+}qzgZ`E+m8%hC7ptn>?w4rJ4W+dIttu0wtWh$7^Ca- zSZe?}J-UEGq3Rny>vW^md!5>?B5rhQx2lLX(d??$gZ3AZeb(J^(5dq`_JES8GlUeX z9UlxFFSAi69>c06&+B|7^>8cZuvO@&vLB%@r+DmEJb&9NHrCxPTKN{w-}t#qJb#HBMnJ|nu#@p zB&oO1&^06TSwcxj-%4U)eI|Cf$6mLckLM<@EA_ZPs;7IMH6-;=4WS|V#a;er=ol`S zanO*|V+~#AV|bl4q*xj%PqS`*v?vXEwaHS564oNH7IH0nCIJRag4|CVxFR9fz)c}r zS7M-xO3w!4;wjNwaHOap!JSo3hm`~=DoWU$QB;+^YB@;Q%~tqUKjb;sWu4D)H?GtBn5h`}wtQ66P$dZdVI_|BGE%5YNFU`&1%K55 zd#_)#_OpjY%I{uV`^q5Zsy+DNG4>zUaGd#pF+;cHrN8{Il4%;A(Rw6Sp;eOo5&B+q zjFieO79B;yl+iFrNCA_C3STme(5g&=1xSj;Bv`52^RIBwRd86?;k;rbfDYQ+xYfAm zOS>~*3QRhC;_XxHk;?Zw7^DB1?FV@XKqnNO^<;WV0YZqqd}qs9&ScBk-@{<6?o78y z*Y+26m?d^#3cA3nJj@nU1!otWg^N6Y!&3(%vteuXgdmJFYeW%NY<i^ZI;1aNl^SN^4X_9`-b2Kx*F!EH}$~bpp8p zX-CX{$ned6{MJ%E-}JqtDD*Xp_hyvQw!{6TWx%6JqB( zT*t@XbPk^2tlHxV&XFfLJWCw?0tH2dT5HHH6i1OtXceXz zv3LC414fMVfcBbJPjO(xTx85k=Poy86ynx&SBW!ex03jJl{AK!bouG8s9`Zk+N%AX z6dR4Hw`Y7urLMNuoITT+riNjr?EQXI_-0MUq#pDmk;ipgzY;g#`7O|D)OT>}O0F6n zxGjds@t3W=l9bso7SPT7)o=nr8CMMBDQ}<(NWuQ#t94KcsSE z_urLGK2ZU$?P0N*Z%XH4S4+uy%GkfM%ZrpvxZB>glLe?o_V+`)RFNg zj)2(FG&o@hmvb5dovX5w8x(~`(EDYn*Sc5!fv)(hQ&(z*=u_6 zCEPdS#I4$?5%J*Tg=fWmmjuqm+Ly3)TKIkt7k!X_ul(?F zh^m{Fo6n?L8)0Atq6G|&sZ9+@EinX|Z98Bf-RjCzlwW|ND<*# zFn3AmiZec@3%AoA-=GkgFYdORFNq82>^K-lxzknU5{(Lf1sE{H?i4t zJ6qTHXY?8W+s0R*kZp)};^V$FCsZ?+If2M5Da)Lc)u0;Xndp$H@5V+gfWb#=p(`SW zV--`;%v!UB(;U+W1YaX7)Ew6JZYxy39XQ|cT*u$6Q0_6eya(NyS+s4fhP#RoHFNY8 zOu9+u(fCcam|N{fI>th`QJH~pqHBz2c|~A+CMp4AJd+HA2xFCp;uhn`1`GP<#5mNI zNMHCCU}9{ffqdrXlkeUZ-cb&Ht;-t?MlW2A;$2Ln1@?kJc8IDj%ZvBkBYk$Eyj5^acda1h zP!&|X%6C_GljE$Q$Lz*_h525&JIz^>H{VJ7R|~+RBQDoPF+eD$i|+zq#!~dRSzo}w zwY(?Rwb#np_HPt$&$rm9b&%g~SudFf<-vWjZWEET1;omFnqAG0%kgx3Cld|-4CXn; z_vSc77TUgM+I{l$yWr-s73jAPB>A{6iqAlbqfasQ$vR}#%XMZwSeA@h60TYjCO&K% zqSk{eA1AI+#G2lUp86P9f=%;PCQ~#|ny)0DT8C!Mmw1>gbt+o~If|@XAHl}wSZrtV zW+Gl;N(L6jD32RSkZM12FApENiK>G#P`vL7nmjb;=tk5jTn-mB?`gl5%&G zCDI@vCcu|dn@RBM3>99HSNQo*g?5eT0@KE{yvH_cYv;=DM6LBgtL(wP;18`O{FqJo z4OGBDkf22}+9rPi@8;}@;ev6$tB1(xJE)#syFc>9cut<2BU0&I@gV)fy{Xn8v>wSm zQ2dSVSFlU>9rCXGQS0s}tKHZ(ihp2icZ$~rYS3IMzVbKNsdZ2<#T)Wb>(viYY!}10 zejfK&(oR~T7_PoD5d$o?U>{8+%(_3A^@N*MA(U>hhs;sE_0H~N=1zg1%gkr@vp&1G z#s`6y*GS-&dBl`<2z*4FzEX`S9$iBfSxh8wyr$=ix-|iPa!e;ywx&AO4w39#u(`fv z!G>#U4l;Le=SfXRKS#1_YBKgtIydUEcRtimpN}2%p@wo#NU44biw^;Ym71$2S4_e>ZYAuqunQ z(RG&-L^kJ$9{ao0ZCP74slZ4Jlk4xZjt7qUx9(e~+}|Tl(LC`Tt6W~FvZa<6gvqz% ztyX~IbH6}LI)z4=@yamtYGD!E#!otR^Xh)pN}oEt4y!w**Q@WUm7b~U%Hf~x^H$AX z$Ms!(%05<=))p-(QY&o%@6zdl)$lgr!ezsG(CH%5!=H0s64$T%J%L1gRcrcKKVIII z#}nn%(?);0?aL`1dmYb0R>krxWae4OEQiy#Dusc;h}~2d3(5uS*Hq{$*o6;%RCOD# z(5LVkP+L_X{#O;4|BB*YDmWA6xK;s6Z&!h}5Iandmnx7NECCXu(<2=?A0ux`dW^}x zRgi0GY~o`+>#Slv;=fc7T1XX03x~-nShUg~GfE4o0wHM?bbVF+;5)E=&%asS@NX3i z(LR-D-W-R3ces^&%I!1ViqGo!R^{L5Rst%VT~mt9U^6`&0=HKC?#%X#Z~GP%IKy zCNK`gv@9;+bSR(UM3<4P36 z`D3w-$_GEJzN*~{7M9ex;{zuZiu_yEJ1X`w`yII(ELSCO95+|oAIWh?4O_{Jw!HUB z?ivPZ`m2(y=TXDuh@v5tJUDLb554aG1df|(95wtFzMniUCI24R^P>*So;+9@W}OQq(~*mGI|=oKh`Nz`DC5V!_jDrzRtDa~;}Cy5Q-&qi^7KX4F>}QT6rP J>WhJ={|AKWt3m(( literal 0 HcmV?d00001 diff --git a/tests/Images/Input/Bmp/rle24rletrns.bmp b/tests/Images/Input/Bmp/rle24rletrns.bmp new file mode 100644 index 0000000000000000000000000000000000000000..baa86167fa9c2c6940b84b7565b59cb7991dcc74 GIT binary patch literal 20036 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 literal 0 HcmV?d00001 From a48de6301b4e5a410e7b6fbd3512fe3c38ee2fc1 Mon Sep 17 00:00:00 2001 From: Anton Firsov Date: Mon, 1 Jul 2019 08:31:52 +0200 Subject: [PATCH 223/223] Introduce non-generic ImageFrameCollection (#941) * temporarily disable target frameworks * drop DelegateProcessor * drop IImageProcessingContext * drop NamedColors * drop ColorBuilder * drop the *Base postfix for clean class hierarchies * adding basic skeletons * non-generic ImageFrameCollection API definition * non-generic ImageFrameCollection tests * cleanup + docs + more tests * implement ImageFrameCollection methods * tests for generic PixelOperations.To() * experimental implementation * fix .ttinclude * generate generic From(...) * fix RgbaVector <--> BT709 Gray pixel conversion * Gray8 and Gray16 using ConvertFromRgbaScaledVector4() by default * fixed all conversion tests * ConstructGif_FromDifferentPixelTypes * fix xmldoc and other StyelCop findings * re-enable all target frameworks * fix NonGenericAddFrame() and NonGenericInsertFrame() * fix remaining bugs --- .gitattributes | 2 +- src/ImageSharp/Common/Helpers/ImageMaths.cs | 13 +- .../Decoder/JpegImagePostProcessor.cs | 4 +- src/ImageSharp/Image.cs | 12 +- src/ImageSharp/ImageFrame.LoadPixelData.cs | 10 +- src/ImageSharp/ImageFrame.cs | 91 +++++ src/ImageSharp/ImageFrameCollection.cs | 252 ++++-------- .../ImageFrameCollection{TPixel}.cs | 358 ++++++++++++++++++ src/ImageSharp/ImageFrame{TPixel}.cs | 84 ++-- src/ImageSharp/ImageSharp.csproj | 10 + src/ImageSharp/Image{TPixel}.cs | 27 +- .../Argb32.PixelOperations.Generated.cs | 12 +- .../Argb32.PixelOperations.Generated.tt | 2 +- .../Bgr24.PixelOperations.Generated.cs | 12 +- .../Bgr24.PixelOperations.Generated.tt | 2 +- .../Bgra32.PixelOperations.Generated.cs | 12 +- .../Bgra32.PixelOperations.Generated.tt | 2 +- .../Gray16.PixelOperations.Generated.cs | 12 +- .../Gray16.PixelOperations.Generated.tt | 2 +- .../Gray8.PixelOperations.Generated.cs | 12 +- .../Gray8.PixelOperations.Generated.tt | 2 +- .../Rgb24.PixelOperations.Generated.cs | 12 +- .../Rgb24.PixelOperations.Generated.tt | 2 +- .../Rgb48.PixelOperations.Generated.cs | 12 +- .../Rgb48.PixelOperations.Generated.tt | 2 +- .../Rgba32.PixelOperations.Generated.cs | 12 +- .../Rgba32.PixelOperations.Generated.tt | 2 +- .../Rgba64.PixelOperations.Generated.cs | 12 +- .../Rgba64.PixelOperations.Generated.tt | 2 +- .../Generated/_Common.ttinclude | 17 +- .../PixelImplementations/Gray16.cs | 16 +- .../PixelImplementations/Gray8.cs | 14 +- .../RgbaVector.PixelOperations.cs | 35 +- .../PixelFormats/PixelOperations{TPixel}.cs | 91 +++-- .../AffineTransformProcessor{TPixel}.cs | 2 +- .../Transforms/CropProcessor{TPixel}.cs | 7 +- .../ProjectiveTransformProcessor{TPixel}.cs | 4 +- .../Resize/ResizeProcessor{TPixel}.cs | 7 +- .../ImageFrameCollectionTests.Generic.cs | 346 +++++++++++++++++ .../ImageFrameCollectionTests.NonGeneric.cs | 325 ++++++++++++++++ .../Image/ImageFrameCollectionTests.cs | 29 ++ .../Image/ImageFramesCollectionTests.cs | 331 ---------------- .../ImageSharp.Tests/ImageSharp.Tests.csproj | 7 + ...ConverterTests.ReferenceImplementations.cs | 115 ++++++ .../PixelFormats/PixelConverterTests.cs | 38 +- ...OperationsTests.Bgra5551OperationsTests.cs | 20 + ...elOperationsTests.Gray16OperationsTests.cs | 87 +---- ...xelOperationsTests.Gray8OperationsTests.cs | 87 +---- ...xelOperationsTests.Rgb24OperationsTests.cs | 2 +- .../PixelOperations/PixelOperationsTests.cs | 131 ++++++- 50 files changed, 1824 insertions(+), 876 deletions(-) create mode 100644 src/ImageSharp/ImageFrame.cs create mode 100644 src/ImageSharp/ImageFrameCollection{TPixel}.cs create mode 100644 tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.Generic.cs create mode 100644 tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs create mode 100644 tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.cs delete mode 100644 tests/ImageSharp.Tests/Image/ImageFramesCollectionTests.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs create mode 100644 tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra5551OperationsTests.cs diff --git a/.gitattributes b/.gitattributes index adef3cc9e..f39b679c5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -50,7 +50,7 @@ *.svg text eol=lf *.targets text eol=lf *.tt text eol=lf -*.ttinclude text eol=lf +*.ttinclude text eol=crlf *.txt text eol=lf *.vb text eol=lf *.yml text eol=lf diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs index 64bcb11c9..7460c9cac 100644 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs @@ -36,6 +36,17 @@ namespace SixLabors.ImageSharp public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b) => (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F)); + /// + /// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709. + /// + /// The red component. + /// The green component. + /// The blue component. + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static ushort Get16BitBT709Luminance(float r, float g, float b) => + (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F)); + /// /// Scales a value from a 16 bit to it's 8 bit equivalent. /// @@ -379,4 +390,4 @@ namespace SixLabors.ImageSharp return GetBoundingRectangle(topLeft, bottomRight); } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs index 2c8190884..f3f2952b1 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// (4) Packing pixels from the buffer.
/// These operations are executed in steps. /// image rows are converted in one step, - /// which means that size of the allocated memory is limited (does not depend on ). + /// which means that size of the allocated memory is limited (does not depend on ). ///
internal class JpegImagePostProcessor : IDisposable { @@ -177,4 +177,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index 3f3d6a62f..86fef715d 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -53,6 +53,11 @@ namespace SixLabors.ImageSharp ///
protected Configuration Configuration { get; } + /// + /// Gets the implementing the public property. + /// + protected abstract ImageFrameCollection NonGenericFrameCollection { get; } + /// public PixelTypeInfo PixelType { get; } @@ -65,6 +70,11 @@ namespace SixLabors.ImageSharp /// public ImageMetadata Metadata { get; } + /// + /// Gets the frames of the image as (non-generic) . + /// + public ImageFrameCollection Frames => this.NonGenericFrameCollection; + /// /// Gets the pixel buffer. /// @@ -137,4 +147,4 @@ namespace SixLabors.ImageSharp } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/ImageFrame.LoadPixelData.cs b/src/ImageSharp/ImageFrame.LoadPixelData.cs index 33dbe31df..9e90aeaf5 100644 --- a/src/ImageSharp/ImageFrame.LoadPixelData.cs +++ b/src/ImageSharp/ImageFrame.LoadPixelData.cs @@ -9,9 +9,9 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { /// - /// Adds static methods allowing the creation of new image from raw pixel data. + /// Contains methods for loading raw pixel data. /// - internal static class ImageFrame + public partial class ImageFrame { /// /// Create a new instance of the class from the given byte array in format. @@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp /// The height of the final image. /// The pixel format. /// A new . - public static ImageFrame LoadPixelData(Configuration configuration, ReadOnlySpan data, int width, int height) + internal static ImageFrame LoadPixelData(Configuration configuration, ReadOnlySpan data, int width, int height) where TPixel : struct, IPixel => LoadPixelData(configuration, MemoryMarshal.Cast(data), width, height); @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp /// The height of the final image. /// The pixel format. /// A new . - public static ImageFrame LoadPixelData(Configuration configuration, ReadOnlySpan data, int width, int height) + internal static ImageFrame LoadPixelData(Configuration configuration, ReadOnlySpan data, int width, int height) where TPixel : struct, IPixel { int count = width * height; @@ -48,4 +48,4 @@ namespace SixLabors.ImageSharp return image; } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/ImageFrame.cs b/src/ImageSharp/ImageFrame.cs new file mode 100644 index 000000000..f3fe1ed8d --- /dev/null +++ b/src/ImageSharp/ImageFrame.cs @@ -0,0 +1,91 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.Metadata; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Memory; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp +{ + /// + /// Represents a pixel-agnostic image frame containing all pixel data and . + /// In case of animated formats like gif, it contains the single frame in a animation. + /// In all other cases it is the only frame of the image. + /// + public abstract partial class ImageFrame : IDisposable + { + /// + /// Initializes a new instance of the class. + /// + /// The . + /// The width. + /// The height. + /// The . + protected ImageFrame(Configuration configuration, int width, int height, ImageFrameMetadata metadata) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(metadata, nameof(metadata)); + + this.Configuration = configuration; + this.MemoryAllocator = configuration.MemoryAllocator; + this.Width = width; + this.Height = height; + this.Metadata = metadata; + } + + /// + /// Gets the to use for buffer allocations. + /// + public MemoryAllocator MemoryAllocator { get; } + + /// + /// Gets the instance associated with this . + /// + internal Configuration Configuration { get; } + + /// + /// Gets the width. + /// + public int Width { get; private set; } + + /// + /// Gets the height. + /// + public int Height { get; private set; } + + /// + /// Gets the metadata of the frame. + /// + public ImageFrameMetadata Metadata { get; } + + /// + /// Gets the size of the frame. + /// + /// The + public Size Size() => new Size(this.Width, this.Height); + + /// + /// Gets the bounds of the frame. + /// + /// The + public Rectangle Bounds() => new Rectangle(0, 0, this.Width, this.Height); + + /// + public abstract void Dispose(); + + internal abstract void CopyPixelsTo(Span destination) + where TDestinationPixel : struct, IPixel; + + /// + /// Updates the size of the image frame. + /// + internal void UpdateSize(Size size) + { + this.Width = size.Width; + this.Height = size.Height; + } + } +} diff --git a/src/ImageSharp/ImageFrameCollection.cs b/src/ImageSharp/ImageFrameCollection.cs index 7e516434c..c5bd02c79 100644 --- a/src/ImageSharp/ImageFrameCollection.cs +++ b/src/ImageSharp/ImageFrameCollection.cs @@ -4,149 +4,69 @@ using System; using System.Collections; using System.Collections.Generic; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp { /// - /// Encapsulates a collection of instances that make up an . + /// Encapsulates a pixel-agnostic collection of instances + /// that make up an . /// - /// The type of the pixel. - public sealed class ImageFrameCollection : IEnumerable> - where TPixel : struct, IPixel + public abstract class ImageFrameCollection : IEnumerable { - private readonly IList> frames = new List>(); - private readonly Image parent; - - internal ImageFrameCollection(Image parent, int width, int height, TPixel backgroundColor) - { - this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); - - // Frames are already cloned within the caller - this.frames.Add(new ImageFrame(parent.GetConfiguration(), width, height, backgroundColor)); - } - - internal ImageFrameCollection(Image parent, int width, int height, MemorySource memorySource) - { - this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); - - // Frames are already cloned within the caller - this.frames.Add(new ImageFrame(parent.GetConfiguration(), width, height, memorySource)); - } - - internal ImageFrameCollection(Image parent, IEnumerable> frames) - { - Guard.NotNull(parent, nameof(parent)); - Guard.NotNull(frames, nameof(frames)); - - this.parent = parent; - - // Frames are already cloned by the caller - foreach (ImageFrame f in frames) - { - this.ValidateFrame(f); - this.frames.Add(f); - } - - // Ensure at least 1 frame was added to the frames collection - if (this.frames.Count == 0) - { - throw new ArgumentException("Must not be empty.", nameof(frames)); - } - } - /// /// Gets the number of frames. /// - public int Count => this.frames.Count; + public abstract int Count { get; } /// /// Gets the root frame. /// - public ImageFrame RootFrame => this.frames.Count > 0 ? this.frames[0] : null; + public ImageFrame RootFrame => this.NonGenericRootFrame; + + /// + /// Gets the root frame. (Implements .) + /// + protected abstract ImageFrame NonGenericRootFrame { get; } /// - /// Gets the at the specified index. + /// Gets the at the specified index. /// /// - /// The . + /// The . /// /// The index. - /// The at the specified index. - public ImageFrame this[int index] => this.frames[index]; + /// The at the specified index. + public ImageFrame this[int index] => this.NonGenericGetFrame(index); /// - /// Determines the index of a specific in the . + /// Determines the index of a specific in the . /// - /// The to locate in the . + /// The to locate in the . /// The index of item if found in the list; otherwise, -1. - public int IndexOf(ImageFrame frame) => this.frames.IndexOf(frame); + public abstract int IndexOf(ImageFrame frame); /// - /// Clones and inserts the into the at the specified . + /// Clones and inserts the into the at the specified . /// /// The zero-based index to insert the frame at. - /// The to clone and insert into the . + /// The to clone and insert into the . /// Frame must have the same dimensions as the image. - /// The cloned . - public ImageFrame InsertFrame(int index, ImageFrame source) - { - this.ValidateFrame(source); - ImageFrame clonedFrame = source.Clone(this.parent.GetConfiguration()); - this.frames.Insert(index, clonedFrame); - return clonedFrame; - } + /// The cloned . + public ImageFrame InsertFrame(int index, ImageFrame source) => this.NonGenericInsertFrame(index, source); /// /// Clones the frame and appends the clone to the end of the collection. /// /// The raw pixel data to generate the from. /// The cloned . - public ImageFrame AddFrame(ImageFrame source) - { - this.ValidateFrame(source); - ImageFrame clonedFrame = source.Clone(this.parent.GetConfiguration()); - this.frames.Add(clonedFrame); - return clonedFrame; - } - - /// - /// Creates a new frame from the pixel data with the same dimensions as the other frames and inserts the - /// new frame at the end of the collection. - /// - /// The raw pixel data to generate the from. - /// The new . - public ImageFrame AddFrame(TPixel[] source) - { - Guard.NotNull(source, nameof(source)); - - var frame = ImageFrame.LoadPixelData( - this.parent.GetConfiguration(), - new ReadOnlySpan(source), - this.RootFrame.Width, - this.RootFrame.Height); - this.frames.Add(frame); - return frame; - } + public ImageFrame AddFrame(ImageFrame source) => this.NonGenericAddFrame(source); /// /// Removes the frame at the specified index and frees all freeable resources associated with it. /// /// The zero-based index of the frame to remove. /// Cannot remove last frame. - public void RemoveFrame(int index) - { - if (index == 0 && this.Count == 1) - { - throw new InvalidOperationException("Cannot remove last frame."); - } - - ImageFrame frame = this.frames[index]; - this.frames.RemoveAt(index); - frame.Dispose(); - } + public abstract void RemoveFrame(int index); /// /// Determines whether the contains the . @@ -155,24 +75,14 @@ namespace SixLabors.ImageSharp /// /// true if the contains the specified frame; otherwise, false. /// - public bool Contains(ImageFrame frame) => this.frames.Contains(frame); + public abstract bool Contains(ImageFrame frame); /// /// Moves an from to . /// /// The zero-based index of the frame to move. /// The index to move the frame to. - public void MoveFrame(int sourceIndex, int destinationIndex) - { - if (sourceIndex == destinationIndex) - { - return; - } - - ImageFrame frameAtIndex = this.frames[sourceIndex]; - this.frames.RemoveAt(sourceIndex); - this.frames.Insert(destinationIndex, frameAtIndex); - } + public abstract void MoveFrame(int sourceIndex, int destinationIndex); /// /// Removes the frame at the specified index and creates a new image with only the removed frame @@ -181,19 +91,7 @@ namespace SixLabors.ImageSharp /// The zero-based index of the frame to export. /// Cannot remove last frame. /// The new with the specified frame. - public Image ExportFrame(int index) - { - ImageFrame frame = this[index]; - - if (this.Count == 1 && this.frames.Contains(frame)) - { - throw new InvalidOperationException("Cannot remove last frame."); - } - - this.frames.Remove(frame); - - return new Image(this.parent.GetConfiguration(), this.parent.Metadata.DeepClone(), new[] { frame }); - } + public Image ExportFrame(int index) => this.NonGenericExportFrame(index); /// /// Creates an with only the frame at the specified index @@ -201,12 +99,7 @@ namespace SixLabors.ImageSharp /// /// The zero-based index of the frame to clone. /// The new with the specified frame. - public Image CloneFrame(int index) - { - ImageFrame frame = this[index]; - ImageFrame clonedFrame = frame.Clone(); - return new Image(this.parent.GetConfiguration(), this.parent.Metadata.DeepClone(), new[] { clonedFrame }); - } + public Image CloneFrame(int index) => this.NonGenericCloneFrame(index); /// /// Creates a new and appends it to the end of the collection. @@ -214,7 +107,7 @@ namespace SixLabors.ImageSharp /// /// The new . /// - public ImageFrame CreateFrame() => this.CreateFrame(default); + public ImageFrame CreateFrame() => this.NonGenericCreateFrame(); /// /// Creates a new and appends it to the end of the collection. @@ -223,44 +116,67 @@ namespace SixLabors.ImageSharp /// /// The new . /// - public ImageFrame CreateFrame(TPixel backgroundColor) - { - var frame = new ImageFrame( - this.parent.GetConfiguration(), - this.RootFrame.Width, - this.RootFrame.Height, - backgroundColor); - this.frames.Add(frame); - return frame; - } + public ImageFrame CreateFrame(Color backgroundColor) => this.NonGenericCreateFrame(backgroundColor); - /// - IEnumerator> IEnumerable>.GetEnumerator() => this.frames.GetEnumerator(); + /// + public IEnumerator GetEnumerator() => this.NonGenericGetEnumerator(); /// - IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this.frames).GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => this.NonGenericGetEnumerator(); - private void ValidateFrame(ImageFrame frame) - { - Guard.NotNull(frame, nameof(frame)); + /// + /// Implements . + /// + /// The enumerator. + protected abstract IEnumerator NonGenericGetEnumerator(); + + /// + /// Implements the getter of the indexer. + /// + /// The index. + /// The frame. + protected abstract ImageFrame NonGenericGetFrame(int index); + + /// + /// Implements . + /// + /// The index. + /// The frame. + /// The new frame. + protected abstract ImageFrame NonGenericInsertFrame(int index, ImageFrame source); + + /// + /// Implements . + /// + /// The frame. + /// The new frame. + protected abstract ImageFrame NonGenericAddFrame(ImageFrame source); + + /// + /// Implements . + /// + /// The index. + /// The new image. + protected abstract Image NonGenericExportFrame(int index); - if (this.Count != 0) - { - if (this.RootFrame.Width != frame.Width || this.RootFrame.Height != frame.Height) - { - throw new ArgumentException("Frame must have the same dimensions as the image.", nameof(frame)); - } - } - } + /// + /// Implements . + /// + /// The index. + /// The new image. + protected abstract Image NonGenericCloneFrame(int index); - internal void Dispose() - { - foreach (ImageFrame f in this.frames) - { - f.Dispose(); - } + /// + /// Implements . + /// + /// The new frame. + protected abstract ImageFrame NonGenericCreateFrame(); - this.frames.Clear(); - } + /// + /// Implements . + /// + /// The background color. + /// The new frame. + protected abstract ImageFrame NonGenericCreateFrame(Color backgroundColor); } -} \ No newline at end of file +} diff --git a/src/ImageSharp/ImageFrameCollection{TPixel}.cs b/src/ImageSharp/ImageFrameCollection{TPixel}.cs new file mode 100644 index 000000000..ffd7225bd --- /dev/null +++ b/src/ImageSharp/ImageFrameCollection{TPixel}.cs @@ -0,0 +1,358 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections; +using System.Collections.Generic; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + /// + /// Encapsulates a pixel-specific collection of instances + /// that make up an . + /// + /// The type of the pixel. + public sealed class ImageFrameCollection : ImageFrameCollection, IEnumerable> + where TPixel : struct, IPixel + { + private readonly IList> frames = new List>(); + private readonly Image parent; + + internal ImageFrameCollection(Image parent, int width, int height, TPixel backgroundColor) + { + this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); + + // Frames are already cloned within the caller + this.frames.Add(new ImageFrame(parent.GetConfiguration(), width, height, backgroundColor)); + } + + internal ImageFrameCollection(Image parent, int width, int height, MemorySource memorySource) + { + this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); + + // Frames are already cloned within the caller + this.frames.Add(new ImageFrame(parent.GetConfiguration(), width, height, memorySource)); + } + + internal ImageFrameCollection(Image parent, IEnumerable> frames) + { + Guard.NotNull(parent, nameof(parent)); + Guard.NotNull(frames, nameof(frames)); + + this.parent = parent; + + // Frames are already cloned by the caller + foreach (ImageFrame f in frames) + { + this.ValidateFrame(f); + this.frames.Add(f); + } + + // Ensure at least 1 frame was added to the frames collection + if (this.frames.Count == 0) + { + throw new ArgumentException("Must not be empty.", nameof(frames)); + } + } + + /// + /// Gets the number of frames. + /// + public override int Count => this.frames.Count; + + /// + /// Gets the root frame. + /// + public new ImageFrame RootFrame => this.frames.Count > 0 ? this.frames[0] : null; + + /// + protected override ImageFrame NonGenericRootFrame => this.RootFrame; + + /// + /// Gets the at the specified index. + /// + /// + /// The . + /// + /// The index. + /// The at the specified index. + public new ImageFrame this[int index] => this.frames[index]; + + /// + public override int IndexOf(ImageFrame frame) + { + return frame is ImageFrame specific ? this.IndexOf(specific) : -1; + } + + /// + /// Determines the index of a specific in the . + /// + /// The to locate in the . + /// The index of item if found in the list; otherwise, -1. + public int IndexOf(ImageFrame frame) => this.frames.IndexOf(frame); + + /// + /// Clones and inserts the into the at the specified . + /// + /// The zero-based index to insert the frame at. + /// The to clone and insert into the . + /// Frame must have the same dimensions as the image. + /// The cloned . + public ImageFrame InsertFrame(int index, ImageFrame source) + { + this.ValidateFrame(source); + ImageFrame clonedFrame = source.Clone(this.parent.GetConfiguration()); + this.frames.Insert(index, clonedFrame); + return clonedFrame; + } + + /// + /// Clones the frame and appends the clone to the end of the collection. + /// + /// The raw pixel data to generate the from. + /// The cloned . + public ImageFrame AddFrame(ImageFrame source) + { + this.ValidateFrame(source); + ImageFrame clonedFrame = source.Clone(this.parent.GetConfiguration()); + this.frames.Add(clonedFrame); + return clonedFrame; + } + + /// + /// Creates a new frame from the pixel data with the same dimensions as the other frames and inserts the + /// new frame at the end of the collection. + /// + /// The raw pixel data to generate the from. + /// The new . + public ImageFrame AddFrame(ReadOnlySpan source) + { + var frame = ImageFrame.LoadPixelData( + this.parent.GetConfiguration(), + source, + this.RootFrame.Width, + this.RootFrame.Height); + this.frames.Add(frame); + return frame; + } + + /// + /// Creates a new frame from the pixel data with the same dimensions as the other frames and inserts the + /// new frame at the end of the collection. + /// + /// The raw pixel data to generate the from. + /// The new . + public ImageFrame AddFrame(TPixel[] source) + { + Guard.NotNull(source, nameof(source)); + return this.AddFrame(source.AsSpan()); + } + + /// + /// Removes the frame at the specified index and frees all freeable resources associated with it. + /// + /// The zero-based index of the frame to remove. + /// Cannot remove last frame. + public override void RemoveFrame(int index) + { + if (index == 0 && this.Count == 1) + { + throw new InvalidOperationException("Cannot remove last frame."); + } + + ImageFrame frame = this.frames[index]; + this.frames.RemoveAt(index); + frame.Dispose(); + } + + /// + public override bool Contains(ImageFrame frame) => + frame is ImageFrame specific && this.Contains(specific); + + /// + /// Determines whether the contains the . + /// + /// The frame. + /// + /// true if the contains the specified frame; otherwise, false. + /// + public bool Contains(ImageFrame frame) => this.frames.Contains(frame); + + /// + /// Moves an from to . + /// + /// The zero-based index of the frame to move. + /// The index to move the frame to. + public override void MoveFrame(int sourceIndex, int destinationIndex) + { + if (sourceIndex == destinationIndex) + { + return; + } + + ImageFrame frameAtIndex = this.frames[sourceIndex]; + this.frames.RemoveAt(sourceIndex); + this.frames.Insert(destinationIndex, frameAtIndex); + } + + /// + /// Removes the frame at the specified index and creates a new image with only the removed frame + /// with the same metadata as the original image. + /// + /// The zero-based index of the frame to export. + /// Cannot remove last frame. + /// The new with the specified frame. + public new Image ExportFrame(int index) + { + ImageFrame frame = this[index]; + + if (this.Count == 1 && this.frames.Contains(frame)) + { + throw new InvalidOperationException("Cannot remove last frame."); + } + + this.frames.Remove(frame); + + return new Image(this.parent.GetConfiguration(), this.parent.Metadata.DeepClone(), new[] { frame }); + } + + /// + /// Creates an with only the frame at the specified index + /// with the same metadata as the original image. + /// + /// The zero-based index of the frame to clone. + /// The new with the specified frame. + public new Image CloneFrame(int index) + { + ImageFrame frame = this[index]; + ImageFrame clonedFrame = frame.Clone(); + return new Image(this.parent.GetConfiguration(), this.parent.Metadata.DeepClone(), new[] { clonedFrame }); + } + + /// + /// Creates a new and appends it to the end of the collection. + /// + /// + /// The new . + /// + public new ImageFrame CreateFrame() + { + var frame = new ImageFrame( + this.parent.GetConfiguration(), + this.RootFrame.Width, + this.RootFrame.Height); + this.frames.Add(frame); + return frame; + } + + /// + protected override IEnumerator NonGenericGetEnumerator() => this.frames.GetEnumerator(); + + /// + protected override ImageFrame NonGenericGetFrame(int index) => this[index]; + + /// + protected override ImageFrame NonGenericInsertFrame(int index, ImageFrame source) + { + Guard.NotNull(source, nameof(source)); + + if (source is ImageFrame compatibleSource) + { + return this.InsertFrame(index, compatibleSource); + } + + ImageFrame result = this.CopyNonCompatibleFrame(source); + this.frames.Insert(index, result); + return result; + } + + /// + protected override ImageFrame NonGenericAddFrame(ImageFrame source) + { + Guard.NotNull(source, nameof(source)); + + if (source is ImageFrame compatibleSource) + { + return this.AddFrame(compatibleSource); + } + + ImageFrame result = this.CopyNonCompatibleFrame(source); + this.frames.Add(result); + return result; + } + + /// + protected override Image NonGenericExportFrame(int index) => this.ExportFrame(index); + + /// + protected override Image NonGenericCloneFrame(int index) => this.CloneFrame(index); + + /// + protected override ImageFrame NonGenericCreateFrame(Color backgroundColor) => + this.CreateFrame(backgroundColor.ToPixel()); + + /// + protected override ImageFrame NonGenericCreateFrame() => this.CreateFrame(); + + /// + /// Creates a new and appends it to the end of the collection. + /// + /// The background color to initialize the pixels with. + /// + /// The new . + /// + public ImageFrame CreateFrame(TPixel backgroundColor) + { + var frame = new ImageFrame( + this.parent.GetConfiguration(), + this.RootFrame.Width, + this.RootFrame.Height, + backgroundColor); + this.frames.Add(frame); + return frame; + } + + /// + IEnumerator> IEnumerable>.GetEnumerator() => this.frames.GetEnumerator(); + + /// + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this.frames).GetEnumerator(); + + private void ValidateFrame(ImageFrame frame) + { + Guard.NotNull(frame, nameof(frame)); + + if (this.Count != 0) + { + if (this.RootFrame.Width != frame.Width || this.RootFrame.Height != frame.Height) + { + throw new ArgumentException("Frame must have the same dimensions as the image.", nameof(frame)); + } + } + } + + internal void Dispose() + { + foreach (ImageFrame f in this.frames) + { + f.Dispose(); + } + + this.frames.Clear(); + } + + private ImageFrame CopyNonCompatibleFrame(ImageFrame source) + { + ImageFrame result = new ImageFrame( + this.parent.GetConfiguration(), + source.Size(), + source.Metadata.DeepClone()); + source.CopyPixelsTo(result.PixelBuffer.Span); + return result; + } + } +} diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs index 4f0be5971..982f8d8f2 100644 --- a/src/ImageSharp/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/ImageFrame{TPixel}.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; @@ -15,10 +16,12 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp { /// - /// Represents a single frame in a animation. + /// Represents a pixel-specific image frame containing all pixel data and . + /// In case of animated formats like gif, it contains the single frame in a animation. + /// In all other cases it is the only frame of the image. /// /// The pixel format. - public sealed class ImageFrame : IPixelSource, IDisposable + public sealed class ImageFrame : ImageFrame, IPixelSource, IDisposable where TPixel : struct, IPixel { private bool isDisposed; @@ -53,8 +56,12 @@ namespace SixLabors.ImageSharp /// The height of the image in pixels. /// The metadata. internal ImageFrame(Configuration configuration, int width, int height, ImageFrameMetadata metadata) - : this(configuration, width, height, default(TPixel), metadata) + : base(configuration, width, height, metadata) { + Guard.MustBeGreaterThan(width, 0, nameof(width)); + Guard.MustBeGreaterThan(height, 0, nameof(height)); + + this.PixelBuffer = this.MemoryAllocator.Allocate2D(width, height, AllocationOptions.Clean); } /// @@ -78,15 +85,12 @@ namespace SixLabors.ImageSharp /// The color to clear the image with. /// The metadata. internal ImageFrame(Configuration configuration, int width, int height, TPixel backgroundColor, ImageFrameMetadata metadata) + : base(configuration, width, height, metadata) { - Guard.NotNull(configuration, nameof(configuration)); Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); - this.Configuration = configuration; - this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = this.MemoryAllocator.Allocate2D(width, height); - this.Metadata = metadata ?? new ImageFrameMetadata(); this.Clear(configuration.GetParallelOptions(), backgroundColor); } @@ -111,16 +115,12 @@ namespace SixLabors.ImageSharp /// The memory source. /// The metadata. internal ImageFrame(Configuration configuration, int width, int height, MemorySource memorySource, ImageFrameMetadata metadata) + : base(configuration, width, height, metadata) { - Guard.NotNull(configuration, nameof(configuration)); Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); - Guard.NotNull(metadata, nameof(metadata)); - this.Configuration = configuration; - this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = new Buffer2D(memorySource, width, height); - this.Metadata = metadata; } /// @@ -129,27 +129,15 @@ namespace SixLabors.ImageSharp /// The configuration which allows altering default behaviour or extending the library. /// The source. internal ImageFrame(Configuration configuration, ImageFrame source) + : base(configuration, source.Width, source.Height, source.Metadata.DeepClone()) { Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(source, nameof(source)); - this.Configuration = configuration; - this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = this.MemoryAllocator.Allocate2D(source.PixelBuffer.Width, source.PixelBuffer.Height); source.PixelBuffer.GetSpan().CopyTo(this.PixelBuffer.GetSpan()); - this.Metadata = source.Metadata.DeepClone(); } - /// - /// Gets the to use for buffer allocations. - /// - public MemoryAllocator MemoryAllocator { get; } - - /// - /// Gets the instance associated with this . - /// - internal Configuration Configuration { get; } - /// /// Gets the image pixels. Not private as Buffer2D requires an array in its constructor. /// @@ -158,21 +146,6 @@ namespace SixLabors.ImageSharp /// Buffer2D IPixelSource.PixelBuffer => this.PixelBuffer; - /// - /// Gets the width. - /// - public int Width => this.PixelBuffer.Width; - - /// - /// Gets the height. - /// - public int Height => this.PixelBuffer.Height; - - /// - /// Gets the metadata of the frame. - /// - public ImageFrameMetadata Metadata { get; } - /// /// Gets or sets the pixel at the specified position. /// @@ -188,18 +161,6 @@ namespace SixLabors.ImageSharp set => this.PixelBuffer[x, y] = value; } - /// - /// Gets the size of the frame. - /// - /// The - public Size Size() => new Size(this.Width, this.Height); - - /// - /// Gets the bounds of the frame. - /// - /// The - public Rectangle Bounds() => new Rectangle(0, 0, this.Width, this.Height); - /// /// Gets a reference to the pixel at the specified position. /// @@ -232,12 +193,13 @@ namespace SixLabors.ImageSharp Guard.NotNull(pixelSource, nameof(pixelSource)); Buffer2D.SwapOrCopyContent(this.PixelBuffer, pixelSource.PixelBuffer); + this.UpdateSize(this.PixelBuffer.Size()); } /// /// Disposes the object and frees resources for the Garbage Collector. /// - internal void Dispose() + public override void Dispose() { if (this.isDisposed) { @@ -251,6 +213,17 @@ namespace SixLabors.ImageSharp this.isDisposed = true; } + internal override void CopyPixelsTo(Span destination) + { + if (typeof(TPixel) == typeof(TDestinationPixel)) + { + Span dest1 = MemoryMarshal.Cast(destination); + this.PixelBuffer.Span.CopyTo(dest1); + } + + PixelOperations.Instance.To(this.Configuration, this.PixelBuffer.Span, destination); + } + /// public override string ToString() => $"ImageFrame<{typeof(TPixel).Name}>({this.Width}x{this.Height})"; @@ -325,8 +298,5 @@ namespace SixLabors.ImageSharp span.Fill(value); } } - - /// - void IDisposable.Dispose() => this.Dispose(); } -} \ No newline at end of file +} diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index a3d614a06..3b0211434 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -5,6 +5,16 @@ SixLabors.ImageSharp SixLabors.ImageSharp A cross-platform library for the processing of image files; written in C# + en + + $(packageversion) + 0.0.1 + + netcoreapp2.1;netstandard1.3;netstandard2.0;net472 + + true + true + SixLabors.ImageSharp SixLabors.ImageSharp Image Resize Crop Gif Jpg Jpeg Bitmap Png Core SixLabors.ImageSharp diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 2b93b710b..5d0364dd8 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -80,7 +80,12 @@ namespace SixLabors.ImageSharp /// The width of the image in pixels. /// The height of the image in pixels. /// The images metadata. - internal Image(Configuration configuration, MemorySource memorySource, int width, int height, ImageMetadata metadata) + internal Image( + Configuration configuration, + MemorySource memorySource, + int width, + int height, + ImageMetadata metadata) : base(configuration, PixelTypeInfo.Create(), metadata, width, height) { this.Frames = new ImageFrameCollection(this, width, height, memorySource); @@ -95,7 +100,12 @@ namespace SixLabors.ImageSharp /// The height of the image in pixels. /// The color to initialize the pixels with. /// The images metadata. - internal Image(Configuration configuration, int width, int height, TPixel backgroundColor, ImageMetadata metadata) + internal Image( + Configuration configuration, + int width, + int height, + TPixel backgroundColor, + ImageMetadata metadata) : base(configuration, PixelTypeInfo.Create(), metadata, width, height) { this.Frames = new ImageFrameCollection(this, width, height, backgroundColor); @@ -114,10 +124,13 @@ namespace SixLabors.ImageSharp this.Frames = new ImageFrameCollection(this, frames); } + /// + protected override ImageFrameCollection NonGenericFrameCollection => this.Frames; + /// /// Gets the frames. /// - public ImageFrameCollection Frames { get; } + public new ImageFrameCollection Frames { get; } /// /// Gets the root frame. @@ -149,7 +162,8 @@ namespace SixLabors.ImageSharp /// Returns a new with all the same pixel data as the original. public Image Clone(Configuration configuration) { - IEnumerable> clonedFrames = this.Frames.Select(x => x.Clone(configuration)); + IEnumerable> clonedFrames = + this.Frames.Select, ImageFrame>(x => x.Clone(configuration)); return new Image(configuration, this.Metadata.DeepClone(), clonedFrames); } @@ -161,7 +175,8 @@ namespace SixLabors.ImageSharp /// The . public override Image CloneAs(Configuration configuration) { - IEnumerable> clonedFrames = this.Frames.Select(x => x.CloneAs(configuration)); + IEnumerable> clonedFrames = + this.Frames.Select, ImageFrame>(x => x.CloneAs(configuration)); return new Image(configuration, this.Metadata.DeepClone(), clonedFrames); } @@ -214,4 +229,4 @@ namespace SixLabors.ImageSharp return rootSize; } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs index 4cff1f8c1..8481fc62c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs @@ -11,6 +11,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -222,6 +223,15 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromArgb32(sp); } } + /// + internal override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + PixelOperations.Instance.ToArgb32(configuration, sourcePixels, destinationPixels); + } + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.tt index 0a58504e1..3a4c7b459 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.tt @@ -16,4 +16,4 @@ namespace SixLabors.ImageSharp.PixelFormats <# GenerateAllDefaultConversionMethods("Argb32"); #> } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs index 225e4b5e0..4b2b3a02e 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs @@ -11,6 +11,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -196,6 +197,15 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgr24(sp); } } + /// + internal override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + PixelOperations.Instance.ToBgr24(configuration, sourcePixels, destinationPixels); + } + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.tt index 84b89aa32..cfaefeda9 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.tt @@ -16,4 +16,4 @@ namespace SixLabors.ImageSharp.PixelFormats <# GenerateAllDefaultConversionMethods("Bgr24"); #> } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs index ce049115e..95d85c7c8 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs @@ -11,6 +11,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -222,6 +223,15 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra32(sp); } } + /// + internal override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + PixelOperations.Instance.ToBgra32(configuration, sourcePixels, destinationPixels); + } + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.tt index 004ceff51..58ecfa5a6 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.tt @@ -16,4 +16,4 @@ namespace SixLabors.ImageSharp.PixelFormats <# GenerateAllDefaultConversionMethods("Bgra32"); #> } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs index 288c5d92e..e6ed75d49 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.cs @@ -11,6 +11,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -185,6 +186,15 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromGray16(sp); } } + /// + internal override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + PixelOperations.Instance.ToGray16(configuration, sourcePixels, destinationPixels); + } + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.tt index 3cbc01e88..ac484bdbc 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray16.PixelOperations.Generated.tt @@ -16,4 +16,4 @@ namespace SixLabors.ImageSharp.PixelFormats <# GenerateAllDefaultConversionMethods("Gray16"); #> } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs index f7e94788e..c9a3a06fe 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.cs @@ -11,6 +11,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -185,6 +186,15 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromGray8(sp); } } + /// + internal override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + PixelOperations.Instance.ToGray8(configuration, sourcePixels, destinationPixels); + } + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.tt index d35843ccd..ffa15af9d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Gray8.PixelOperations.Generated.tt @@ -16,4 +16,4 @@ namespace SixLabors.ImageSharp.PixelFormats <# GenerateAllDefaultConversionMethods("Gray8"); #> } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs index 02a8869ec..ef224c02d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs @@ -11,6 +11,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -196,6 +197,15 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb24(sp); } } + /// + internal override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + PixelOperations.Instance.ToRgb24(configuration, sourcePixels, destinationPixels); + } + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.tt index d96c3684b..fc149b238 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.tt @@ -16,4 +16,4 @@ namespace SixLabors.ImageSharp.PixelFormats <# GenerateAllDefaultConversionMethods("Rgb24"); #> } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs index 30c9972bb..694388899 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs @@ -11,6 +11,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -185,6 +186,15 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } + /// + internal override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + PixelOperations.Instance.ToRgb48(configuration, sourcePixels, destinationPixels); + } + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.tt index 7bff33638..957c8f886 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.tt @@ -16,4 +16,4 @@ namespace SixLabors.ImageSharp.PixelFormats <# GenerateAllDefaultConversionMethods("Rgb48"); #> } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs index da2ce3770..f0c8bc884 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs @@ -11,6 +11,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -211,6 +212,15 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba32(sp); } } + /// + internal override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + PixelOperations.Instance.ToRgba32(configuration, sourcePixels, destinationPixels); + } + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.tt index 6b9e2d124..905e2cc58 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.tt @@ -16,4 +16,4 @@ namespace SixLabors.ImageSharp.PixelFormats <# GenerateAllDefaultConversionMethods("Rgba32"); #> } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs index 42c40ad5d..0faa6eb44 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs @@ -11,6 +11,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -185,6 +186,15 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } + /// + internal override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + PixelOperations.Instance.ToRgba64(configuration, sourcePixels, destinationPixels); + } + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.tt index d15945f94..03179a392 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.tt @@ -16,4 +16,4 @@ namespace SixLabors.ImageSharp.PixelFormats <# GenerateAllDefaultConversionMethods("Rgba64"); #> } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude index 584615532..17e9469f3 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude @@ -22,6 +22,19 @@ using System.Runtime.InteropServices; // Types with Rgba32-combatible to/from Vector4 conversion static readonly string[] Rgba32CompatibleTypes = { "Argb32", "Bgra32", "Rgb24", "Bgr24" }; + void GenerateGenericConverterMethods(string pixelType) + { +#> + /// + internal override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span<<#=pixelType#>> destinationPixels) + { + PixelOperations.Instance.To<#=pixelType#>(configuration, sourcePixels, destinationPixels); + } +<#+ + } void GenerateDefaultSelfConversionMethods(string pixelType) { @@ -117,7 +130,7 @@ using System.Runtime.InteropServices; } #> /// - internal override void FromVector4(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels, PixelConversionModifiers modifiers) + internal override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels, PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(<#=removeTheseModifiers#>)); } @@ -156,5 +169,7 @@ using System.Runtime.InteropServices; { GenerateDefaultConvertToMethod(pixelType, destPixelType); } + + GenerateGenericConverterMethods(pixelType); } #> diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Gray16.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Gray16.cs index 6fce1c757..195a8bedb 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Gray16.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Gray16.cs @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromScaledVector4(Vector4 vector) => this.FromVector4(vector); + public void FromScaledVector4(Vector4 vector) => this.ConvertFromRgbaScaledVector4(vector); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -62,11 +62,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromVector4(Vector4 vector) - { - vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max * Average; - this.PackedValue = (ushort)MathF.Round(vector.X + vector.Y + vector.Z); - } + public void FromVector4(Vector4 vector) => this.ConvertFromRgbaScaledVector4(vector); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -176,9 +172,9 @@ namespace SixLabors.ImageSharp.PixelFormats { vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max; this.PackedValue = ImageMaths.Get16BitBT709Luminance( - (ushort)MathF.Round(vector.X), - (ushort)MathF.Round(vector.Y), - (ushort)MathF.Round(vector.Z)); + vector.X, + vector.Y, + vector.Z); } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs index 1c278b434..09597a949 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Gray8.cs @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromScaledVector4(Vector4 vector) => this.FromVector4(vector); + public void FromScaledVector4(Vector4 vector) => this.ConvertFromRgbaScaledVector4(vector); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -67,15 +67,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromVector4(Vector4 vector) - { - vector = Vector4.Max(Min, vector); - vector = Vector4.Min(Max, vector); - - float roundedSum = Vector4.Dot(vector, Accumulator); - - this.PackedValue = (byte)roundedSum; - } + public void FromVector4(Vector4 vector) => this.ConvertFromRgbaScaledVector4(vector); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -166,4 +158,4 @@ namespace SixLabors.ImageSharp.PixelFormats this.PackedValue = ImageMaths.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z); } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs index 3112126e7..b331dbd99 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs @@ -3,6 +3,7 @@ using System; using System.Numerics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.PixelFormats.Utils; @@ -44,6 +45,38 @@ namespace SixLabors.ImageSharp.PixelFormats MemoryMarshal.Cast(sourcePixels).CopyTo(destVectors); Vector4Converters.ApplyForwardConversionModifiers(destVectors, modifiers); } + + internal override void ToGray8(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + { + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref Vector4 sourceBaseRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref Gray8 destBaseRef = ref MemoryMarshal.GetReference(destPixels); + + for (int i = 0; i < sourcePixels.Length; i++) + { + ref Vector4 sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Gray8 dp = ref Unsafe.Add(ref destBaseRef, i); + + dp.ConvertFromRgbaScaledVector4(sp); + } + } + + internal override void ToGray16(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels) + { + Guard.DestinationShouldNotBeTooShort(sourcePixels, destPixels, nameof(destPixels)); + + ref Vector4 sourceBaseRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); + ref Gray16 destBaseRef = ref MemoryMarshal.GetReference(destPixels); + + for (int i = 0; i < sourcePixels.Length; i++) + { + ref Vector4 sp = ref Unsafe.Add(ref sourceBaseRef, i); + ref Gray16 dp = ref Unsafe.Add(ref destBaseRef, i); + + dp.ConvertFromRgbaScaledVector4(sp); + } + } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index d009822e8..2b2d79c73 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -7,6 +7,8 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using SixLabors.ImageSharp.Memory; + namespace SixLabors.ImageSharp.PixelFormats { /// @@ -89,63 +91,56 @@ namespace SixLabors.ImageSharp.PixelFormats Span destVectors) => this.ToVector4(configuration, sourcePixels, destVectors, PixelConversionModifiers.None); - /// - /// Converts 'sourceColors.Length' pixels from 'sourceColors' into 'destinationColors'. - /// - /// The destination pixel type. - /// A to configure internal operations - /// The to the source colors. - /// The to the destination colors. - internal virtual void To( + internal virtual void From( Configuration configuration, - ReadOnlySpan sourceColors, - Span destinationColors) - where TDestinationPixel : struct, IPixel + ReadOnlySpan sourcePixels, + Span destinationPixels) + where TSourcePixel : struct, IPixel { - Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourceColors, destinationColors, nameof(destinationColors)); - - int count = sourceColors.Length; - ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); - - // Gray8 and Gray16 are special implementations of IPixel in that they do not conform to the - // standard RGBA colorspace format and must be converted from RGBA using the special ITU BT709 algorithm. - // One of the requirements of FromScaledVector4/ToScaledVector4 is that it unaware of this and - // packs/unpacks the pixel without and conversion so we employ custom methods do do this. - if (typeof(TDestinationPixel) == typeof(Gray16)) + const int SliceLength = 1024; + int numberOfSlices = sourcePixels.Length / SliceLength; + using (IMemoryOwner tempVectors = configuration.MemoryAllocator.Allocate(SliceLength)) { - ref Gray16 gray16Ref = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(destinationColors)); - for (int i = 0; i < count; i++) + Span vectorSpan = tempVectors.GetSpan(); + for (int i = 0; i < numberOfSlices; i++) { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - ref Gray16 dp = ref Unsafe.Add(ref gray16Ref, i); - dp.ConvertFromRgbaScaledVector4(sp.ToScaledVector4()); + int start = i * SliceLength; + ReadOnlySpan s = sourcePixels.Slice(start, SliceLength); + Span d = destinationPixels.Slice(start, SliceLength); + PixelOperations.Instance.ToVector4(configuration, s, vectorSpan); + this.FromVector4Destructive(configuration, vectorSpan, d); } - return; - } - - if (typeof(TDestinationPixel) == typeof(Gray8)) - { - ref Gray8 gray8Ref = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(destinationColors)); - for (int i = 0; i < count; i++) + int endOfCompleteSlices = numberOfSlices * SliceLength; + int remainder = sourcePixels.Length - endOfCompleteSlices; + if (remainder > 0) { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - ref Gray8 dp = ref Unsafe.Add(ref gray8Ref, i); - dp.ConvertFromRgbaScaledVector4(sp.ToScaledVector4()); + ReadOnlySpan s = sourcePixels.Slice(endOfCompleteSlices); + Span d = destinationPixels.Slice(endOfCompleteSlices); + vectorSpan = vectorSpan.Slice(0, remainder); + PixelOperations.Instance.ToVector4(configuration, s, vectorSpan); + this.FromVector4Destructive(configuration, vectorSpan, d); } - - return; } + } - // Normal conversion - ref TDestinationPixel destRef = ref MemoryMarshal.GetReference(destinationColors); - for (int i = 0; i < count; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - ref TDestinationPixel dp = ref Unsafe.Add(ref destRef, i); - dp.FromScaledVector4(sp.ToScaledVector4()); - } + /// + /// Converts 'sourcePixels.Length' pixels from 'sourcePixels' into 'destinationPixels'. + /// + /// The destination pixel type. + /// A to configure internal operations. + /// The to the source pixels. + /// The to the destination pixels. + internal virtual void To( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + where TDestinationPixel : struct, IPixel + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); + + PixelOperations.Instance.From(configuration, sourcePixels, destinationPixels); } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs index 9625ca216..529a49bf7 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select( + IEnumerable> frames = source.Frames.Select, ImageFrame>( x => new ImageFrame(source.GetConfiguration(), this.TargetDimensions, x.Metadata.DeepClone())); // Use the overload to prevent an extra frame being added diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs index 4c4c27def..25f8d7849 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs @@ -36,7 +36,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.CropRectangle.Width, this.CropRectangle.Height, x.Metadata.DeepClone())); + IEnumerable> frames = source.Frames.Select, ImageFrame>( + x => new ImageFrame( + source.GetConfiguration(), + this.CropRectangle.Width, + this.CropRectangle.Height, + x.Metadata.DeepClone())); // Use the overload to prevent an extra frame being added return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs index 15d8141ba..80b03000b 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs @@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select( + IEnumerable> frames = source.Frames.Select, ImageFrame>( x => new ImageFrame( source.GetConfiguration(), this.TargetDimensions.Width, @@ -140,4 +140,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index fdd1d339d..fb03057a4 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -68,7 +68,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select(x => new ImageFrame(source.GetConfiguration(), this.Width, this.Height, x.Metadata.DeepClone())); + IEnumerable> frames = source.Frames.Select, ImageFrame>( + x => new ImageFrame( + source.GetConfiguration(), + this.Width, + this.Height, + x.Metadata.DeepClone())); // Use the overload to prevent an extra frame being added return new Image(source.GetConfiguration(), source.Metadata.DeepClone(), frames); diff --git a/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.Generic.cs b/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.Generic.cs new file mode 100644 index 000000000..37c3a27cd --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.Generic.cs @@ -0,0 +1,346 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using System; +using System.Linq; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public abstract partial class ImageFrameCollectionTests + { + [GroupOutput("ImageFramesCollectionTests")] + public class Generic : ImageFrameCollectionTests + { + [Fact] + public void Constructor_ShouldCreateOneFrame() + { + Assert.Equal(1, this.Collection.Count); + } + + [Fact] + public void AddNewFrame_FramesMustHaveSameSize() + { + ArgumentException ex = Assert.Throws( + () => + { + this.Collection.AddFrame(new ImageFrame(Configuration.Default, 1, 1)); + }); + + Assert.StartsWith("Frame must have the same dimensions as the image.", ex.Message); + } + + [Fact] + public void AddNewFrame_Frame_FramesNotBeNull() + { + ArgumentNullException ex = Assert.Throws( + () => + { + this.Collection.AddFrame((ImageFrame)null); + }); + + Assert.StartsWith("Value cannot be null.", ex.Message); + } + + [Fact] + public void AddNewFrame_PixelBuffer_DataMustNotBeNull() + { + Rgba32[] data = null; + + ArgumentNullException ex = Assert.Throws( + () => + { + this.Collection.AddFrame(data); + }); + + Assert.StartsWith("Value cannot be null.", ex.Message); + } + + [Fact] + public void AddNewFrame_PixelBuffer_BufferIncorrectSize() + { + ArgumentOutOfRangeException ex = Assert.Throws( + () => + { + this.Collection.AddFrame(new Rgba32[0]); + }); + + Assert.StartsWith("Value 0 must be greater than or equal to 100.", ex.Message); + } + + [Fact] + public void InsertNewFrame_FramesMustHaveSameSize() + { + ArgumentException ex = Assert.Throws( + () => + { + this.Collection.InsertFrame(1, new ImageFrame(Configuration.Default, 1, 1)); + }); + + Assert.StartsWith("Frame must have the same dimensions as the image.", ex.Message); + } + + [Fact] + public void InsertNewFrame_FramesNotBeNull() + { + ArgumentNullException ex = Assert.Throws( + () => + { + this.Collection.InsertFrame(1, null); + }); + + Assert.StartsWith("Value cannot be null.", ex.Message); + } + + [Fact] + public void Constructor_FramesMustHaveSameSize() + { + ArgumentException ex = Assert.Throws( + () => + { + var collection = new ImageFrameCollection( + this.Image, + new[] + { + new ImageFrame(Configuration.Default, 10, 10), + new ImageFrame(Configuration.Default, 1, 1) + }); + }); + + Assert.StartsWith("Frame must have the same dimensions as the image.", ex.Message); + } + + [Fact] + public void RemoveAtFrame_ThrowIfRemovingLastFrame() + { + var collection = new ImageFrameCollection( + this.Image, + new[] { new ImageFrame(Configuration.Default, 10, 10) }); + + InvalidOperationException ex = Assert.Throws( + () => + { + collection.RemoveFrame(0); + }); + Assert.Equal("Cannot remove last frame.", ex.Message); + } + + [Fact] + public void RemoveAtFrame_CanRemoveFrameZeroIfMultipleFramesExist() + { + var collection = new ImageFrameCollection( + this.Image, + new[] + { + new ImageFrame(Configuration.Default, 10, 10), + new ImageFrame(Configuration.Default, 10, 10) + }); + + collection.RemoveFrame(0); + Assert.Equal(1, collection.Count); + } + + [Fact] + public void RootFrameIsFrameAtIndexZero() + { + var collection = new ImageFrameCollection( + this.Image, + new[] + { + new ImageFrame(Configuration.Default, 10, 10), + new ImageFrame(Configuration.Default, 10, 10) + }); + + Assert.Equal(collection.RootFrame, collection[0]); + } + + [Fact] + public void ConstructorPopulatesFrames() + { + var collection = new ImageFrameCollection( + this.Image, + new[] + { + new ImageFrame(Configuration.Default, 10, 10), + new ImageFrame(Configuration.Default, 10, 10) + }); + + Assert.Equal(2, collection.Count); + } + + [Fact] + public void DisposeClearsCollection() + { + var collection = new ImageFrameCollection( + this.Image, + new[] + { + new ImageFrame(Configuration.Default, 10, 10), + new ImageFrame(Configuration.Default, 10, 10) + }); + + collection.Dispose(); + + Assert.Equal(0, collection.Count); + } + + [Fact] + public void Dispose_DisposesAllInnerFrames() + { + var collection = new ImageFrameCollection( + this.Image, + new[] + { + new ImageFrame(Configuration.Default, 10, 10), + new ImageFrame(Configuration.Default, 10, 10) + }); + + IPixelSource[] framesSnapShot = collection.OfType>().ToArray(); + collection.Dispose(); + + Assert.All( + framesSnapShot, + f => + { + // the pixel source of the frame is null after its been disposed. + Assert.Null(f.PixelBuffer); + }); + } + + [Theory] + [WithTestPatternImages(10, 10, PixelTypes.Rgba32)] + public void CloneFrame(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image img = provider.GetImage()) + { + img.Frames.AddFrame(new ImageFrame(Configuration.Default, 10, 10)); // add a frame anyway + using (Image cloned = img.Frames.CloneFrame(0)) + { + Assert.Equal(2, img.Frames.Count); + cloned.ComparePixelBufferTo(img.GetPixelSpan()); + } + } + } + + [Theory] + [WithTestPatternImages(10, 10, PixelTypes.Rgba32)] + public void ExtractFrame(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image img = provider.GetImage()) + { + var sourcePixelData = img.GetPixelSpan().ToArray(); + + img.Frames.AddFrame(new ImageFrame(Configuration.Default, 10, 10)); + using (Image cloned = img.Frames.ExportFrame(0)) + { + Assert.Equal(1, img.Frames.Count); + cloned.ComparePixelBufferTo(sourcePixelData); + } + } + } + + [Fact] + public void CreateFrame_Default() + { + this.Image.Frames.CreateFrame(); + + Assert.Equal(2, this.Image.Frames.Count); + this.Image.Frames[1].ComparePixelBufferTo(default(Rgba32)); + } + + [Fact] + public void CreateFrame_CustomFillColor() + { + this.Image.Frames.CreateFrame(Rgba32.HotPink); + + Assert.Equal(2, this.Image.Frames.Count); + this.Image.Frames[1].ComparePixelBufferTo(Rgba32.HotPink); + } + + [Fact] + public void AddFrameFromPixelData() + { + var pixelData = this.Image.Frames.RootFrame.GetPixelSpan().ToArray(); + this.Image.Frames.AddFrame(pixelData); + Assert.Equal(2, this.Image.Frames.Count); + } + + [Fact] + public void AddFrame_clones_sourceFrame() + { + var pixelData = this.Image.Frames.RootFrame.GetPixelSpan().ToArray(); + var otherFRame = new ImageFrame(Configuration.Default, 10, 10); + var addedFrame = this.Image.Frames.AddFrame(otherFRame); + addedFrame.ComparePixelBufferTo(otherFRame.GetPixelSpan()); + Assert.NotEqual(otherFRame, addedFrame); + } + + [Fact] + public void InsertFrame_clones_sourceFrame() + { + var pixelData = this.Image.Frames.RootFrame.GetPixelSpan().ToArray(); + var otherFRame = new ImageFrame(Configuration.Default, 10, 10); + var addedFrame = this.Image.Frames.InsertFrame(0, otherFRame); + addedFrame.ComparePixelBufferTo(otherFRame.GetPixelSpan()); + Assert.NotEqual(otherFRame, addedFrame); + } + + [Fact] + public void MoveFrame_LeavesFrmaeInCorrectLocation() + { + for (var i = 0; i < 9; i++) + { + this.Image.Frames.CreateFrame(); + } + + var frame = this.Image.Frames[4]; + this.Image.Frames.MoveFrame(4, 7); + var newIndex = this.Image.Frames.IndexOf(frame); + Assert.Equal(7, newIndex); + } + + [Fact] + public void IndexOf_ReturnsCorrectIndex() + { + for (var i = 0; i < 9; i++) + { + this.Image.Frames.CreateFrame(); + } + + var frame = this.Image.Frames[4]; + var index = this.Image.Frames.IndexOf(frame); + Assert.Equal(4, index); + } + + [Fact] + public void Contains_TrueIfMember() + { + for (var i = 0; i < 9; i++) + { + this.Image.Frames.CreateFrame(); + } + + var frame = this.Image.Frames[4]; + Assert.True(this.Image.Frames.Contains(frame)); + } + + [Fact] + public void Contains_FalseIfNonMember() + { + for (var i = 0; i < 9; i++) + { + this.Image.Frames.CreateFrame(); + } + + var frame = new ImageFrame(Configuration.Default, 10, 10); + Assert.False(this.Image.Frames.Contains(frame)); + } + } + } +} diff --git a/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs b/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs new file mode 100644 index 000000000..0956cce9c --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs @@ -0,0 +1,325 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using System; +using System.Drawing.Imaging; +using System.Linq; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Formats.Gif; +using SixLabors.ImageSharp.PixelFormats; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests +{ + public abstract partial class ImageFrameCollectionTests + { + [GroupOutput("ImageFramesCollectionTests")] + public class NonGeneric : ImageFrameCollectionTests + { + private new Image Image => base.Image; + + private new ImageFrameCollection Collection => base.Collection; + + [Fact] + public void AddFrame_OfDifferentPixelType() + { + using (Image sourceImage = new Image( + this.Image.GetConfiguration(), + this.Image.Width, + this.Image.Height, + (Bgra32)Color.Blue)) + { + this.Collection.AddFrame(sourceImage.Frames.RootFrame); + } + + Rgba32[] expectedAllBlue = + Enumerable.Repeat(Rgba32.Blue, this.Image.Width * this.Image.Height).ToArray(); + + Assert.Equal(2, this.Collection.Count); + ImageFrame actualFrame = (ImageFrame)this.Collection[1]; + + actualFrame.ComparePixelBufferTo(expectedAllBlue); + } + + [Fact] + public void InsertFrame_OfDifferentPixelType() + { + using (Image sourceImage = new Image( + this.Image.GetConfiguration(), + this.Image.Width, + this.Image.Height, + (Bgra32)Color.Blue)) + { + this.Collection.InsertFrame(0, sourceImage.Frames.RootFrame); + } + + Rgba32[] expectedAllBlue = + Enumerable.Repeat(Rgba32.Blue, this.Image.Width * this.Image.Height).ToArray(); + + Assert.Equal(2, this.Collection.Count); + ImageFrame actualFrame = (ImageFrame)this.Collection[0]; + + actualFrame.ComparePixelBufferTo(expectedAllBlue); + + } + + [Fact] + public void Constructor_ShouldCreateOneFrame() + { + Assert.Equal(1, this.Collection.Count); + } + + [Fact] + public void AddNewFrame_FramesMustHaveSameSize() + { + ArgumentException ex = Assert.Throws( + () => + { + this.Collection.AddFrame(new ImageFrame(Configuration.Default, 1, 1)); + }); + + Assert.StartsWith("Frame must have the same dimensions as the image.", ex.Message); + } + + [Fact] + public void AddNewFrame_Frame_FramesNotBeNull() + { + ArgumentNullException ex = Assert.Throws( + () => + { + this.Collection.AddFrame((ImageFrame)null); + }); + + Assert.StartsWith("Value cannot be null.", ex.Message); + } + + [Fact] + public void InsertNewFrame_FramesMustHaveSameSize() + { + ArgumentException ex = Assert.Throws( + () => + { + this.Collection.InsertFrame(1, new ImageFrame(Configuration.Default, 1, 1)); + }); + + Assert.StartsWith("Frame must have the same dimensions as the image.", ex.Message); + } + + [Fact] + public void InsertNewFrame_FramesNotBeNull() + { + ArgumentNullException ex = Assert.Throws( + () => + { + this.Collection.InsertFrame(1, null); + }); + + Assert.StartsWith("Value cannot be null.", ex.Message); + } + + + [Fact] + public void RemoveAtFrame_ThrowIfRemovingLastFrame() + { + + InvalidOperationException ex = Assert.Throws( + () => + { + this.Collection.RemoveFrame(0); + }); + Assert.Equal("Cannot remove last frame.", ex.Message); + } + + [Fact] + public void RemoveAtFrame_CanRemoveFrameZeroIfMultipleFramesExist() + { + this.Collection.AddFrame(new ImageFrame(Configuration.Default, 10, 10)); + + this.Collection.RemoveFrame(0); + Assert.Equal(1, this.Collection.Count); + } + + [Fact] + public void RootFrameIsFrameAtIndexZero() + { + Assert.Equal(this.Collection.RootFrame, this.Collection[0]); + } + + [Theory] + [WithTestPatternImages(10, 10, PixelTypes.Rgba32 | PixelTypes.Bgr24)] + public void CloneFrame(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image img = provider.GetImage()) + { + ImageFrameCollection nonGenericFrameCollection = img.Frames; + + nonGenericFrameCollection.AddFrame(new ImageFrame(Configuration.Default, 10, 10)); // add a frame anyway + using (Image cloned = nonGenericFrameCollection.CloneFrame(0)) + { + Assert.Equal(2, img.Frames.Count); + + Image expectedClone = (Image)cloned; + + expectedClone.ComparePixelBufferTo(img.GetPixelSpan()); + } + } + } + + [Theory] + [WithTestPatternImages(10, 10, PixelTypes.Rgba32)] + public void ExtractFrame(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image img = provider.GetImage()) + { + var sourcePixelData = img.GetPixelSpan().ToArray(); + + ImageFrameCollection nonGenericFrameCollection = img.Frames; + + nonGenericFrameCollection.AddFrame(new ImageFrame(Configuration.Default, 10, 10)); + using (Image cloned = nonGenericFrameCollection.ExportFrame(0)) + { + Assert.Equal(1, img.Frames.Count); + + Image expectedClone = (Image)cloned; + expectedClone.ComparePixelBufferTo(sourcePixelData); + } + } + } + + [Fact] + public void CreateFrame_Default() + { + this.Image.Frames.CreateFrame(); + + Assert.Equal(2, this.Image.Frames.Count); + + ImageFrame frame = (ImageFrame)this.Image.Frames[1]; + + frame.ComparePixelBufferTo(default(Rgba32)); + } + + [Fact] + public void CreateFrame_CustomFillColor() + { + this.Image.Frames.CreateFrame(Rgba32.HotPink); + + Assert.Equal(2, this.Image.Frames.Count); + + ImageFrame frame = (ImageFrame)this.Image.Frames[1]; + + frame.ComparePixelBufferTo(Rgba32.HotPink); + } + + [Fact] + public void MoveFrame_LeavesFrmaeInCorrectLocation() + { + for (var i = 0; i < 9; i++) + { + this.Image.Frames.CreateFrame(); + } + + var frame = this.Image.Frames[4]; + this.Image.Frames.MoveFrame(4, 7); + var newIndex = this.Image.Frames.IndexOf(frame); + Assert.Equal(7, newIndex); + } + + [Fact] + public void IndexOf_ReturnsCorrectIndex() + { + for (var i = 0; i < 9; i++) + { + this.Image.Frames.CreateFrame(); + } + + var frame = this.Image.Frames[4]; + var index = this.Image.Frames.IndexOf(frame); + Assert.Equal(4, index); + } + + [Fact] + public void Contains_TrueIfMember() + { + for (var i = 0; i < 9; i++) + { + this.Image.Frames.CreateFrame(); + } + + var frame = this.Image.Frames[4]; + Assert.True(this.Image.Frames.Contains(frame)); + } + + [Fact] + public void Contains_FalseIfNonMember() + { + for (var i = 0; i < 9; i++) + { + this.Image.Frames.CreateFrame(); + } + + var frame = new ImageFrame(Configuration.Default, 10, 10); + Assert.False(this.Image.Frames.Contains(frame)); + } + + /// + /// Integration test for end-to end API validation. + /// + [Theory] + [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)] + public void ConstructGif_FromDifferentPixelTypes(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (Image dest = new Image(source.GetConfiguration(), source.Width, source.Height)) + { + // Giphy.gif has 5 frames + + ImportFrameAs(source.Frames, dest.Frames, 0); + ImportFrameAs(source.Frames, dest.Frames, 1); + ImportFrameAs(source.Frames, dest.Frames, 2); + ImportFrameAs(source.Frames, dest.Frames, 3); + ImportFrameAs(source.Frames, dest.Frames, 4); + + // Drop the original empty root frame: + dest.Frames.RemoveFrame(0); + + dest.DebugSave(provider, appendSourceFileOrDescription: false, extension: "gif"); + dest.CompareToOriginal(provider); + + for (int i = 0; i < 5; i++) + { + CompareGifMetadata(source.Frames[i], dest.Frames[i]); + } + } + } + + private static void ImportFrameAs(ImageFrameCollection source, ImageFrameCollection destination, int index) + where TPixel : struct, IPixel + { + using (Image temp = source.CloneFrame(index)) + { + using (Image temp2 = temp.CloneAs()) + { + destination.AddFrame(temp2.Frames.RootFrame); + } + } + } + + private static void CompareGifMetadata(ImageFrame a, ImageFrame b) + { + // TODO: all metadata classes should be equatable! + + GifFrameMetadata aData = a.Metadata.GetFormatMetadata(GifFormat.Instance); + GifFrameMetadata bData = b.Metadata.GetFormatMetadata(GifFormat.Instance); + + Assert.Equal(aData.DisposalMethod, bData.DisposalMethod); + Assert.Equal(aData.FrameDelay, bData.FrameDelay); + Assert.Equal(aData.ColorTableLength, bData.ColorTableLength); + } + } + } +} diff --git a/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.cs b/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.cs new file mode 100644 index 000000000..a29f45271 --- /dev/null +++ b/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Tests +{ + public abstract partial class ImageFrameCollectionTests : IDisposable + { + protected Image Image { get; } + protected ImageFrameCollection Collection { get; } + + public ImageFrameCollectionTests() + { + // Needed to get English exception messages, which are checked in several tests. + System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US"); + + this.Image = new Image(10, 10); + this.Collection = new ImageFrameCollection(this.Image, 10, 10, default(Rgba32)); + } + + public void Dispose() + { + this.Image.Dispose(); + this.Collection.Dispose(); + } + } +} diff --git a/tests/ImageSharp.Tests/Image/ImageFramesCollectionTests.cs b/tests/ImageSharp.Tests/Image/ImageFramesCollectionTests.cs deleted file mode 100644 index 392397057..000000000 --- a/tests/ImageSharp.Tests/Image/ImageFramesCollectionTests.cs +++ /dev/null @@ -1,331 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.PixelFormats; -using Xunit; - -namespace SixLabors.ImageSharp.Tests -{ - public class ImageFramesCollectionTests : IDisposable - { - private Image image; - private ImageFrameCollection collection; - - public ImageFramesCollectionTests() - { - // Needed to get English exception messages, which are checked in several tests. - System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US"); - - this.image = new Image(10, 10); - this.collection = new ImageFrameCollection(this.image, 10, 10, default(Rgba32)); - } - - [Fact] - public void ImageFramesaLwaysHaveOneFrame() - { - Assert.Equal(1, this.collection.Count); - } - - [Fact] - public void AddNewFrame_FramesMustHaveSameSize() - { - ArgumentException ex = Assert.Throws(() => - { - this.collection.AddFrame(new ImageFrame(Configuration.Default, 1, 1)); - }); - - Assert.StartsWith("Frame must have the same dimensions as the image.", ex.Message); - } - - [Fact] - public void AddNewFrame_Frame_FramesNotBeNull() - { - ArgumentNullException ex = Assert.Throws(() => - { - this.collection.AddFrame((ImageFrame)null); - }); - - Assert.StartsWith("Value cannot be null.", ex.Message); - } - - [Fact] - public void AddNewFrame_PixelBuffer_DataMustNotBeNull() - { - Rgba32[] data = null; - - ArgumentNullException ex = Assert.Throws(() => - { - this.collection.AddFrame(data); - }); - - Assert.StartsWith("Value cannot be null.", ex.Message); - } - - [Fact] - public void AddNewFrame_PixelBuffer_BufferIncorrectSize() - { - ArgumentOutOfRangeException ex = Assert.Throws(() => - { - this.collection.AddFrame(new Rgba32[0]); - }); - - Assert.StartsWith("Value 0 must be greater than or equal to 100.", ex.Message); - } - - [Fact] - public void InsertNewFrame_FramesMustHaveSameSize() - { - ArgumentException ex = Assert.Throws(() => - { - this.collection.InsertFrame(1, new ImageFrame(Configuration.Default, 1, 1)); - }); - - Assert.StartsWith("Frame must have the same dimensions as the image.", ex.Message); - } - - [Fact] - public void InsertNewFrame_FramesNotBeNull() - { - ArgumentNullException ex = Assert.Throws(() => - { - this.collection.InsertFrame(1, null); - }); - - Assert.StartsWith("Value cannot be null.", ex.Message); - } - - [Fact] - public void Constructor_FramesMustHaveSameSize() - { - ArgumentException ex = Assert.Throws(() => - { - var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default,10,10), - new ImageFrame(Configuration.Default,1,1) - }); - }); - - Assert.StartsWith("Frame must have the same dimensions as the image.", ex.Message); - } - - [Fact] - public void RemoveAtFrame_ThrowIfRemovingLastFrame() - { - var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default,10,10) - }); - - InvalidOperationException ex = Assert.Throws(() => - { - collection.RemoveFrame(0); - }); - Assert.Equal("Cannot remove last frame.", ex.Message); - } - - [Fact] - public void RemoveAtFrame_CanRemoveFrameZeroIfMultipleFramesExist() - { - - var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default,10,10), - new ImageFrame(Configuration.Default,10,10) - }); - - collection.RemoveFrame(0); - Assert.Equal(1, collection.Count); - } - - [Fact] - public void RootFrameIsFrameAtIndexZero() - { - var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default,10,10), - new ImageFrame(Configuration.Default,10,10) - }); - - Assert.Equal(collection.RootFrame, collection[0]); - } - - [Fact] - public void ConstructorPopulatesFrames() - { - var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default,10,10), - new ImageFrame(Configuration.Default,10,10) - }); - - Assert.Equal(2, collection.Count); - } - - [Fact] - public void DisposeClearsCollection() - { - var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default,10,10), - new ImageFrame(Configuration.Default,10,10) - }); - - collection.Dispose(); - - Assert.Equal(0, collection.Count); - } - - [Fact] - public void Dispose_DisposesAllInnerFrames() - { - var collection = new ImageFrameCollection(this.image, new[] { - new ImageFrame(Configuration.Default,10,10), - new ImageFrame(Configuration.Default,10,10) - }); - - IPixelSource[] framesSnapShot = collection.OfType>().ToArray(); - collection.Dispose(); - - Assert.All(framesSnapShot, f => - { - // the pixel source of the frame is null after its been disposed. - Assert.Null(f.PixelBuffer); - }); - } - - [Theory] - [WithTestPatternImages(10, 10, PixelTypes.Rgba32)] - public void CloneFrame(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image img = provider.GetImage()) - { - img.Frames.AddFrame(new ImageFrame(Configuration.Default, 10, 10));// add a frame anyway - using (Image cloned = img.Frames.CloneFrame(0)) - { - Assert.Equal(2, img.Frames.Count); - cloned.ComparePixelBufferTo(img.GetPixelSpan()); - } - } - } - - [Theory] - [WithTestPatternImages(10, 10, PixelTypes.Rgba32)] - public void ExtractFrame(TestImageProvider provider) - where TPixel : struct, IPixel - { - using (Image img = provider.GetImage()) - { - var sourcePixelData = img.GetPixelSpan().ToArray(); - - img.Frames.AddFrame(new ImageFrame(Configuration.Default, 10, 10)); - using (Image cloned = img.Frames.ExportFrame(0)) - { - Assert.Equal(1, img.Frames.Count); - cloned.ComparePixelBufferTo(sourcePixelData); - } - } - } - - [Fact] - public void CreateFrame_Default() - { - this.image.Frames.CreateFrame(); - - Assert.Equal(2, this.image.Frames.Count); - this.image.Frames[1].ComparePixelBufferTo(default(Rgba32)); - } - - [Fact] - public void CreateFrame_CustomFillColor() - { - this.image.Frames.CreateFrame(Rgba32.HotPink); - - Assert.Equal(2, this.image.Frames.Count); - this.image.Frames[1].ComparePixelBufferTo(Rgba32.HotPink); - } - - [Fact] - public void AddFrameFromPixelData() - { - var pixelData = this.image.Frames.RootFrame.GetPixelSpan().ToArray(); - this.image.Frames.AddFrame(pixelData); - Assert.Equal(2, this.image.Frames.Count); - } - - [Fact] - public void AddFrame_clones_sourceFrame() - { - var pixelData = this.image.Frames.RootFrame.GetPixelSpan().ToArray(); - var otherFRame = new ImageFrame(Configuration.Default, 10, 10); - var addedFrame = this.image.Frames.AddFrame(otherFRame); - addedFrame.ComparePixelBufferTo(otherFRame.GetPixelSpan()); - Assert.NotEqual(otherFRame, addedFrame); - } - - [Fact] - public void InsertFrame_clones_sourceFrame() - { - var pixelData = this.image.Frames.RootFrame.GetPixelSpan().ToArray(); - var otherFRame = new ImageFrame(Configuration.Default, 10, 10); - var addedFrame = this.image.Frames.InsertFrame(0, otherFRame); - addedFrame.ComparePixelBufferTo(otherFRame.GetPixelSpan()); - Assert.NotEqual(otherFRame, addedFrame); - } - - [Fact] - public void MoveFrame_LeavesFrmaeInCorrectLocation() - { - for (var i = 0; i < 9; i++) - { - this.image.Frames.CreateFrame(); - } - - var frame = this.image.Frames[4]; - this.image.Frames.MoveFrame(4, 7); - var newIndex = this.image.Frames.IndexOf(frame); - Assert.Equal(7, newIndex); - } - - - [Fact] - public void IndexOf_ReturnsCorrectIndex() - { - for (var i = 0; i < 9; i++) - { - this.image.Frames.CreateFrame(); - } - - var frame = this.image.Frames[4]; - var index = this.image.Frames.IndexOf(frame); - Assert.Equal(4, index); - } - - [Fact] - public void Contains_TrueIfMember() - { - for (var i = 0; i < 9; i++) - { - this.image.Frames.CreateFrame(); - } - - var frame = this.image.Frames[4]; - Assert.True(this.image.Frames.Contains(frame)); - } - - [Fact] - public void Contains_TFalseIfNoneMember() - { - for (var i = 0; i < 9; i++) - { - this.image.Frames.CreateFrame(); - } - - var frame = new ImageFrame(Configuration.Default, 10, 10); - Assert.False(this.image.Frames.Contains(frame)); - } - - public void Dispose() - { - this.image.Dispose(); - this.collection.Dispose(); - } - } -} diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 406719ab4..4f92f4007 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -2,6 +2,13 @@ + netcoreapp2.1;net462;net472 + True + latest + full + portable + True + SixLabors.ImageSharp.Tests SixLabors.ImageSharp.Tests AnyCPU;x64;x86 SixLabors.ImageSharp.Tests diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs new file mode 100644 index 000000000..d03cfeee2 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs @@ -0,0 +1,115 @@ +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +// // Copyright (c) Six Labors and contributors. +// // Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Tests.PixelFormats +{ + public abstract partial class PixelConverterTests + { + public static class ReferenceImplementations + { + public static Rgba32 MakeRgba32(byte r, byte g, byte b, byte a) + { + Rgba32 d = default; + d.R = r; + d.G = g; + d.B = b; + d.A = a; + return d; + } + + public static Argb32 MakeArgb32(byte r, byte g, byte b, byte a) + { + Argb32 d = default; + d.R = r; + d.G = g; + d.B = b; + d.A = a; + return d; + } + + public static Bgra32 MakeBgra32(byte r, byte g, byte b, byte a) + { + Bgra32 d = default; + d.R = r; + d.G = g; + d.B = b; + d.A = a; + return d; + } + + internal static void To( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + where TSourcePixel : struct, IPixel where TDestinationPixel : struct, IPixel + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); + + int count = sourcePixels.Length; + ref TSourcePixel sourceRef = ref MemoryMarshal.GetReference(sourcePixels); + + if (typeof(TSourcePixel) == typeof(TDestinationPixel)) + { + Span uniformDest = + MemoryMarshal.Cast(destinationPixels); + sourcePixels.CopyTo(uniformDest); + return; + } + + // Gray8 and Gray16 are special implementations of IPixel in that they do not conform to the + // standard RGBA colorspace format and must be converted from RGBA using the special ITU BT709 algorithm. + // One of the requirements of FromScaledVector4/ToScaledVector4 is that it unaware of this and + // packs/unpacks the pixel without and conversion so we employ custom methods do do this. + if (typeof(TDestinationPixel) == typeof(Gray16)) + { + ref Gray16 gray16Ref = ref MemoryMarshal.GetReference( + MemoryMarshal.Cast(destinationPixels)); + for (int i = 0; i < count; i++) + { + ref TSourcePixel sp = ref Unsafe.Add(ref sourceRef, i); + ref Gray16 dp = ref Unsafe.Add(ref gray16Ref, i); + dp.ConvertFromRgbaScaledVector4(sp.ToScaledVector4()); + } + + return; + } + + if (typeof(TDestinationPixel) == typeof(Gray8)) + { + ref Gray8 gray8Ref = ref MemoryMarshal.GetReference( + MemoryMarshal.Cast(destinationPixels)); + for (int i = 0; i < count; i++) + { + ref TSourcePixel sp = ref Unsafe.Add(ref sourceRef, i); + ref Gray8 dp = ref Unsafe.Add(ref gray8Ref, i); + dp.ConvertFromRgbaScaledVector4(sp.ToScaledVector4()); + } + + return; + } + + // Normal conversion + ref TDestinationPixel destRef = ref MemoryMarshal.GetReference(destinationPixels); + for (int i = 0; i < count; i++) + { + ref TSourcePixel sp = ref Unsafe.Add(ref sourceRef, i); + ref TDestinationPixel dp = ref Unsafe.Add(ref destRef, i); + dp.FromScaledVector4(sp.ToScaledVector4()); + } + } + } + } +} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs index c539e9dcf..f1f56fcd4 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs @@ -5,7 +5,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { - public abstract class PixelConverterTests + public abstract partial class PixelConverterTests { public static readonly TheoryData RgbaData = new TheoryData @@ -122,39 +122,5 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats Assert.Equal(expectedPacked, actualPacked); } } - - - private static class ReferenceImplementations - { - public static Rgba32 MakeRgba32(byte r, byte g, byte b, byte a) - { - Rgba32 d = default; - d.R = r; - d.G = g; - d.B = b; - d.A = a; - return d; - } - - public static Argb32 MakeArgb32(byte r, byte g, byte b, byte a) - { - Argb32 d = default; - d.R = r; - d.G = g; - d.B = b; - d.A = a; - return d; - } - - public static Bgra32 MakeBgra32(byte r, byte g, byte b, byte a) - { - Bgra32 d = default; - d.R = r; - d.G = g; - d.B = b; - d.A = a; - return d; - } - } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra5551OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra5551OperationsTests.cs new file mode 100644 index 000000000..aa9b7bb1b --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra5551OperationsTests.cs @@ -0,0 +1,20 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + public class Bgra5551OperationsTests : PixelOperationsTests + { + public Bgra5551OperationsTests(ITestOutputHelper output) + : base(output) + { + } + } + } +} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs index c3de33547..f44401ae9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray16OperationsTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -25,90 +26,6 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations [Fact] public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - [Theory] - [MemberData(nameof(ArraySizesData))] - public void FromGray8Bytes(int count) - { - byte[] source = CreateByteTestData(count); - var expected = new Gray16[count]; - - for (int i = 0; i < count; i++) - { - expected[i].FromGray8(new Gray8(source[i])); - } - - TestOperation( - source, - expected, - (s, d) => Operations.FromGray8Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void ToGray8Bytes(int count) - { - Gray16[] source = CreatePixelTestData(count); - byte[] expected = new byte[count]; - var gray = default(Gray8); - - for (int i = 0; i < count; i++) - { - gray.FromScaledVector4(source[i].ToScaledVector4()); - expected[i] = gray.PackedValue; - } - - TestOperation( - source, - expected, - (s, d) => Operations.ToGray8Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void FromGray16Bytes(int count) - { - byte[] source = CreateByteTestData(count * 2); - Span sourceSpan = source.AsSpan(); - var expected = new Gray16[count]; - - for (int i = 0; i < count; i++) - { - int i2 = i * 2; - expected[i].FromGray16(MemoryMarshal.Cast(sourceSpan.Slice(i2, 2))[0]); - } - - TestOperation( - source, - expected, - (s, d) => Operations.FromGray16Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void ToGray16Bytes(int count) - { - Gray16[] source = CreatePixelTestData(count); - byte[] expected = new byte[count * 2]; - Gray16 gray = default; - - for (int i = 0; i < count; i++) - { - int i2 = i * 2; - gray.FromScaledVector4(source[i].ToScaledVector4()); - OctetBytes bytes = Unsafe.As(ref gray); - expected[i2] = bytes[0]; - expected[i2 + 1] = bytes[1]; - } - - TestOperation( - source, - expected, - (s, d) => Operations.ToGray16Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs index acd6ef23a..30c429000 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Gray8OperationsTests.cs @@ -24,91 +24,6 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations [Fact] public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void FromGray8Bytes(int count) - { - byte[] source = CreateByteTestData(count); - var expected = new Gray8[count]; - - for (int i = 0; i < count; i++) - { - expected[i].FromGray8(new Gray8(source[i])); - } - - TestOperation( - source, - expected, - (s, d) => Operations.FromGray8Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void ToGray8Bytes(int count) - { - Gray8[] source = CreatePixelTestData(count); - byte[] expected = new byte[count]; - var gray = default(Gray8); - - for (int i = 0; i < count; i++) - { - gray.FromScaledVector4(source[i].ToScaledVector4()); - expected[i] = gray.PackedValue; - } - - TestOperation( - source, - expected, - (s, d) => Operations.ToGray8Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void FromGray16Bytes(int count) - { - byte[] source = CreateByteTestData(count * 2); - Span sourceSpan = source.AsSpan(); - var expected = new Gray8[count]; - - for (int i = 0; i < count; i++) - { - int i2 = i * 2; - expected[i].FromGray16(MemoryMarshal.Cast(sourceSpan.Slice(i2, 2))[0]); - } - - TestOperation( - source, - expected, - (s, d) => Operations.FromGray16Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } - - [Theory] - [MemberData(nameof(ArraySizesData))] - public void ToGray16Bytes(int count) - { - Gray8[] source = CreatePixelTestData(count); - byte[] expected = new byte[count * 2]; - Gray16 gray = default; - - for (int i = 0; i < count; i++) - { - int i2 = i * 2; - gray.FromScaledVector4(source[i].ToScaledVector4()); - OctetBytes bytes = Unsafe.As(ref gray); - expected[i2] = bytes[0]; - expected[i2 + 1] = bytes[1]; - } - - TestOperation( - source, - expected, - (s, d) => Operations.ToGray16Bytes(this.Configuration, s, d.GetSpan(), count) - ); - } } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs index 1c7d312d3..37793911a 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs @@ -21,4 +21,4 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index d9ae9131f..71adc1749 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -3,12 +3,14 @@ using System; using System.Buffers; +using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.ColorSpaces.Companding; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils; using Xunit; using Xunit.Abstractions; @@ -245,7 +247,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { Vector4Utils.UnPremultiply(ref v); } - + SRgbCompanding.Compress(ref v); } @@ -277,6 +279,33 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations ); } + + public static readonly TheoryData Generic_To_Data = new TheoryData + { + default(Rgba32), + default(Bgra32), + default(Rgb24), + default(Gray8), + default(Gray16), + default(Rgb48), + default(Rgba64) + }; + + [Theory] + [MemberData(nameof(Generic_To_Data))] + public void Generic_To(TDestPixel dummy) + where TDestPixel : struct, IPixel + { + const int Count = 2134; + TPixel[] source = CreatePixelTestData(Count); + TDestPixel[] expected = new TDestPixel[Count]; + + PixelConverterTests.ReferenceImplementations.To(this.Configuration, source, expected); + + TestOperation(source, expected, (s, d) => Operations.To(this.Configuration, (ReadOnlySpan)s, d.GetSpan())); + } + + [Theory] [MemberData(nameof(ArraySizesData))] public void ToScaledVector4(int count) @@ -732,6 +761,92 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations ); } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void FromGray8(int count) + { + byte[] sourceBytes = CreateByteTestData(count); + Gray8[] source = sourceBytes.Select(b => new Gray8(b)).ToArray(); + var expected = new TPixel[count]; + + + for (int i = 0; i < count; i++) + { + expected[i].FromGray8(source[i]); + } + + TestOperation( + source, + expected, + (s, d) => Operations.FromGray8(this.Configuration, s, d.GetSpan()) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToGray8(int count) + { + TPixel[] source = CreatePixelTestData(count); + Gray8[] expected = new Gray8[count]; + + for (int i = 0; i < count; i++) + { + expected[i].FromScaledVector4(source[i].ToScaledVector4()); + } + + TestOperation( + source, + expected, + (s, d) => Operations.ToGray8(this.Configuration, s, d.GetSpan()) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void FromGray16(int count) + { + Gray16[] source = CreateVector4TestData(count).Select(v => + { + Gray16 g = default; + g.FromVector4(v); + return g; + }).ToArray(); + + var expected = new TPixel[count]; + + for (int i = 0; i < count; i++) + { + int i2 = i * 2; + expected[i].FromGray16(source[i]); + } + + TestOperation( + source, + expected, + (s, d) => Operations.FromGray16(this.Configuration, s, d.GetSpan()) + ); + } + + [Theory] + [MemberData(nameof(ArraySizesData))] + public void ToGray16(int count) + { + TPixel[] source = CreatePixelTestData(count); + Gray16[] expected = new Gray16[count]; + + for (int i = 0; i < count; i++) + { + expected[i].FromScaledVector4(source[i].ToScaledVector4()); + } + + TestOperation( + source, + expected, + (s, d) => Operations.ToGray16(this.Configuration, s, d.GetSpan()) + ); + } + public delegate void RefAction(ref T1 arg1); internal static Vector4[] CreateExpectedVector4Data(TPixel[] source, RefAction vectorModifier = null) @@ -903,6 +1018,18 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations // ReSharper restore PossibleNullReferenceException } } + else if (typeof(TDest) == typeof(Gray16)) + { + // Minor difference is tolerated for 16 bit pixel values + Span expected = MemoryMarshal.Cast(this.ExpectedDestBuffer.AsSpan()); + Span actual = MemoryMarshal.Cast(this.ActualDestBuffer.GetSpan()); + + for (int i = 0; i < count; i++) + { + int difference = expected[i].PackedValue - actual[i].PackedValue; + Assert.True(Math.Abs(difference) < 2); + } + } else { Span expected = this.ExpectedDestBuffer.AsSpan(); @@ -915,4 +1042,4 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations } } } -} \ No newline at end of file +}