mirror of https://github.com/SixLabors/ImageSharp
7 changed files with 125 additions and 199 deletions
@ -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<string, byte, float> DrawPathData = new TheoryData<string, byte, float> |
|||
{ |
|||
{ "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<TPixel>(TestImageProvider<TPixel> provider, string colorName, byte alpha, float thickness) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Path"); |
|||
using (var image = new Image<Rgba32>(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<Rgba32> 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<Rgba32>(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<Rgba32> 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<TPixel>(), thickness, path), |
|||
testDetails, |
|||
appendPixelTypeToFileName: false, |
|||
appendSourceFileOrDescription: false); |
|||
} |
|||
|
|||
[Fact] |
|||
public void PathExtendingOffEdgeOfImageShouldNotBeCropped() |
|||
[Theory] |
|||
[WithSolidFilledImages(256, 256, "Black", PixelTypes.Rgba32)] |
|||
public void PathExtendingOffEdgeOfImageShouldNotBeCropped<TPixel>(TestImageProvider<TPixel> provider) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
|
|||
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Path"); |
|||
using (var image = new Image<Rgba32>(256, 256)) |
|||
{ |
|||
image.Mutate(x => x.Fill(Rgba32.Black)); |
|||
Pen<Rgba32> 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<Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); |
|||
Assert.Equal(Rgba32.White, sourcePixels[0, 90]); |
|||
} |
|||
Color color = Color.White; |
|||
Pen<TPixel> pen = Pens.Solid(color.ToPixel<TPixel>(), 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); |
|||
} |
|||
} |
|||
} |
|||
@ -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<TPixel>(TestImageProvider<TPixel> provider, bool overlap, bool transparent) |
|||
where TPixel :struct, IPixel<TPixel> |
|||
{ |
|||
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<TPixel>(), clipped), |
|||
testDetails, |
|||
appendPixelTypeToFileName: false, |
|||
appendSourceFileOrDescription: false); |
|||
} |
|||
} |
|||
} |
|||
@ -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<Rgba32>(500, 500)) |
|||
{ |
|||
image.Mutate(x => x.BackgroundColor(Rgba32.Blue)); |
|||
image.Mutate(x => x.Fill(Rgba32.HotPink, clipped)); |
|||
image.Save($"{path}/Simple.png"); |
|||
|
|||
Buffer2D<Rgba32> 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<Rgba32>(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<Rgba32> 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<Rgba32>(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<Rgba32> sourcePixels = image.GetRootFramePixelBuffer(); |
|||
Assert.Equal(mergedColor, sourcePixels[20, 35]); |
|||
|
|||
//inside hole
|
|||
Assert.Equal(Rgba32.Blue, sourcePixels[60, 100]); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1 +1 @@ |
|||
Subproject commit c057090b4402120a83a8efe251aa5b691db9c0dc |
|||
Subproject commit d83843deedc43712f29f631aab090640b4f54946 |
|||
Loading…
Reference in new issue