From c31a53dc4cdbe50a791293d39ad89d888427e036 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 9 Jan 2025 10:30:05 +1000 Subject: [PATCH 1/4] API compatibility --- .editorconfig | 14 +-- .gitattributes | 10 ++ .github/workflows/build-and-test.yml | 40 ++++---- .../DrawShapesWithImageSharp.csproj | 4 +- .../ImageSharpLogo.cs | 2 +- shared-infrastructure | 2 +- .../Extensions/GraphicsOptionsExtensions.cs | 2 +- .../ImageSharp.Drawing.csproj | 14 +-- .../Processing/GradientBrush.cs | 7 +- .../Processing/PathGradientBrush.cs | 31 ++---- .../Processing/PatternBrush.cs | 4 +- .../Processors/Text/RichTextGlyphRenderer.cs | 2 +- .../Processing/RecolorBrush.cs | 6 +- .../Rasterization/ScanEdgeCollection.Build.cs | 3 + tests/Directory.Build.targets | 16 ++-- .../ImageSharp.Drawing.Benchmarks.csproj | 10 +- .../ConfigurationTests.cs | 2 +- .../Drawing/DrawBezierTests.cs | 4 +- .../Drawing/DrawComplexPolygonTests.cs | 6 +- .../Drawing/DrawPathTests.cs | 4 +- .../Drawing/DrawingRobustnessTests.cs | 2 +- .../Drawing/FillComplexPolygonTests.cs | 6 +- .../Drawing/FillLinearGradientBrushTests.cs | 6 +- .../Drawing/FillOutsideBoundsTests.cs | 2 +- .../Drawing/FillPathGradientBrushTests.cs | 13 +-- .../Drawing/FillPatternBrushTests.cs | 34 +++---- .../Drawing/SolidBezierTests.cs | 3 +- .../Drawing/Text/DrawTextOnImageTests.cs | 48 +++++++++- .../ImageSharp.Drawing.Tests.csproj | 5 +- .../Issues/Issue_241.cs | 2 +- .../Issues/Issue_270.cs | 4 +- .../Issues/Issue_28_108.cs | 18 ++-- .../Issues/Issues_55_59.cs | 4 +- tests/ImageSharp.Drawing.Tests/TestFormat.cs | 87 ++++++----------- .../ImageComparison/ExactImageComparer.cs | 3 +- .../ImageComparison/TolerantImageComparer.cs | 2 +- .../BasicTestPatternProvider.cs | 6 +- .../ImageProviders/SolidProvider.cs | 2 +- .../ImageProviders/TestPatternProvider.cs | 12 +-- .../TestUtilities/ImagingTestCaseUtility.cs | 6 +- .../ReferenceCodecs/MagickReferenceDecoder.cs | 50 ++++++++-- .../ReferenceCodecUtilities.cs | 94 +++++++++++++++++++ .../SystemDrawingReferenceDecoder.cs | 26 +++-- .../TestUtilities/TestEnvironment.Formats.cs | 4 +- .../TestUtilities/TestImageExtensions.cs | 2 +- .../TestUtilities/TestPixel.cs | 12 +-- .../TestUtilities/TestUtils.cs | 5 +- .../Tests/TestImageProviderTests.cs | 15 ++- .../Tests/TestUtilityExtensionsTests.cs | 8 +- 49 files changed, 409 insertions(+), 255 deletions(-) create mode 100644 tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/ReferenceCodecUtilities.cs diff --git a/.editorconfig b/.editorconfig index 2e3045fb..af1e5b44 100644 --- a/.editorconfig +++ b/.editorconfig @@ -104,8 +104,8 @@ dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:war dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion # Expression-level preferences -dotnet_style_object_initializer = true:warning -dotnet_style_collection_initializer = true:warning +dotnet_style_object_initializer = true:error +dotnet_style_collection_initializer = true:error dotnet_style_explicit_tuple_names = true:warning dotnet_style_prefer_inferred_tuple_names = true:warning dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning @@ -135,9 +135,9 @@ csharp_style_prefer_null_check_over_type_check = true:warning # https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#c-style-rules [*.{cs,csx,cake}] # 'var' preferences -csharp_style_var_for_built_in_types = false:warning -csharp_style_var_when_type_is_apparent = false:warning -csharp_style_var_elsewhere = false:warning +csharp_style_var_for_built_in_types = false:error +csharp_style_var_when_type_is_apparent = false:error +csharp_style_var_elsewhere = false:error # Expression-bodied members csharp_style_expression_bodied_methods = true:warning csharp_style_expression_bodied_constructors = true:warning @@ -160,7 +160,7 @@ csharp_style_pattern_local_over_anonymous_function = true:warning csharp_style_deconstructed_variable_declaration = true:warning csharp_style_prefer_index_operator = true:warning csharp_style_prefer_range_operator = true:warning -csharp_style_implicit_object_creation_when_type_is_apparent = true:warning +csharp_style_implicit_object_creation_when_type_is_apparent = true:error # "Null" checking preferences csharp_style_throw_expression = true:warning csharp_style_conditional_delegate_call = true:warning @@ -172,6 +172,8 @@ dotnet_diagnostic.IDE0063.severity = suggestion csharp_using_directive_placement = outside_namespace:warning # Modifier preferences csharp_prefer_static_local_function = true:warning +# Primary constructor preferences +csharp_style_prefer_primary_constructors = false:none ########################################## # Unnecessary Code Rules diff --git a/.gitattributes b/.gitattributes index 3647a706..f7bd4d06 100644 --- a/.gitattributes +++ b/.gitattributes @@ -133,3 +133,13 @@ *.pnm filter=lfs diff=lfs merge=lfs -text *.wbmp filter=lfs diff=lfs merge=lfs -text *.exr filter=lfs diff=lfs merge=lfs -text +*.ico filter=lfs diff=lfs merge=lfs -text +*.cur filter=lfs diff=lfs merge=lfs -text +*.ani filter=lfs diff=lfs merge=lfs -text +*.heic filter=lfs diff=lfs merge=lfs -text +*.hif filter=lfs diff=lfs merge=lfs -text +*.avif filter=lfs diff=lfs merge=lfs -text +############################################################################### +# Handle ICC files by git lfs +############################################################################### +*.icc filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 4c3a36ae..c250e01f 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -18,44 +18,50 @@ jobs: - ${{ contains(github.event.pull_request.labels.*.name, 'arch:arm32') || contains(github.event.pull_request.labels.*.name, 'arch:arm64') }} options: - os: ubuntu-latest - framework: net7.0 - sdk: 7.0.x + framework: net9.0 + sdk: 9.0.x sdk-preview: true runtime: -x64 codecov: false - os: macos-13 # macos-latest runs on arm64 runners where libgdiplus is unavailable - framework: net7.0 - sdk: 7.0.x + framework: net9.0 + sdk: 9.0.x sdk-preview: true runtime: -x64 codecov: false - os: windows-latest - framework: net7.0 - sdk: 7.0.x + framework: net9.0 + sdk: 9.0.x sdk-preview: true runtime: -x64 codecov: false - os: buildjet-4vcpu-ubuntu-2204-arm - framework: net7.0 - sdk: 7.0.x + framework: net9.0 + sdk: 9.0.x sdk-preview: true runtime: -x64 codecov: false + - os: ubuntu-latest - framework: net6.0 - sdk: 6.0.x + framework: net8.0 + sdk: 8.0.x runtime: -x64 codecov: false - os: macos-13 # macos-latest runs on arm64 runners where libgdiplus is unavailable - framework: net6.0 - sdk: 6.0.x + framework: net8.0 + sdk: 8.0.x runtime: -x64 codecov: false - os: windows-latest - framework: net6.0 - sdk: 6.0.x + framework: net8.0 + sdk: 8.0.x runtime: -x64 - codecov: true + codecov: false + - os: buildjet-4vcpu-ubuntu-2204-arm + framework: net8.0 + sdk: 8.0.x + runtime: -x64 + codecov: false exclude: - isARM: false options: @@ -110,14 +116,14 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x + 8.0.x - name: DotNet Setup Preview if: ${{ matrix.options.sdk-preview == true }} uses: actions/setup-dotnet@v4 with: dotnet-version: | - 7.0.x + 9.0.x - name: DotNet Build if: ${{ matrix.options.sdk-preview != true }} diff --git a/samples/DrawShapesWithImageSharp/DrawShapesWithImageSharp.csproj b/samples/DrawShapesWithImageSharp/DrawShapesWithImageSharp.csproj index c9b0a852..a8711843 100644 --- a/samples/DrawShapesWithImageSharp/DrawShapesWithImageSharp.csproj +++ b/samples/DrawShapesWithImageSharp/DrawShapesWithImageSharp.csproj @@ -8,12 +8,12 @@ - net7.0;net6.0 + net9.0;net8.0 - net6.0 + net8.0 diff --git a/samples/DrawShapesWithImageSharp/ImageSharpLogo.cs b/samples/DrawShapesWithImageSharp/ImageSharpLogo.cs index 71380b05..00bd3114 100644 --- a/samples/DrawShapesWithImageSharp/ImageSharpLogo.cs +++ b/samples/DrawShapesWithImageSharp/ImageSharpLogo.cs @@ -62,7 +62,7 @@ public static void SaveLogo(float size, string path) img.Mutate(i => i.Fill(colors[s], segments[s].Transform(scaler))); } - img.Mutate(i => i.Fill(new Rgba32(0, 0, 0, 170), new ComplexPolygon(new EllipsePolygon(center, 161f), new EllipsePolygon(center, 61f)).Transform(scaler))); + img.Mutate(i => i.Fill(Color.FromPixel(new Rgba32(0, 0, 0, 170)), new ComplexPolygon(new EllipsePolygon(center, 161f), new EllipsePolygon(center, 61f)).Transform(scaler))); string fullPath = System.IO.Path.GetFullPath(System.IO.Path.Combine("Output", path)); diff --git a/shared-infrastructure b/shared-infrastructure index 353b9afe..5e13cde8 160000 --- a/shared-infrastructure +++ b/shared-infrastructure @@ -1 +1 @@ -Subproject commit 353b9afe32a8000410312d17263407cd7bb82d19 +Subproject commit 5e13cde851a3d6e95d0dfdde2a57071f1efda9c3 diff --git a/src/ImageSharp.Drawing/Common/Extensions/GraphicsOptionsExtensions.cs b/src/ImageSharp.Drawing/Common/Extensions/GraphicsOptionsExtensions.cs index 31fcc925..1f68e439 100644 --- a/src/ImageSharp.Drawing/Common/Extensions/GraphicsOptionsExtensions.cs +++ b/src/ImageSharp.Drawing/Common/Extensions/GraphicsOptionsExtensions.cs @@ -41,7 +41,7 @@ public static bool IsOpaqueColorWithoutBlending(this GraphicsOptions options, Co return false; } - if (((Vector4)color).W != Opaque) + if (color.ToScaledVector4().W != Opaque) { return false; } diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 44e9ed38..631dfae7 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -12,11 +12,12 @@ Image Draw Shape Path Font An extension to ImageSharp that allows the drawing of images, paths, and text. Debug;Release + true - - 2.0 + + 3.0 @@ -28,13 +29,12 @@ - net7.0;net6.0 - true + net8.0;net9.0 - net6.0 + net8.0 true @@ -45,8 +45,8 @@ - - + + \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processing/GradientBrush.cs b/src/ImageSharp.Drawing/Processing/GradientBrush.cs index 4b2364d9..065125c6 100644 --- a/src/ImageSharp.Drawing/Processing/GradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/GradientBrush.cs @@ -4,7 +4,6 @@ using System.Numerics; using SixLabors.ImageSharp.Drawing.Utilities; using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Drawing.Processing; @@ -138,7 +137,11 @@ protected GradientBrushApplicator( float onLocalGradient = (positionOnCompleteGradient - from.Ratio) / (to.Ratio - from.Ratio); // TODO: This should use premultiplied vectors to avoid bad blends e.g. red -> brown <- green. - return new Color(Vector4.Lerp((Vector4)from.Color, (Vector4)to.Color, onLocalGradient)).ToPixel(); + return Color.FromScaledVector( + Vector4.Lerp( + from.Color.ToScaledVector4(), + to.Color.ToScaledVector4(), + onLocalGradient)).ToPixel(); } } diff --git a/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs b/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs index da640936..78799c43 100644 --- a/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs +++ b/src/ImageSharp.Drawing/Processing/PathGradientBrush.cs @@ -22,10 +22,7 @@ public sealed class PathGradientBrush : Brush /// Array of colors that correspond to each point in the polygon. public PathGradientBrush(PointF[] points, Color[] colors) { - if (points == null) - { - throw new ArgumentNullException(nameof(points)); - } + ArgumentNullException.ThrowIfNull(points); if (points.Length < 3) { @@ -34,10 +31,7 @@ public PathGradientBrush(PointF[] points, Color[] colors) "There must be at least 3 lines to construct a path gradient brush."); } - if (colors == null) - { - throw new ArgumentNullException(nameof(colors)); - } + ArgumentNullException.ThrowIfNull(colors); if (colors.Length == 0) { @@ -106,10 +100,7 @@ public override BrushApplicator CreateApplicator( private static Color CalculateCenterColor(Color[] colors) { - if (colors == null) - { - throw new ArgumentNullException(nameof(colors)); - } + ArgumentNullException.ThrowIfNull(colors); if (colors.Length == 0) { @@ -118,7 +109,7 @@ private static Color CalculateCenterColor(Color[] colors) "One or more color is needed to construct a path gradient brush."); } - return new Color(colors.Select(c => (Vector4)c).Aggregate((p1, p2) => p1 + p2) / colors.Length); + return Color.FromScaledVector(colors.Select(c => c.ToScaledVector4()).Aggregate((p1, p2) => p1 + p2) / colors.Length); } private static float DistanceBetween(Vector2 p1, Vector2 p2) => (p2 - p1).Length(); @@ -147,8 +138,8 @@ public Edge(Vector2 start, Vector2 end, Color startColor, Color endColor) { this.Start = start; this.End = end; - this.StartColor = (Vector4)startColor; - this.EndColor = (Vector4)endColor; + this.StartColor = startColor.ToScaledVector4(); + this.EndColor = endColor.ToScaledVector4(); this.length = DistanceBetween(this.End, this.Start); } @@ -236,7 +227,7 @@ public PathGradientBrushApplicator( Vector2[] points = edges.Select(s => s.Start).ToArray(); this.center = points.Aggregate((p1, p2) => p1 + p2) / edges.Count; - this.centerColor = (Vector4)centerColor; + this.centerColor = centerColor.ToScaledVector4(); this.hasSpecialCenterColor = hasSpecialCenterColor; this.centerPixel = centerColor.ToPixel(); this.maxDistance = points.Select(p => p - this.center).Max(d => d.Length()); @@ -272,9 +263,7 @@ public PathGradientBrushApplicator( + (u * this.edges[0].EndColor) + (v * this.edges[2].StartColor); - TPixel px = default; - px.FromScaledVector4(pointColor); - return px; + return TPixel.FromScaledVector4(pointColor); } Vector2 direction = Vector2.Normalize(point - this.center); @@ -295,9 +284,7 @@ public PathGradientBrushApplicator( Vector4 color = Vector4.Lerp(edgeColor, this.centerColor, ratio); - TPixel pixel = default; - pixel.FromScaledVector4(color); - return pixel; + return TPixel.FromScaledVector4(color); } } diff --git a/src/ImageSharp.Drawing/Processing/PatternBrush.cs b/src/ImageSharp.Drawing/Processing/PatternBrush.cs index 1891f3ed..008add9d 100644 --- a/src/ImageSharp.Drawing/Processing/PatternBrush.cs +++ b/src/ImageSharp.Drawing/Processing/PatternBrush.cs @@ -54,8 +54,8 @@ public PatternBrush(Color foreColor, Color backColor, bool[,] pattern) /// The pattern. internal PatternBrush(Color foreColor, Color backColor, in DenseMatrix pattern) { - var foreColorVector = (Vector4)foreColor; - var backColorVector = (Vector4)backColor; + var foreColorVector = foreColor.ToScaledVector4(); + var backColorVector = backColor.ToScaledVector4(); 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++) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/RichTextGlyphRenderer.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/RichTextGlyphRenderer.cs index 985a3f2f..db1fd377 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/RichTextGlyphRenderer.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/RichTextGlyphRenderer.cs @@ -144,7 +144,7 @@ protected override void BeginGlyph(in FontRectangle bounds, in GlyphRendererPara /// public void SetColor(GlyphColor color) - => this.currentColor = new Color(new Rgba32(color.Red, color.Green, color.Blue, color.Alpha)); + => this.currentColor = Color.FromPixel(new Rgba32(color.Red, color.Green, color.Blue, color.Alpha)); public override TextDecorations EnabledDecorations() { diff --git a/src/ImageSharp.Drawing/Processing/RecolorBrush.cs b/src/ImageSharp.Drawing/Processing/RecolorBrush.cs index 797e88d6..677c0019 100644 --- a/src/ImageSharp.Drawing/Processing/RecolorBrush.cs +++ b/src/ImageSharp.Drawing/Processing/RecolorBrush.cs @@ -104,10 +104,8 @@ public RecolorBrushApplicator( this.targetColorPixel = targetColor; // Lets hack a min max extremes for a color space by letting the IPackedPixel clamp our values to something in the correct spaces :) - var maxColor = default(TPixel); - maxColor.FromVector4(new Vector4(float.MaxValue)); - var minColor = default(TPixel); - minColor.FromVector4(new Vector4(float.MinValue)); + TPixel maxColor = TPixel.FromVector4(new Vector4(float.MaxValue)); + TPixel minColor = TPixel.FromVector4(new Vector4(float.MinValue)); this.threshold = Vector4.DistanceSquared(maxColor.ToVector4(), minColor.ToVector4()) * threshold; this.blenderBuffers = new ThreadLocalBlenderBuffers(configuration.MemoryAllocator, source.Width); } diff --git a/src/ImageSharp.Drawing/Shapes/Rasterization/ScanEdgeCollection.Build.cs b/src/ImageSharp.Drawing/Shapes/Rasterization/ScanEdgeCollection.Build.cs index a9acab03..bb56e870 100644 --- a/src/ImageSharp.Drawing/Shapes/Rasterization/ScanEdgeCollection.Build.cs +++ b/src/ImageSharp.Drawing/Shapes/Rasterization/ScanEdgeCollection.Build.cs @@ -208,10 +208,13 @@ static void RoundY(ReadOnlySpan vertices, Span destination, float [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector128 AdvSimdShuffle(Vector128 a, Vector128 b, byte control) { + // TODO: Review the codegen here. Might be better just looping. +#pragma warning disable CA1857 // A constant is expected for the parameter Vector128 result = Vector128.Create(AdvSimd.Extract(a, (byte)(control & 0x3))); result = AdvSimd.Insert(result, 1, AdvSimd.Extract(a, (byte)((control >> 2) & 0x3))); result = AdvSimd.Insert(result, 2, AdvSimd.Extract(b, (byte)((control >> 4) & 0x3))); result = AdvSimd.Insert(result, 3, AdvSimd.Extract(b, (byte)((control >> 6) & 0x3))); +#pragma warning restore CA1857 // A constant is expected for the parameter return result; } diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets index b0dc7c7b..e77ce0d4 100644 --- a/tests/Directory.Build.targets +++ b/tests/Directory.Build.targets @@ -19,14 +19,18 @@ - - - - + + + + + - + - + diff --git a/tests/ImageSharp.Drawing.Benchmarks/ImageSharp.Drawing.Benchmarks.csproj b/tests/ImageSharp.Drawing.Benchmarks/ImageSharp.Drawing.Benchmarks.csproj index daef9a87..0179f706 100644 --- a/tests/ImageSharp.Drawing.Benchmarks/ImageSharp.Drawing.Benchmarks.csproj +++ b/tests/ImageSharp.Drawing.Benchmarks/ImageSharp.Drawing.Benchmarks.csproj @@ -8,15 +8,21 @@ false + + + + CA1822 + + - net7.0;net6.0 + net8.0;net9.0 - net6.0 + net8.0 diff --git a/tests/ImageSharp.Drawing.Tests/ConfigurationTests.cs b/tests/ImageSharp.Drawing.Tests/ConfigurationTests.cs index d3fd08ca..85f1efd5 100644 --- a/tests/ImageSharp.Drawing.Tests/ConfigurationTests.cs +++ b/tests/ImageSharp.Drawing.Tests/ConfigurationTests.cs @@ -18,7 +18,7 @@ public class ConfigurationTests public Configuration DefaultConfiguration { get; } - private readonly int expectedDefaultConfigurationCount = 9; + private readonly int expectedDefaultConfigurationCount = 11; public ConfigurationTests() { diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/DrawBezierTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/DrawBezierTests.cs index 9ebdf256..daf6781c 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/DrawBezierTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/DrawBezierTests.cs @@ -33,9 +33,7 @@ public void DrawBeziers(TestImageProvider provider, string color new Vector2(300, 400) }; - Rgba32 rgba = TestUtils.GetColorByName(colorName); - rgba.A = alpha; - Color color = rgba; + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha / 255F); FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/DrawComplexPolygonTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/DrawComplexPolygonTests.cs index eb658a68..8197b9ed 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/DrawComplexPolygonTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/DrawComplexPolygonTests.cs @@ -30,14 +30,12 @@ public void DrawComplexPolygon(TestImageProvider provider, bool IPath clipped = simplePath.Clip(hole1); - Rgba32 colorRgba = Color.White; + Color color = Color.White; if (transparent) { - colorRgba.A = 150; + color = color.WithAlpha(150 / 255F); } - Color color = colorRgba; - string testDetails = string.Empty; if (overlap) { diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/DrawPathTests.cs index bbd196d7..a2303ad8 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/DrawPathTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/DrawPathTests.cs @@ -41,9 +41,7 @@ public void DrawPath(TestImageProvider provider, string colorNam Path path = new(linearSegment, bezierSegment, ellipticArcSegment1, ellipticArcSegment2); - Rgba32 rgba = TestUtils.GetColorByName(colorName); - rgba.A = alpha; - Color color = rgba; + Color color = TestUtils.GetColorByName(colorName).WithAlpha(alpha / 255F); FormattableString testDetails = $"{colorName}_A{alpha}_T{thickness}"; diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/DrawingRobustnessTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/DrawingRobustnessTests.cs index fbc04393..1295d6f3 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/DrawingRobustnessTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/DrawingRobustnessTests.cs @@ -130,7 +130,7 @@ private Image FillGeoJsonPolygons(TestImageProvider provider, st { rnd.NextBytes(rgb); - var color = Color.FromRgb(rgb[0], rgb[1], rgb[2]); + var color = Color.FromPixel(new(rgb[0], rgb[1], rgb[2])); image.Mutate(c => c.FillPolygon(options, color, loop)); } diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/FillComplexPolygonTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/FillComplexPolygonTests.cs index 9128d0c8..44b02a63 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/FillComplexPolygonTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/FillComplexPolygonTests.cs @@ -29,14 +29,12 @@ public void ComplexPolygon_SolidFill(TestImageProvider provider, IPath clipped = simplePath.Clip(hole1); - Rgba32 colorRgba = Color.HotPink; + Color color = Color.HotPink; if (transparent) { - colorRgba.A = 150; + color = color.WithAlpha(150 / 255F); } - Color color = colorRgba; - string testDetails = string.Empty; if (overlap) { diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/FillLinearGradientBrushTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/FillLinearGradientBrushTests.cs index 53374e39..ee4e6ad7 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/FillLinearGradientBrushTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/FillLinearGradientBrushTests.cs @@ -316,8 +316,7 @@ public void ArbitraryGradients( Color color = colors[stopColorCodes[i % colors.Length]]; float position = stopPositions[i]; colorStops[i] = new ColorStop(position, color); - Rgba32 rgba = color; - coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position); + coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", color.ToPixel().ToHex(), position); } FormattableString variant = $"({startX},{startY})_TO_({endX},{endY})__[{coloringVariant}]"; @@ -364,8 +363,7 @@ public void MultiplePointGradients( Color color = colors[stopColorCodes[i % colors.Length]]; float position = stopPositions[i]; colorStops[i] = new ColorStop(position, color); - Rgba32 rgba = color; - coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position); + coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", color.ToPixel().ToHex(), position); } FormattableString variant = $"({startX},{startY})_TO_({endX},{endY})__[{coloringVariant}]"; diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/FillOutsideBoundsTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/FillOutsideBoundsTests.cs index 40ea2b7e..f3109f66 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/FillOutsideBoundsTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/FillOutsideBoundsTests.cs @@ -20,7 +20,7 @@ public void DrawRectactangleOutsideBoundsDrawingArea(int xpos) int width = 100; int height = 100; - using (var image = new Image(width, height, Color.Red)) + using (var image = new Image(width, height, Color.Red.ToPixel())) { var rectangle = new Rectangle(xpos, 0, width, height); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/FillPathGradientBrushTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/FillPathGradientBrushTests.cs index fac1779b..172e00be 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/FillPathGradientBrushTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/FillPathGradientBrushTests.cs @@ -57,14 +57,11 @@ public void FillTriangleWithGreyscale(TestImageProvider provider { PointF[] points = { new PointF(10, 0), new PointF(20, 20), new PointF(0, 20) }; - var c1 = default(Rgba32); - var c2 = default(Rgba32); - var c3 = default(Rgba32); - new HalfSingle(-1).ToRgba32(ref c1); - new HalfSingle(0).ToRgba32(ref c2); - new HalfSingle(1).ToRgba32(ref c3); - - Color[] colors = { new Color(c1), new Color(c2), new Color(c3) }; + Color c1 = Color.FromPixel(new HalfSingle(-1)); + Color c2 = Color.FromPixel(new HalfSingle(0)); + Color c3 = Color.FromPixel(new HalfSingle(1)); + + Color[] colors = { c1, c2, c3 }; var brush = new PathGradientBrush(points, colors); diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/FillPatternBrushTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/FillPatternBrushTests.cs index 9391c945..2e8451e1 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/FillPatternBrushTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/FillPatternBrushTests.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Drawing.Tests.Drawing; public class FillPatternBrushTests { - private void Test(string name, Rgba32 background, Brush brush, Rgba32[,] expectedPattern) + private void Test(string name, Color background, Brush brush, Color[,] expectedPattern) { string path = TestEnvironment.CreateOutputDirectory("Drawing", "FillPatternBrushTests"); using (var image = new Image(20, 20)) @@ -23,7 +23,7 @@ private void Test(string name, Rgba32 background, Brush brush, Rgba32[,] expecte // lets pick random spots to start checking var r = new Random(); - var expectedPatternFast = new DenseMatrix(expectedPattern); + var expectedPatternFast = new DenseMatrix(expectedPattern); int xStride = expectedPatternFast.Columns; int yStride = expectedPatternFast.Rows; int offsetX = r.Next(image.Width / xStride) * xStride; @@ -34,7 +34,7 @@ private void Test(string name, Rgba32 background, Brush brush, Rgba32[,] expecte { int actualX = x + offsetX; int actualY = y + offsetY; - Rgba32 expected = expectedPatternFast[y, x]; // inverted pattern + Rgba32 expected = expectedPatternFast[y, x].ToPixel(); // inverted pattern Rgba32 actual = sourcePixels[actualX, actualY]; if (expected != actual) { @@ -51,7 +51,7 @@ private void Test(string name, Rgba32 background, Brush brush, Rgba32[,] expecte [Fact] public void ImageShouldBeFloodFilledWithPercent10() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.HotPink, Color.LimeGreen, Color.LimeGreen, Color.LimeGreen }, { Color.LimeGreen, Color.LimeGreen, Color.LimeGreen, Color.LimeGreen }, @@ -69,7 +69,7 @@ public void ImageShouldBeFloodFilledWithPercent10() [Fact] public void ImageShouldBeFloodFilledWithPercent10Transparent() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.HotPink, Color.Blue, Color.Blue, Color.Blue }, { Color.Blue, Color.Blue, Color.Blue, Color.Blue }, @@ -87,7 +87,7 @@ public void ImageShouldBeFloodFilledWithPercent10Transparent() [Fact] public void ImageShouldBeFloodFilledWithPercent20() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.HotPink, Color.LimeGreen, Color.LimeGreen, Color.LimeGreen }, { Color.LimeGreen, Color.LimeGreen, Color.HotPink, Color.LimeGreen }, @@ -105,7 +105,7 @@ public void ImageShouldBeFloodFilledWithPercent20() [Fact] public void ImageShouldBeFloodFilledWithPercent20_transparent() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.HotPink, Color.Blue, Color.Blue, Color.Blue }, { Color.Blue, Color.Blue, Color.HotPink, Color.Blue }, @@ -123,7 +123,7 @@ public void ImageShouldBeFloodFilledWithPercent20_transparent() [Fact] public void ImageShouldBeFloodFilledWithHorizontal() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.LimeGreen, Color.LimeGreen, Color.LimeGreen, Color.LimeGreen }, { Color.HotPink, Color.HotPink, Color.HotPink, Color.HotPink }, @@ -141,7 +141,7 @@ public void ImageShouldBeFloodFilledWithHorizontal() [Fact] public void ImageShouldBeFloodFilledWithHorizontal_transparent() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.Blue, Color.Blue, Color.Blue, Color.Blue }, { Color.HotPink, Color.HotPink, Color.HotPink, Color.HotPink }, @@ -159,7 +159,7 @@ public void ImageShouldBeFloodFilledWithHorizontal_transparent() [Fact] public void ImageShouldBeFloodFilledWithMin() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.LimeGreen, Color.LimeGreen, Color.LimeGreen, Color.LimeGreen }, { Color.LimeGreen, Color.LimeGreen, Color.LimeGreen, Color.LimeGreen }, @@ -177,7 +177,7 @@ public void ImageShouldBeFloodFilledWithMin() [Fact] public void ImageShouldBeFloodFilledWithMin_transparent() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.Blue, Color.Blue, Color.Blue, Color.Blue }, { Color.Blue, Color.Blue, Color.Blue, Color.Blue }, @@ -195,7 +195,7 @@ public void ImageShouldBeFloodFilledWithMin_transparent() [Fact] public void ImageShouldBeFloodFilledWithVertical() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.LimeGreen, Color.HotPink, Color.LimeGreen, Color.LimeGreen }, { Color.LimeGreen, Color.HotPink, Color.LimeGreen, Color.LimeGreen }, @@ -213,7 +213,7 @@ public void ImageShouldBeFloodFilledWithVertical() [Fact] public void ImageShouldBeFloodFilledWithVertical_transparent() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.Blue, Color.HotPink, Color.Blue, Color.Blue }, { Color.Blue, Color.HotPink, Color.Blue, Color.Blue }, @@ -231,7 +231,7 @@ public void ImageShouldBeFloodFilledWithVertical_transparent() [Fact] public void ImageShouldBeFloodFilledWithForwardDiagonal() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.LimeGreen, Color.LimeGreen, Color.LimeGreen, Color.HotPink }, { Color.LimeGreen, Color.LimeGreen, Color.HotPink, Color.LimeGreen }, @@ -249,7 +249,7 @@ public void ImageShouldBeFloodFilledWithForwardDiagonal() [Fact] public void ImageShouldBeFloodFilledWithForwardDiagonal_transparent() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.Blue, Color.Blue, Color.Blue, Color.HotPink }, { Color.Blue, Color.Blue, Color.HotPink, Color.Blue }, @@ -267,7 +267,7 @@ public void ImageShouldBeFloodFilledWithForwardDiagonal_transparent() [Fact] public void ImageShouldBeFloodFilledWithBackwardDiagonal() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.HotPink, Color.LimeGreen, Color.LimeGreen, Color.LimeGreen }, { Color.LimeGreen, Color.HotPink, Color.LimeGreen, Color.LimeGreen }, @@ -285,7 +285,7 @@ public void ImageShouldBeFloodFilledWithBackwardDiagonal() [Fact] public void ImageShouldBeFloodFilledWithBackwardDiagonal_transparent() { - var expectedPattern = new Rgba32[,] + var expectedPattern = new Color[,] { { Color.HotPink, Color.Blue, Color.Blue, Color.Blue }, { Color.Blue, Color.HotPink, Color.Blue, Color.Blue }, diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/SolidBezierTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/SolidBezierTests.cs index ea3fb983..dd6a7b0b 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/SolidBezierTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/SolidBezierTests.cs @@ -49,8 +49,7 @@ public void OverlayByFilledPolygonOpacity(TestImageProvider prov new Vector2(300, 400) }; - Rgba32 color = Color.HotPink; - color.A = 150; + Color color = Color.HotPink.WithAlpha(150 / 255F); using (var image = provider.GetImage() as Image) { diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawTextOnImageTests.cs index b5d26e27..5d441cb4 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -129,7 +129,7 @@ public void DoesntThrowExceptionWhenOverlappingRightEdge_Issue688_2(Test { Font font = CreateFont(TestFonts.OpenSans, 39); string text = new('a', 10000); - Rgba32 color = Color.Black; + Color color = Color.Black; var point = new PointF(100, 100); using Image img = provider.GetImage(); @@ -857,6 +857,7 @@ public void CanDrawTextVertical(TestImageProvider provider) FallbackFontFamilies = new[] { fallback.Family }, WrappingLength = 400, LayoutMode = LayoutMode.VerticalLeftRight, + LineSpacing = 1.4F, TextRuns = new[] { new RichTextRun() { Start = 0, End = text.GetGraphemeCount(), TextDecorations = TextDecorations.Underline | TextDecorations.Strikeout | TextDecorations.Overline } } }; @@ -865,6 +866,28 @@ public void CanDrawTextVertical(TestImageProvider provider) comparer: ImageComparer.TolerantPercentage(0.002f)); } + [Theory] + [WithBlankImage(48, 935, PixelTypes.Rgba32)] + public void CanDrawTextVertical2(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + if (SystemFonts.TryGet("Yu Gothic", out FontFamily fontFamily)) + { + Font font = fontFamily.CreateFont(30F); + const string text = "あいうえお、「こんにちはー」。もしもし。ABCDEFG 日本語"; + RichTextOptions textOptions = new(font) + { + LayoutMode = LayoutMode.VerticalLeftRight, + LineSpacing = 1.4F, + // TextRuns = new[] { new RichTextRun() { Start = 0, End = text.GetGraphemeCount(), TextDecorations = TextDecorations.Underline | TextDecorations.Strikeout | TextDecorations.Overline } } + }; + + provider.RunValidatingProcessorTest( + c => c.Fill(Color.White).DrawText(textOptions, text, Brushes.Solid(Color.Black)), + comparer: ImageComparer.TolerantPercentage(0.002f)); + } + } + [Theory] [WithBlankImage(500, 400, PixelTypes.Rgba32)] public void CanDrawTextVerticalMixed(TestImageProvider provider) @@ -879,6 +902,7 @@ public void CanDrawTextVerticalMixed(TestImageProvider provider) FallbackFontFamilies = new[] { fallback.Family }, WrappingLength = 400, LayoutMode = LayoutMode.VerticalMixedLeftRight, + LineSpacing = 1.4F, TextRuns = new[] { new RichTextRun() { Start = 0, End = text.GetGraphemeCount(), TextDecorations = TextDecorations.Underline | TextDecorations.Strikeout | TextDecorations.Overline } } }; @@ -887,6 +911,28 @@ public void CanDrawTextVerticalMixed(TestImageProvider provider) comparer: ImageComparer.TolerantPercentage(0.002f)); } + [Theory] + [WithBlankImage(48, 839, PixelTypes.Rgba32)] + public void CanDrawTextVerticalMixed2(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + if (SystemFonts.TryGet("Yu Gothic", out FontFamily fontFamily)) + { + Font font = fontFamily.CreateFont(30F); + const string text = "あいうえお、「こんにちはー」。もしもし。ABCDEFGg 日本語"; + RichTextOptions textOptions = new(font) + { + LayoutMode = LayoutMode.VerticalMixedLeftRight, + LineSpacing = 1.4F, + TextRuns = new[] { new RichTextRun() { Start = 0, End = text.GetGraphemeCount(), TextDecorations = TextDecorations.Underline | TextDecorations.Strikeout | TextDecorations.Overline } } + }; + + provider.RunValidatingProcessorTest( + c => c.Fill(Color.White).DrawText(textOptions, text, Brushes.Solid(Color.Black)), + comparer: ImageComparer.TolerantPercentage(0.002f)); + } + } + [Theory] [WithBlankImage(200, 200, PixelTypes.Rgba32)] public void CanRenderTextOutOfBoundsIssue301(TestImageProvider provider) diff --git a/tests/ImageSharp.Drawing.Tests/ImageSharp.Drawing.Tests.csproj b/tests/ImageSharp.Drawing.Tests/ImageSharp.Drawing.Tests.csproj index 5767ff84..a08486cb 100644 --- a/tests/ImageSharp.Drawing.Tests/ImageSharp.Drawing.Tests.csproj +++ b/tests/ImageSharp.Drawing.Tests/ImageSharp.Drawing.Tests.csproj @@ -13,12 +13,12 @@ - net7.0;net6.0 + net8.0;net9.0 - net6.0 + net8.0 @@ -28,6 +28,7 @@ + diff --git a/tests/ImageSharp.Drawing.Tests/Issues/Issue_241.cs b/tests/ImageSharp.Drawing.Tests/Issues/Issue_241.cs index 96634e5e..1d208a0d 100644 --- a/tests/ImageSharp.Drawing.Tests/Issues/Issue_241.cs +++ b/tests/ImageSharp.Drawing.Tests/Issues/Issue_241.cs @@ -26,7 +26,7 @@ public void DoesNotThrowArgumentOutOfRangeException() }; const string content = "TEST"; - using Image image = new Image(512, 256, Color.Black); + using Image image = new Image(512, 256, Color.Black.ToPixel()); image.Mutate(x => x.DrawText(opt, content, Brushes.Horizontal(Color.Orange))); } } diff --git a/tests/ImageSharp.Drawing.Tests/Issues/Issue_270.cs b/tests/ImageSharp.Drawing.Tests/Issues/Issue_270.cs index ace95bbc..43ad525b 100644 --- a/tests/ImageSharp.Drawing.Tests/Issues/Issue_270.cs +++ b/tests/ImageSharp.Drawing.Tests/Issues/Issue_270.cs @@ -29,8 +29,8 @@ public void DoesNotThrowArgumentOutOfRangeException() Font font = SystemFonts.CreateFont("Arial", minimumCrashingFontSize); Pen pen = Pens.Solid(Color.Black, 1); - using Image targetImage = new(targetImageWidth, targetImageHeight, Color.Wheat); - using Image imageBrushImage = new(sourceImageWidth, sourceImageHeight, Color.Black); + using Image targetImage = new(targetImageWidth, targetImageHeight, Color.Wheat.ToPixel()); + using Image imageBrushImage = new(sourceImageWidth, sourceImageHeight, Color.Black.ToPixel()); ImageBrush imageBrush = new(imageBrushImage); targetImage.Mutate(x => x.DrawText(CreateTextOptions(font, targetImageWidth), text, imageBrush, pen)); diff --git a/tests/ImageSharp.Drawing.Tests/Issues/Issue_28_108.cs b/tests/ImageSharp.Drawing.Tests/Issues/Issue_28_108.cs index 5dd10f95..6a5c767c 100644 --- a/tests/ImageSharp.Drawing.Tests/Issues/Issue_28_108.cs +++ b/tests/ImageSharp.Drawing.Tests/Issues/Issue_28_108.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Drawing.Tests.Issues; public class Issue_28_108 { - private Rgba32 red = Color.Red.ToRgba32(); + private Rgba32 red = Color.Red.ToPixel(); [Theory] [InlineData(1F)] @@ -18,11 +18,11 @@ public class Issue_28_108 [InlineData(3F)] public void DrawingLineAtTopShouldDisplay(float stroke) { - using var image = new Image(Configuration.Default, 100, 100, Color.Black); + using var image = new Image(Configuration.Default, 100, 100, Color.Black.ToPixel()); image.Mutate(x => x .SetGraphicsOptions(g => g.Antialias = false) .DrawLine( - this.red, + Color.Red, stroke, new PointF(0, 0), new PointF(100, 0))); @@ -38,11 +38,11 @@ public void DrawingLineAtTopShouldDisplay(float stroke) [InlineData(3F)] public void DrawingLineAtBottomShouldDisplay(float stroke) { - using var image = new Image(Configuration.Default, 100, 100, Color.Black); + using var image = new Image(Configuration.Default, 100, 100, Color.Black.ToPixel()); image.Mutate(x => x .SetGraphicsOptions(g => g.Antialias = false) .DrawLine( - this.red, + Color.Red, stroke, new PointF(0, 99), new PointF(100, 99))); @@ -58,11 +58,11 @@ public void DrawingLineAtBottomShouldDisplay(float stroke) [InlineData(3F)] public void DrawingLineAtLeftShouldDisplay(float stroke) { - using var image = new Image(Configuration.Default, 100, 100, Color.Black); + using var image = new Image(Configuration.Default, 100, 100, Color.Black.ToPixel()); image.Mutate(x => x .SetGraphicsOptions(g => g.Antialias = false) .DrawLine( - this.red, + Color.Red, stroke, new PointF(0, 0), new PointF(0, 99))); @@ -78,11 +78,11 @@ public void DrawingLineAtLeftShouldDisplay(float stroke) [InlineData(3F)] public void DrawingLineAtRightShouldDisplay(float stroke) { - using var image = new Image(Configuration.Default, 100, 100, Color.Black); + using var image = new Image(Configuration.Default, 100, 100, Color.Black.ToPixel()); image.Mutate(x => x .SetGraphicsOptions(g => g.Antialias = false) .DrawLine( - this.red, + Color.Red, stroke, new PointF(99, 0), new PointF(99, 99))); diff --git a/tests/ImageSharp.Drawing.Tests/Issues/Issues_55_59.cs b/tests/ImageSharp.Drawing.Tests/Issues/Issues_55_59.cs index 07698129..4101cfda 100644 --- a/tests/ImageSharp.Drawing.Tests/Issues/Issues_55_59.cs +++ b/tests/ImageSharp.Drawing.Tests/Issues/Issues_55_59.cs @@ -24,7 +24,7 @@ public void SimplifyOutOfRangeExceptionDrawLines() }; using var image = new Image(100, 100); - image.Mutate(imageContext => imageContext.DrawLine(new Rgba32(255, 0, 0), 1, line)); + image.Mutate(imageContext => imageContext.DrawLine(Color.FromPixel(new Rgba32(255, 0, 0)), 1, line)); } [Fact] @@ -37,6 +37,6 @@ public void SimplifyOutOfRangeExceptionDraw() new LinearLineSegment(new PointF(592.916f, 1155.754f), new PointF(592.0153f, 1156.238f))); using var image = new Image(2000, 2000); - image.Mutate(imageContext => imageContext.Draw(new Rgba32(255, 0, 0), 1, path)); + image.Mutate(imageContext => imageContext.Draw(Color.FromPixel(new Rgba32(255, 0, 0)), 1, path)); } } diff --git a/tests/ImageSharp.Drawing.Tests/TestFormat.cs b/tests/ImageSharp.Drawing.Tests/TestFormat.cs index 648b0507..2db0b097 100644 --- a/tests/ImageSharp.Drawing.Tests/TestFormat.cs +++ b/tests/ImageSharp.Drawing.Tests/TestFormat.cs @@ -202,11 +202,12 @@ public class TestDecoder : SpecializedImageDecoder protected override ImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { - Image image = - this.Decode(this.CreateDefaultSpecializedOptions(options), stream, cancellationToken); - ImageFrameCollection m = image.Frames; - - return new(image.PixelType, image.Size, image.Metadata, new List(image.Frames.Select(x => x.Metadata))); + using Image image = this.Decode(this.CreateDefaultSpecializedOptions(options), stream, cancellationToken); + ImageMetadata metadata = image.Metadata; + return new(image.Size, metadata, new List(image.Frames.Select(x => x.Metadata))) + { + PixelType = metadata.GetDecodedPixelTypeInfo() + }; } protected override TestDecoderOptions CreateDefaultSpecializedOptions(DecoderOptions options) @@ -263,75 +264,49 @@ public Task EncodeAsync(Image image, Stream stream, Cancellation public struct TestPixelForAgnosticDecode : IPixel { - public PixelOperations CreatePixelOperations() => new(); + public readonly Rgba32 ToRgba32() => default; - public void FromScaledVector4(Vector4 vector) - { - } + public readonly Vector4 ToScaledVector4() => default; - public Vector4 ToScaledVector4() => default; + public readonly Vector4 ToVector4() => default; - public void FromVector4(Vector4 vector) - { - } + public static PixelTypeInfo GetPixelTypeInfo() + => PixelTypeInfo.Create( + PixelComponentInfo.Create(2, 8, 8), + PixelColorType.Red | PixelColorType.Green, + PixelAlphaRepresentation.None); - public Vector4 ToVector4() => default; + public static PixelOperations CreatePixelOperations() => new(); - public void FromArgb32(Argb32 source) - { - } + public static TestPixelForAgnosticDecode FromScaledVector4(Vector4 vector) => default; - public void FromBgra5551(Bgra5551 source) - { - } + public static TestPixelForAgnosticDecode FromVector4(Vector4 vector) => default; - public void FromBgr24(Bgr24 source) - { - } + public static TestPixelForAgnosticDecode FromAbgr32(Abgr32 source) => default; - public void FromBgra32(Bgra32 source) - { - } + public static TestPixelForAgnosticDecode FromArgb32(Argb32 source) => default; - public void FromAbgr32(Abgr32 source) - { - } + public static TestPixelForAgnosticDecode FromBgra5551(Bgra5551 source) => default; - public void FromL8(L8 source) - { - } + public static TestPixelForAgnosticDecode FromBgr24(Bgr24 source) => default; - public void FromL16(L16 source) - { - } + public static TestPixelForAgnosticDecode FromBgra32(Bgra32 source) => default; - public void FromLa16(La16 source) - { - } + public static TestPixelForAgnosticDecode FromL8(L8 source) => default; - public void FromLa32(La32 source) - { - } + public static TestPixelForAgnosticDecode FromL16(L16 source) => default; - public void FromRgb24(Rgb24 source) - { - } + public static TestPixelForAgnosticDecode FromLa16(La16 source) => default; - public void FromRgba32(Rgba32 source) - { - } + public static TestPixelForAgnosticDecode FromLa32(La32 source) => default; - public void ToRgba32(ref Rgba32 dest) - { - } + public static TestPixelForAgnosticDecode FromRgb24(Rgb24 source) => default; - public void FromRgb48(Rgb48 source) - { - } + public static TestPixelForAgnosticDecode FromRgba32(Rgba32 source) => default; - public void FromRgba64(Rgba64 source) - { - } + public static TestPixelForAgnosticDecode FromRgb48(Rgb48 source) => default; + + public static TestPixelForAgnosticDecode FromRgba64(Rgba64 source) => default; public bool Equals(TestPixelForAgnosticDecode other) => false; } diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs index 4b4293f5..0aad4c3f 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -16,7 +15,7 @@ public override ImageSimilarityReport CompareImagesOrFrames expected, ImageFrame actual) { - if (expected.Size() != actual.Size()) + if (expected.Size != actual.Size) { throw new InvalidOperationException("Calling ImageComparer is invalid when dimensions mismatch!"); } diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs index 55690bde..eeb257fa 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs @@ -56,7 +56,7 @@ public TolerantImageComparer(float imageThreshold, int perPixelManhattanThreshol public override ImageSimilarityReport CompareImagesOrFrames(int index, ImageFrame expected, ImageFrame actual) { - if (expected.Size() != actual.Size()) + if (expected.Size != actual.Size) { throw new InvalidOperationException("Calling ImageComparer is invalid when dimensions mismatch!"); } diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs index a596a773..87ea2925 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/BasicTestPatternProvider.cs @@ -78,10 +78,6 @@ public override TPixel GetExpectedBasicTestPatternPixelAt(int x, int y) } private static TPixel GetBottomRightColor() - { - TPixel bottomRightColor = default; - bottomRightColor.FromVector4(new Vector4(1f, 0f, 1f, 0.5f)); - return bottomRightColor; - } + => TPixel.FromVector4(new Vector4(1f, 0f, 1f, 0.5f)); } } diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/SolidProvider.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/SolidProvider.cs index a3aa0ee6..0ff20b6a 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/SolidProvider.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/SolidProvider.cs @@ -51,7 +51,7 @@ public override string SourceFileOrDescription public override Image GetImage() { Image image = base.GetImage(); - Color color = new Rgba32(this.r, this.g, this.b, this.a); + Color color = Color.FromPixel(new Rgba32(this.r, this.g, this.b, this.a)); image.GetRootFramePixelBuffer().FastMemoryGroup.Fill(color.ToPixel()); return image; diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs index 0f17058c..5ca033bf 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs @@ -157,13 +157,11 @@ private static void TransparentGradients(Buffer2D pixels) var green = Color.Green.ToPixel().ToVector4(); // use real color so we can see how it translates in the test pattern var blue = Color.Blue.ToPixel().ToVector4(); // use real color so we can see how it translates in the test pattern - var c = default(TPixel); - for (int x = left; x < right; x++) { blue.W = red.W = green.W = (float)x / (float)right; - c.FromVector4(red); + TPixel c = TPixel.FromVector4(red); int topBand = top; for (int y = topBand; y < top + height; y++) { @@ -171,14 +169,14 @@ private static void TransparentGradients(Buffer2D pixels) } topBand = topBand + height; - c.FromVector4(green); + c = TPixel.FromVector4(green); for (int y = topBand; y < topBand + height; y++) { pixels[x, y] = c; } topBand = topBand + height; - c.FromVector4(blue); + c = TPixel.FromVector4(blue); for (int y = topBand; y < bottom; y++) { pixels[x, y] = c; @@ -199,7 +197,6 @@ private static void Rainbow(Buffer2D pixels) int pixelCount = left * top; uint stepsPerPixel = (uint)(uint.MaxValue / pixelCount); - TPixel c = default; var t = new Rgba32(0); for (int x = left; x < right; x++) @@ -210,8 +207,7 @@ private static void Rainbow(Buffer2D pixels) var v = t.ToVector4(); // v.W = (x - left) / (float)left; - c.FromVector4(v); - pixels[x, y] = c; + pixels[x, y] = TPixel.FromVector4(v); } } } diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImagingTestCaseUtility.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImagingTestCaseUtility.cs index 66ac5949..f3c727ea 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/ImagingTestCaseUtility.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/ImagingTestCaseUtility.cs @@ -288,8 +288,7 @@ public static void ModifyPixel(ImageFrame img, int x, int y, byt where TPixel : unmanaged, IPixel { TPixel pixel = img[x, y]; - Rgba64 rgbaPixel = default; - rgbaPixel.FromScaledVector4(pixel.ToScaledVector4()); + Rgba64 rgbaPixel = Rgba64.FromScaledVector4(pixel.ToScaledVector4()); ushort change = (ushort)Math.Round((perChannelChange / 255F) * 65535F); if (rgbaPixel.R + perChannelChange <= 255) @@ -328,7 +327,6 @@ public static void ModifyPixel(ImageFrame img, int x, int y, byt rgbaPixel.A -= perChannelChange; } - pixel.FromRgba64(rgbaPixel); - img[x, y] = pixel; + img[x, y] = TPixel.FromRgba64(rgbaPixel); } } diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index 510dcefe..7d3d926b 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -5,6 +5,11 @@ using ImageMagick; using ImageMagick.Formats; using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Formats.Tiff; +using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; @@ -13,36 +18,56 @@ namespace SixLabors.ImageSharp.Drawing.Tests.TestUtilities.ReferenceCodecs; public class MagickReferenceDecoder : ImageDecoder { + private readonly IImageFormat imageFormat; private readonly bool validate; - public MagickReferenceDecoder() - : this(true) + public MagickReferenceDecoder(IImageFormat imageFormat) + : this(imageFormat, true) { } - public MagickReferenceDecoder(bool validate) => this.validate = validate; + public MagickReferenceDecoder(IImageFormat imageFormat, bool validate) + { + this.imageFormat = imageFormat; + this.validate = validate; + } + + public static MagickReferenceDecoder Png { get; } = new MagickReferenceDecoder(PngFormat.Instance); + + public static MagickReferenceDecoder Bmp { get; } = new MagickReferenceDecoder(BmpFormat.Instance); + + public static MagickReferenceDecoder Jpeg { get; } = new MagickReferenceDecoder(JpegFormat.Instance); + + public static MagickReferenceDecoder Tiff { get; } = new MagickReferenceDecoder(TiffFormat.Instance); - public static MagickReferenceDecoder Instance { get; } = new(); + public static MagickReferenceDecoder WebP { get; } = new MagickReferenceDecoder(WebpFormat.Instance); protected override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { + ImageMetadata metadata = new(); + Configuration configuration = options.Configuration; BmpReadDefines bmpReadDefines = new() { IgnoreFileSize = !this.validate }; + PngReadDefines pngReadDefines = new() + { + IgnoreCrc = !this.validate + }; MagickReadSettings settings = new() { FrameCount = (int)options.MaxFrames }; settings.SetDefines(bmpReadDefines); + settings.SetDefines(pngReadDefines); using MagickImageCollection magickImageCollection = new(stream, settings); - List> framesList = new(); + List> framesList = []; foreach (IMagickImage magicFrame in magickImageCollection) { - ImageFrame frame = new(configuration, magicFrame.Width, magicFrame.Height); + ImageFrame frame = new(configuration, (int)magicFrame.Width, (int)magicFrame.Height); framesList.Add(frame); MemoryGroup framePixels = frame.PixelBuffer.FastMemoryGroup; @@ -56,6 +81,11 @@ protected override Image Decode(DecoderOptions options, Stream s } else if (magicFrame.Depth is 16 or 14) { + if (this.imageFormat is PngFormat png) + { + metadata.GetPngMetadata().BitDepth = PngBitDepth.Bit16; + } + ushort[] data = pixels.ToShortArray(PixelMapping.RGBA); Span bytes = MemoryMarshal.Cast(data.AsSpan()); FromRgba64Bytes(configuration, bytes, framePixels); @@ -66,7 +96,7 @@ protected override Image Decode(DecoderOptions options, Stream s } } - return new Image(configuration, new ImageMetadata(), framesList); + return ReferenceCodecUtilities.EnsureDecodedMetadata(new(configuration, metadata, framesList), this.imageFormat); } protected override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) @@ -75,7 +105,11 @@ protected override Image Decode(DecoderOptions options, Stream stream, Cancellat protected override ImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { using Image image = this.Decode(options, stream, cancellationToken); - return new(image.PixelType, image.Size, image.Metadata, new List(image.Frames.Select(x => x.Metadata))); + ImageMetadata metadata = image.Metadata; + return new(image.Size, metadata, new List(image.Frames.Select(x => x.Metadata))) + { + PixelType = metadata.GetDecodedPixelTypeInfo() + }; } private static void FromRgba32Bytes(Configuration configuration, Span rgbaBytes, IMemoryGroup destinationGroup) diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/ReferenceCodecUtilities.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/ReferenceCodecUtilities.cs new file mode 100644 index 00000000..a4df368b --- /dev/null +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/ReferenceCodecUtilities.cs @@ -0,0 +1,94 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Gif; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Pbm; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Formats.Qoi; +using SixLabors.ImageSharp.Formats.Tga; +using SixLabors.ImageSharp.Formats.Tiff; +using SixLabors.ImageSharp.Formats.Webp; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Drawing.Tests.TestUtilities.ReferenceCodecs; + +internal static class ReferenceCodecUtilities +{ + /// + /// Ensures that the metadata is properly initialized for reference and test encoders which cannot initialize + /// metadata in the same manner as our built in decoders. + /// + /// The type of pixel format. + /// The decoded image. + /// The image format + /// The format is unknown. + public static Image EnsureDecodedMetadata(Image image, IImageFormat format) + where TPixel : unmanaged, IPixel + { + if (image.Metadata.DecodedImageFormat is null) + { + image.Metadata.DecodedImageFormat = format; + } + + foreach (ImageFrame frame in image.Frames) + { + frame.Metadata.DecodedImageFormat = format; + } + + switch (format) + { + case BmpFormat: + image.Metadata.GetBmpMetadata(); + break; + case GifFormat: + image.Metadata.GetGifMetadata(); + foreach (ImageFrame frame in image.Frames) + { + frame.Metadata.GetGifMetadata(); + } + + break; + case JpegFormat: + image.Metadata.GetJpegMetadata(); + break; + case PbmFormat: + image.Metadata.GetPbmMetadata(); + break; + case PngFormat: + image.Metadata.GetPngMetadata(); + foreach (ImageFrame frame in image.Frames) + { + frame.Metadata.GetPngMetadata(); + } + + break; + case QoiFormat: + image.Metadata.GetQoiMetadata(); + break; + case TgaFormat: + image.Metadata.GetTgaMetadata(); + break; + case TiffFormat: + image.Metadata.GetTiffMetadata(); + foreach (ImageFrame frame in image.Frames) + { + frame.Metadata.GetTiffMetadata(); + } + + break; + case WebpFormat: + image.Metadata.GetWebpMetadata(); + foreach (ImageFrame frame in image.Frames) + { + frame.Metadata.GetWebpMetadata(); + } + + break; + } + + return image; + } +} diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs index cd301384..bcb9fc4d 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/ReferenceCodecs/SystemDrawingReferenceDecoder.cs @@ -1,23 +1,35 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +#pragma warning disable CA1416 // Validate platform compatibility using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Bmp; +using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SDBitmap = System.Drawing.Bitmap; -using SDImage = System.Drawing.Image; namespace SixLabors.ImageSharp.Drawing.Tests.TestUtilities.ReferenceCodecs; public class SystemDrawingReferenceDecoder : ImageDecoder { - public static SystemDrawingReferenceDecoder Instance { get; } = new SystemDrawingReferenceDecoder(); + private readonly IImageFormat imageFormat; + + public SystemDrawingReferenceDecoder(IImageFormat imageFormat) + => this.imageFormat = imageFormat; + + public static SystemDrawingReferenceDecoder Png { get; } = new SystemDrawingReferenceDecoder(PngFormat.Instance); + + public static SystemDrawingReferenceDecoder Bmp { get; } = new SystemDrawingReferenceDecoder(BmpFormat.Instance); protected override ImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { - using SDBitmap sourceBitmap = new(stream); - PixelTypeInfo pixelType = new(SDImage.GetPixelFormatSize(sourceBitmap.PixelFormat)); - return new ImageInfo(pixelType, new(sourceBitmap.Width, sourceBitmap.Height), new ImageMetadata()); + using Image image = this.Decode(options, stream, cancellationToken); + ImageMetadata metadata = image.Metadata; + return new(image.Size, metadata, new List(image.Frames.Select(x => x.Metadata))) + { + PixelType = metadata.GetDecodedPixelTypeInfo() + }; } protected override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) @@ -42,7 +54,9 @@ protected override Image Decode(DecoderOptions options, Stream s g.DrawImage(sourceBitmap, 0, 0, sourceBitmap.Width, sourceBitmap.Height); } - return SystemDrawingBridge.From32bppArgbSystemDrawingBitmap(convertedBitmap); + return ReferenceCodecUtilities.EnsureDecodedMetadata( + SystemDrawingBridge.From32bppArgbSystemDrawingBitmap(convertedBitmap), + this.imageFormat); } protected override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/TestEnvironment.Formats.cs index 72e02377..7651b544 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/TestEnvironment.Formats.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/TestEnvironment.Formats.cs @@ -64,13 +64,13 @@ private static Configuration CreateDefaultConfiguration() cfg.ConfigureCodecs( PngFormat.Instance, - MagickReferenceDecoder.Instance, + MagickReferenceDecoder.Png, pngEncoder, new PngImageFormatDetector()); cfg.ConfigureCodecs( BmpFormat.Instance, - IsWindows ? SystemDrawingReferenceDecoder.Instance : MagickReferenceDecoder.Instance, + IsWindows ? SystemDrawingReferenceDecoder.Bmp : MagickReferenceDecoder.Bmp, bmpEncoder, new BmpImageFormatDetector()); diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/TestImageExtensions.cs index 874a5f65..16c03c23 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/TestImageExtensions.cs @@ -701,7 +701,7 @@ internal static Image ToGrayscaleImage(this Buffer2D buffer, floa { float value = bufferSpan[i] * scale; var v = new Vector4(value, value, value, 1f); - pixels[i].FromVector4(v); + pixels[i] = Rgba32.FromVector4(v); } return image; diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/TestPixel.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/TestPixel.cs index dea98213..5336e37a 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/TestPixel.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/TestPixel.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Numerics; using SixLabors.ImageSharp.PixelFormats; using Xunit.Abstractions; @@ -29,16 +30,9 @@ public TestPixel(float red, float green, float blue, float alpha) public float Alpha { get; set; } - public static implicit operator TPixel(TestPixel d) => d?.AsPixel() ?? default; + public TPixel AsPixel() => TPixel.FromScaledVector4(new Vector4(this.Red, this.Green, this.Blue, this.Alpha)); - public TPixel AsPixel() - { - TPixel pix = default; - pix.FromVector4(new System.Numerics.Vector4(this.Red, this.Green, this.Blue, this.Alpha)); - return pix; - } - - internal Span AsSpan() => new Span(new[] { this.AsPixel() }); + internal Span AsSpan() => new([this.AsPixel()]); public void Deserialize(IXunitSerializationInfo info) { diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/TestUtils.cs index a7f1309c..5d572874 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/TestUtils.cs @@ -76,10 +76,9 @@ public static bool IsEquivalentTo(this Image a, Image b, } else { - Rgba32 rgba = default; - ca.ToRgba32(ref rgba); + Rgba32 rgba = ca.ToRgba32(); rgb1 = rgba.Rgb; - cb.ToRgba32(ref rgba); + rgba = cb.ToRgba32(); rgb2 = rgba.Rgb; if (!rgb1.Equals(rgb2)) diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 404cb5f7..ec000014 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -2,7 +2,6 @@ // Licensed under the Six Labors Split License. using System.Collections.Concurrent; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; @@ -309,7 +308,7 @@ public void Use_WithSolidFilledImagesAttribute(TestImageProvider { for (int x = 0; x < pixels.Width; x++) { - pixels[x, y].ToRgba32(ref rgba); + rgba = pixels[x, y].ToRgba32(); Assert.Equal(255, rgba.R); Assert.Equal(100, rgba.G); @@ -372,7 +371,11 @@ public static void DoTestThreadSafe(Action action) protected override ImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { using Image image = this.Decode(this.CreateDefaultSpecializedOptions(options), stream, cancellationToken); - return new(image.PixelType, image.Size, image.Metadata, new List(image.Frames.Select(x => x.Metadata))); + ImageMetadata metadata = image.Metadata; + return new(image.Size, metadata, new List(image.Frames.Select(x => x.Metadata))) + { + PixelType = metadata.GetDecodedPixelTypeInfo() + }; } protected override Image Decode(TestDecoderOptions options, Stream stream, CancellationToken cancellationToken) @@ -415,7 +418,11 @@ public static void DoTestThreadSafe(Action action) protected override ImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) { using Image image = this.Decode(this.CreateDefaultSpecializedOptions(options), stream, cancellationToken); - return new(image.PixelType, image.Size, image.Metadata, new List(image.Frames.Select(x => x.Metadata))); + ImageMetadata metadata = image.Metadata; + return new(image.Size, metadata, new List(image.Frames.Select(x => x.Metadata))) + { + PixelType = metadata.GetDecodedPixelTypeInfo() + }; } protected override Image Decode(TestDecoderWithParametersOptions options, Stream stream, CancellationToken cancellationToken) diff --git a/tests/ImageSharp.Drawing.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs b/tests/ImageSharp.Drawing.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs index 688436e9..41597be7 100644 --- a/tests/ImageSharp.Drawing.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs +++ b/tests/ImageSharp.Drawing.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs @@ -26,13 +26,9 @@ public static Image CreateTestImage() { for (int j = 0; j < 10; j++) { - var v = new Vector4(i, j, 0, 1); + Vector4 v = new(i, j, 0, 1); v /= 10; - - var color = default(TPixel); - color.FromVector4(v); - - pixels[i, j] = color; + pixels[i, j] = TPixel.FromVector4(v); } } From 5646c227ad6ca70b42b0b8a87b916c52399eb458 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 9 Jan 2025 10:31:34 +1000 Subject: [PATCH 2/4] Fix refs --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 8a881de8..8f4390cc 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -45,10 +45,8 @@ - - - + \ No newline at end of file From 7f34884411b90a672934d1917ccd2ed12477d911 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 9 Jan 2025 10:37:44 +1000 Subject: [PATCH 3/4] Update tests --- .../Drawing/Text/DrawTextOnImageTests.cs | 6 +++--- .../CanDrawTextVertical2_Rgba32_Blank48x935.png | 3 +++ .../CanDrawTextVerticalMixed2_Rgba32_Blank48x839.png | 3 +++ .../CanDrawTextVerticalMixed_Rgba32_Blank500x400.png | 4 ++-- .../CanDrawTextVertical_Rgba32_Blank500x400.png | 4 ++-- 5 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVertical2_Rgba32_Blank48x935.png create mode 100644 tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed2_Rgba32_Blank48x839.png diff --git a/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawTextOnImageTests.cs index dd7ff3ed..413f437b 100644 --- a/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -879,7 +879,7 @@ public void CanDrawTextVertical2(TestImageProvider provider) { LayoutMode = LayoutMode.VerticalLeftRight, LineSpacing = 1.4F, - // TextRuns = new[] { new RichTextRun() { Start = 0, End = text.GetGraphemeCount(), TextDecorations = TextDecorations.Underline | TextDecorations.Strikeout | TextDecorations.Overline } } + TextRuns = [new RichTextRun() { Start = 0, End = text.GetGraphemeCount(), TextDecorations = TextDecorations.Underline | TextDecorations.Strikeout | TextDecorations.Overline }] }; provider.RunValidatingProcessorTest( @@ -903,7 +903,7 @@ public void CanDrawTextVerticalMixed(TestImageProvider provider) WrappingLength = 400, LayoutMode = LayoutMode.VerticalMixedLeftRight, LineSpacing = 1.4F, - TextRuns = new[] { new RichTextRun() { Start = 0, End = text.GetGraphemeCount(), TextDecorations = TextDecorations.Underline | TextDecorations.Strikeout | TextDecorations.Overline } } + TextRuns = [new RichTextRun() { Start = 0, End = text.GetGraphemeCount(), TextDecorations = TextDecorations.Underline | TextDecorations.Strikeout | TextDecorations.Overline }] }; provider.RunValidatingProcessorTest( @@ -919,7 +919,7 @@ public void CanDrawTextVerticalMixed2(TestImageProvider provider if (SystemFonts.TryGet("Yu Gothic", out FontFamily fontFamily)) { Font font = fontFamily.CreateFont(30F); - const string text = "あいうえお、「こんにちはー」。もしもし。ABCDEFGg 日本語"; + const string text = "あいうえお、「こんにちはー」。もしもし。ABCDEFG 日本語"; RichTextOptions textOptions = new(font) { LayoutMode = LayoutMode.VerticalMixedLeftRight, diff --git a/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVertical2_Rgba32_Blank48x935.png b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVertical2_Rgba32_Blank48x935.png new file mode 100644 index 00000000..a179a801 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVertical2_Rgba32_Blank48x935.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c17b664f4211b759137770cc448027ff90c0d635725bca75636373193bba0701 +size 5543 diff --git a/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed2_Rgba32_Blank48x839.png b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed2_Rgba32_Blank48x839.png new file mode 100644 index 00000000..88a05ee2 --- /dev/null +++ b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed2_Rgba32_Blank48x839.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8b1c7415e5803b1527c5f08693de6b32a6a392e9465ad3a3fea5f9261d026ca +size 5475 diff --git a/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed_Rgba32_Blank500x400.png b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed_Rgba32_Blank500x400.png index 1b377121..f8c6f84a 100644 --- a/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed_Rgba32_Blank500x400.png +++ b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed_Rgba32_Blank500x400.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cfa1c0c0c65831499867466b8b3ac7d0402ea89fba93af2e58283c8d293108b1 -size 10180 +oid sha256:198d02c1e26c0684f2e5a7c29fef402e6256c97d6f341ed1c08a566f2636c021 +size 13925 diff --git a/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVertical_Rgba32_Blank500x400.png b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVertical_Rgba32_Blank500x400.png index 8569fe5b..25804b47 100644 --- a/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVertical_Rgba32_Blank500x400.png +++ b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVertical_Rgba32_Blank500x400.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a42eb1279a508cda6a6791bda68bb03136acec6e20e55c69d53f249d0efe9c3 -size 4460 +oid sha256:dd69cc84711d235653e7e0b93cb5944130ea4e6813773158a483bde31b53655f +size 12508 From 0def2c9a338357503f65a752f74b02b3f29bb19f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 11 Jan 2025 16:05:24 +1000 Subject: [PATCH 4/4] Update to latest Fonts --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 2 +- .../CanDrawTextVerticalMixed_Rgba32_Blank500x400.png | 4 ++-- .../CanFillTextVerticalMixed_Rgba32_Blank500x400.png | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 8f4390cc..cad3a463 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -45,7 +45,7 @@ - + diff --git a/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed_Rgba32_Blank500x400.png b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed_Rgba32_Blank500x400.png index f8c6f84a..b8ebbffb 100644 --- a/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed_Rgba32_Blank500x400.png +++ b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanDrawTextVerticalMixed_Rgba32_Blank500x400.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:198d02c1e26c0684f2e5a7c29fef402e6256c97d6f341ed1c08a566f2636c021 -size 13925 +oid sha256:09fd3e738d38c6dceaeec4286744fff8a43c4dc5e803368666666b1fdf532968 +size 13888 diff --git a/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanFillTextVerticalMixed_Rgba32_Blank500x400.png b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanFillTextVerticalMixed_Rgba32_Blank500x400.png index 8bf1f4c2..e06fd8b6 100644 --- a/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanFillTextVerticalMixed_Rgba32_Blank500x400.png +++ b/tests/Images/ReferenceOutput/Drawing/Text/DrawTextOnImageTests/CanFillTextVerticalMixed_Rgba32_Blank500x400.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdcba4f5713dd1678ec57f5dd97fca793f8d062677f0282c9ea6abfcad946ec7 -size 11460 +oid sha256:8d9a56365aec87bc9ec1a5f8dd7213b5d68f104ac71def4d5a0f4ebfabdd3a32 +size 11318