Browse Source

Merge pull request #98 from JimBobSquarePants/tocsoft/paths

Use SixLabors.Shapes for polygons instead of our own
af/merge-core
Scott Williams 9 years ago
committed by GitHub
parent
commit
8f6da2b9ac
  1. 8
      ImageSharp.sln
  2. 4
      README.md
  3. 114
      src/ImageSharp.Drawing.Paths/DrawBeziers.cs
  4. 112
      src/ImageSharp.Drawing.Paths/DrawLines.cs
  5. 112
      src/ImageSharp.Drawing.Paths/DrawPath.cs
  6. 112
      src/ImageSharp.Drawing.Paths/DrawPolygon.cs
  7. 58
      src/ImageSharp.Drawing.Paths/DrawRectangle.cs
  8. 112
      src/ImageSharp.Drawing.Paths/DrawShape.cs
  9. 79
      src/ImageSharp.Drawing.Paths/FillPaths.cs
  10. 79
      src/ImageSharp.Drawing.Paths/FillPolygon.cs
  11. 33
      src/ImageSharp.Drawing.Paths/FillRectangle.cs
  12. 79
      src/ImageSharp.Drawing.Paths/FillShape.cs
  13. 25
      src/ImageSharp.Drawing.Paths/ImageSharp.Drawing.Paths.xproj
  14. 6
      src/ImageSharp.Drawing.Paths/Properties/AssemblyInfo.cs
  15. 36
      src/ImageSharp.Drawing.Paths/RectangleExtensions.cs
  16. 153
      src/ImageSharp.Drawing.Paths/ShapePath.cs
  17. 109
      src/ImageSharp.Drawing.Paths/ShapeRegion.cs
  18. 96
      src/ImageSharp.Drawing.Paths/project.json
  19. 20
      src/ImageSharp.Drawing/Brushes/ImageBrush{TColor}.cs
  20. 18
      src/ImageSharp.Drawing/Brushes/PatternBrush{TColor}.cs
  21. 15
      src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs
  22. 31
      src/ImageSharp.Drawing/Brushes/RecolorBrush{TColor}.cs
  23. 8
      src/ImageSharp.Drawing/Brushes/SolidBrush{TColor}.cs
  24. 507
      src/ImageSharp.Drawing/Draw.cs
  25. 3
      src/ImageSharp.Drawing/DrawImage.cs
  26. 111
      src/ImageSharp.Drawing/DrawPath.cs
  27. 51
      src/ImageSharp.Drawing/Drawable.cs
  28. 173
      src/ImageSharp.Drawing/Fill.cs
  29. 103
      src/ImageSharp.Drawing/FillRegion.cs
  30. 119
      src/ImageSharp.Drawing/Paths/BezierLineSegment.cs
  31. 21
      src/ImageSharp.Drawing/Paths/ILineSegment.cs
  32. 48
      src/ImageSharp.Drawing/Paths/IPath.cs
  33. 516
      src/ImageSharp.Drawing/Paths/InternalPath.cs
  34. 55
      src/ImageSharp.Drawing/Paths/LinearLineSegment.cs
  35. 51
      src/ImageSharp.Drawing/Paths/Path.cs
  36. 35
      src/ImageSharp.Drawing/Paths/PointInfo.cs
  37. 9
      src/ImageSharp.Drawing/Pens/Pen{TColor}.cs
  38. 14
      src/ImageSharp.Drawing/Pens/Processors/PenApplicator.cs
  39. 26
      src/ImageSharp.Drawing/PointInfo.cs
  40. 102
      src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs
  41. 7
      src/ImageSharp.Drawing/Processors/FillProcessor.cs
  42. 225
      src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
  43. 46
      src/ImageSharp.Drawing/Region.cs
  44. 93
      src/ImageSharp.Drawing/Shapes/BezierPolygon.cs
  45. 246
      src/ImageSharp.Drawing/Shapes/ComplexPolygon.cs
  46. 56
      src/ImageSharp.Drawing/Shapes/IShape.cs
  47. 93
      src/ImageSharp.Drawing/Shapes/LinearPolygon.cs
  48. 156
      src/ImageSharp.Drawing/Shapes/Polygon.cs
  49. 3860
      src/ImageSharp.Drawing/Shapes/PolygonClipper/Clipper.cs
  50. 31
      src/ImageSharp.Drawing/Shapes/PolygonClipper/ClipperException.cs
  51. 31
      src/ImageSharp.Drawing/Shapes/PolygonClipper/Direction.cs
  52. 31
      src/ImageSharp.Drawing/Shapes/PolygonClipper/EdgeSide.cs
  53. 38
      src/ImageSharp.Drawing/Shapes/PolygonClipper/IntersectNode.cs
  54. 48
      src/ImageSharp.Drawing/Shapes/PolygonClipper/IntersectNodeSort.cs
  55. 38
      src/ImageSharp.Drawing/Shapes/PolygonClipper/Join.cs
  56. 44
      src/ImageSharp.Drawing/Shapes/PolygonClipper/LocalMinima.cs
  57. 38
      src/ImageSharp.Drawing/Shapes/PolygonClipper/Maxima.cs
  58. 43
      src/ImageSharp.Drawing/Shapes/PolygonClipper/OutPt.cs
  59. 64
      src/ImageSharp.Drawing/Shapes/PolygonClipper/OutRec.cs
  60. 179
      src/ImageSharp.Drawing/Shapes/PolygonClipper/PolyNode.cs
  61. 81
      src/ImageSharp.Drawing/Shapes/PolygonClipper/PolyTree.cs
  62. 31
      src/ImageSharp.Drawing/Shapes/PolygonClipper/PolyType.cs
  63. 40
      src/ImageSharp.Drawing/Shapes/PolygonClipper/README.md
  64. 33
      src/ImageSharp.Drawing/Shapes/PolygonClipper/Scanbeam.cs
  65. 118
      src/ImageSharp.Drawing/Shapes/PolygonClipper/TEdge.cs
  66. 281
      src/ImageSharp.Drawing/Shapes/RectangularPolygon.cs
  67. 6
      src/ImageSharp.Drawing/project.json
  68. 3
      src/ImageSharp.Processing/Binarization/BinaryThreshold.cs
  69. 3
      src/ImageSharp.Processing/ColorMatrix/BlackWhite.cs
  70. 3
      src/ImageSharp.Processing/ColorMatrix/ColorBlindness.cs
  71. 3
      src/ImageSharp.Processing/ColorMatrix/Grayscale.cs
  72. 3
      src/ImageSharp.Processing/ColorMatrix/Hue.cs
  73. 3
      src/ImageSharp.Processing/ColorMatrix/Kodachrome.cs
  74. 3
      src/ImageSharp.Processing/ColorMatrix/Lomograph.cs
  75. 3
      src/ImageSharp.Processing/ColorMatrix/Polaroid.cs
  76. 3
      src/ImageSharp.Processing/ColorMatrix/Saturation.cs
  77. 3
      src/ImageSharp.Processing/ColorMatrix/Sepia.cs
  78. 3
      src/ImageSharp.Processing/Convolution/BoxBlur.cs
  79. 3
      src/ImageSharp.Processing/Convolution/DetectEdges.cs
  80. 3
      src/ImageSharp.Processing/Convolution/GaussianBlur.cs
  81. 3
      src/ImageSharp.Processing/Convolution/GaussianSharpen.cs
  82. 3
      src/ImageSharp.Processing/Effects/Alpha.cs
  83. 3
      src/ImageSharp.Processing/Effects/BackgroundColor.cs
  84. 5
      src/ImageSharp.Processing/Effects/Brightness.cs
  85. 3
      src/ImageSharp.Processing/Effects/Contrast.cs
  86. 3
      src/ImageSharp.Processing/Effects/Invert.cs
  87. 3
      src/ImageSharp.Processing/Effects/OilPainting.cs
  88. 3
      src/ImageSharp.Processing/Effects/Pixelate.cs
  89. 3
      src/ImageSharp.Processing/Overlays/Glow.cs
  90. 3
      src/ImageSharp.Processing/Overlays/Vignette.cs
  91. 4
      src/ImageSharp.Processing/Transforms/Crop.cs
  92. 4
      src/ImageSharp.Processing/Transforms/EntropyCrop.cs
  93. 4
      src/ImageSharp.Processing/Transforms/Flip.cs
  94. 3
      src/ImageSharp.Processing/Transforms/Resize.cs
  95. 4
      src/ImageSharp.Processing/Transforms/Rotate.cs
  96. 4
      src/ImageSharp.Processing/Transforms/Skew.cs
  97. 11
      src/ImageSharp/Image/ImageBase{TColor}.cs
  98. 25
      src/ImageSharp/Image/ImageProcessingExtensions.cs
  99. 16
      src/ImageSharp/Image/Image{TColor}.cs
  100. 10
      tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs

8
ImageSharp.sln

@ -60,11 +60,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageSharp.Sandbox46", "tes
{2AA31A1F-142C-43F4-8687-09ABCA4B3A26} = {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}
{27AD4B5F-ECC4-4C63-9ECB-04EC772FDB6F} = {27AD4B5F-ECC4-4C63-9ECB-04EC772FDB6F}
{7213767C-0003-41CA-AB18-0223CFA7CE4B} = {7213767C-0003-41CA-AB18-0223CFA7CE4B}
{E5BD4F96-28A8-410C-8B63-1C5731948549} = {E5BD4F96-28A8-410C-8B63-1C5731948549}
{C77661B9-F793-422E-8E27-AC60ECC5F215} = {C77661B9-F793-422E-8E27-AC60ECC5F215}
{556ABDCF-ED93-4327-BE98-F6815F78B9B8} = {556ABDCF-ED93-4327-BE98-F6815F78B9B8}
{A623CFE9-9D2B-4528-AD1F-2E834B061134} = {A623CFE9-9D2B-4528-AD1F-2E834B061134}
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ImageSharp.Drawing.Paths", "src\ImageSharp.Drawing.Paths\ImageSharp.Drawing.Paths.xproj", "{E5BD4F96-28A8-410C-8B63-1C5731948549}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -115,6 +118,10 @@ Global
{96188137-5FA6-4924-AB6E-4EFF79C6E0BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96188137-5FA6-4924-AB6E-4EFF79C6E0BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96188137-5FA6-4924-AB6E-4EFF79C6E0BB}.Release|Any CPU.Build.0 = Release|Any CPU
{E5BD4F96-28A8-410C-8B63-1C5731948549}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5BD4F96-28A8-410C-8B63-1C5731948549}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5BD4F96-28A8-410C-8B63-1C5731948549}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5BD4F96-28A8-410C-8B63-1C5731948549}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -132,5 +139,6 @@ Global
{A623CFE9-9D2B-4528-AD1F-2E834B061134} = {815C0625-CD3D-440F-9F80-2D83856AB7AE}
{9E574A07-F879-4811-9C41-5CBDC6BAFDB7} = {815C0625-CD3D-440F-9F80-2D83856AB7AE}
{96188137-5FA6-4924-AB6E-4EFF79C6E0BB} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC}
{E5BD4F96-28A8-410C-8B63-1C5731948549} = {815C0625-CD3D-440F-9F80-2D83856AB7AE}
EndGlobalSection
EndGlobal

4
README.md

@ -45,7 +45,9 @@ Packages include:
Contains methods like Resize, Crop, Skew, Rotate - Anything that alters the dimensions of the image.
Contains methods like Gaussian Blur, Pixelate, Edge Detection - Anything that maintains the original image dimensions.
- **ImageSharp.Drawing**
Brushes and various drawing algorithms.
Brushes and various drawing algorithms, including drawing Images
- **ImageSharp.Drawing.Paths**
Various vector drawing methods for drawing paths, polygons etc.
### Manual build

114
src/ImageSharp.Drawing.Paths/DrawBeziers.cs

@ -0,0 +1,114 @@
// <copyright file="DrawBeziers.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using Drawing.Processors;
using SixLabors.Shapes;
using Path = SixLabors.Shapes.Path;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Path(new BezierLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Path(new BezierLineSegment(points)));
}
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawBeziers(new SolidBrush<TColor>(color), thickness, points);
}
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawBeziers(new SolidBrush<TColor>(color), thickness, points, options);
}
/// <summary>
/// Draws the provided Points as an open Bezier path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, new Path(new BezierLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Bezier path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, new Path(new BezierLineSegment(points)));
}
}
}

112
src/ImageSharp.Drawing.Paths/DrawLines.cs

@ -0,0 +1,112 @@
// <copyright file="DrawLines.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using Drawing.Processors;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Path(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Path(new LinearLineSegment(points)));
}
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawLines(new SolidBrush<TColor>(color), thickness, points);
}
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawLines(new SolidBrush<TColor>(color), thickness, points, options);
}
/// <summary>
/// Draws the provided Points as an open Linear path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, new Path(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Linear path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, new Path(new LinearLineSegment(points)));
}
}
}

112
src/ImageSharp.Drawing.Paths/DrawPath.cs

@ -0,0 +1,112 @@
// <copyright file="DrawPath.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using Drawing.Processors;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IPen<TColor> pen, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, new ShapePath(path), options);
}
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="path">The path.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IPen<TColor> pen, IPath path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, path, GraphicsOptions.Default);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), path, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, IPath path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), path);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, TColor color, float thickness, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, path, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, TColor color, float thickness, IPath path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, path);
}
}
}

112
src/ImageSharp.Drawing.Paths/DrawPolygon.cs

@ -0,0 +1,112 @@
// <copyright file="DrawPolygon.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using Drawing.Processors;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Polygon(new LinearLineSegment(points)));
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new SolidBrush<TColor>(color), thickness, points);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new SolidBrush<TColor>(color), thickness, points, options);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided Pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, new Polygon(new LinearLineSegment(points)), GraphicsOptions.Default);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided Pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, new Polygon(new LinearLineSegment(points)), options);
}
}
}

58
src/ImageSharp.Drawing/DrawRectangle.cs → src/ImageSharp.Drawing.Paths/DrawRectangle.cs

@ -9,10 +9,10 @@ namespace ImageSharp
using Drawing;
using Drawing.Brushes;
using Drawing.Paths;
using Drawing.Pens;
using Drawing.Processors;
using Drawing.Shapes;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
@ -23,97 +23,91 @@ namespace ImageSharp
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IPen<TColor> pen, RectangleF shape, GraphicsOptions options)
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IPen<TColor> pen, Rectangle shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new DrawPathProcessor<TColor>(pen, (IPath)new RectangularPolygon(shape), options));
return source.Draw(pen, new SixLabors.Shapes.Rectangle(shape.X, shape.Y, shape.Width, shape.Height), options);
}
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IPen<TColor> pen, RectangleF shape)
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IPen<TColor> pen, Rectangle shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(pen, shape, GraphicsOptions.Default);
return source.Draw(pen, shape, GraphicsOptions.Default);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, RectangleF shape, GraphicsOptions options)
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Rectangle shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new Pen<TColor>(brush, thickness), shape, options);
return source.Draw(new Pen<TColor>(brush, thickness), shape, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, RectangleF shape)
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Rectangle shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new Pen<TColor>(brush, thickness), shape);
return source.Draw(new Pen<TColor>(brush, thickness), shape);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, TColor color, float thickness, RectangleF shape, GraphicsOptions options)
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, TColor color, float thickness, Rectangle shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new SolidBrush<TColor>(color), thickness, shape, options);
return source.Draw(new SolidBrush<TColor>(color), thickness, shape, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, TColor color, float thickness, RectangleF shape)
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, TColor color, float thickness, Rectangle shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new SolidBrush<TColor>(color), thickness, shape);
return source.Draw(new SolidBrush<TColor>(color), thickness, shape);
}
}
}

112
src/ImageSharp.Drawing.Paths/DrawShape.cs

@ -0,0 +1,112 @@
// <copyright file="DrawShape.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using Drawing.Processors;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IPen<TColor> pen, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, new ShapePath(shape), options);
}
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="shape">The shape.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IPen<TColor> pen, IShape shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, shape, GraphicsOptions.Default);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), shape, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, IShape shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), shape);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, TColor color, float thickness, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, shape, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, TColor color, float thickness, IShape shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, shape);
}
}
}

79
src/ImageSharp.Drawing.Paths/FillPaths.cs

@ -0,0 +1,79 @@
// <copyright file="FillPaths.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Processors;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="path">The shape.</param>
/// <param name="options">The graphics options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(brush, new ShapeRegion(path), options);
}
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="path">The path.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, IPath path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(brush, new ShapeRegion(path), GraphicsOptions.Default);
}
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), path, options);
}
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="path">The path.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, IPath path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), path);
}
}
}

79
src/ImageSharp.Drawing.Paths/FillPolygon.cs

@ -0,0 +1,79 @@
// <copyright file="FillPolygon.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Processors;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> FillPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(brush, new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> FillPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(brush, new Polygon(new LinearLineSegment(points)));
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> FillPolygon<TColor>(this Image<TColor> source, TColor color, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="points">The points.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> FillPolygon<TColor>(this Image<TColor> source, TColor color, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), new Polygon(new LinearLineSegment(points)));
}
}
}

33
src/ImageSharp.Drawing/FillRectangle.cs → src/ImageSharp.Drawing.Paths/FillRectangle.cs

@ -10,7 +10,6 @@ namespace ImageSharp
using Drawing;
using Drawing.Brushes;
using Drawing.Processors;
using Drawing.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
@ -21,45 +20,41 @@ namespace ImageSharp
/// Flood fills the image in the shape of the provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, RectangleF shape, GraphicsOptions options)
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, Rectangle shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new FillShapeProcessor<TColor>(brush, new RectangularPolygon(shape), options));
return source.Fill(brush, new SixLabors.Shapes.Rectangle(shape.X, shape.Y, shape.Width, shape.Height), options);
}
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, RectangleF shape)
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, Rectangle shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new FillShapeProcessor<TColor>(brush, new RectangularPolygon(shape), GraphicsOptions.Default));
return source.Fill(brush, new SixLabors.Shapes.Rectangle(shape.X, shape.Y, shape.Width, shape.Height));
}
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, RectangleF shape, GraphicsOptions options)
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, Rectangle shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), shape, options);
@ -69,11 +64,11 @@ namespace ImageSharp
/// Flood fills the image in the shape of the provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, RectangleF shape)
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, Rectangle shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), shape);

79
src/ImageSharp.Drawing.Paths/FillShape.cs

@ -0,0 +1,79 @@
// <copyright file="FillShape.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Processors;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The graphics options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(brush, new ShapeRegion(shape), options);
}
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="shape">The shape.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, IShape shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(brush, new ShapeRegion(shape), GraphicsOptions.Default);
}
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), shape, options);
}
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="shape">The shape.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, IShape shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), shape);
}
}
}

25
src/ImageSharp.Drawing.Paths/ImageSharp.Drawing.Paths.xproj

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>e5bd4f96-28a8-410c-8b63-1c5731948549</ProjectGuid>
<RootNamespace>ImageSharp.Drawing</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild>
</PropertyGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

6
src/ImageSharp.Drawing.Paths/Properties/AssemblyInfo.cs

@ -0,0 +1,6 @@
// <copyright file="AssemblyInfo.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// Common values read from `AssemblyInfo.Common.cs`

36
src/ImageSharp.Drawing.Paths/RectangleExtensions.cs

@ -0,0 +1,36 @@
// <copyright file="RectangleExtensions.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Processors
{
using System;
using System.Buffers;
using System.Numerics;
using System.Threading.Tasks;
using Drawing;
using ImageSharp.Processing;
using SixLabors.Shapes;
using Rectangle = ImageSharp.Rectangle;
/// <summary>
/// Extension methods for helping to bridge Shaper2D and ImageSharp primitives.
/// </summary>
internal static class RectangleExtensions
{
/// <summary>
/// Converts a Shaper2D <see cref="SixLabors.Shapes.Rectangle"/> to an ImageSharp <see cref="Rectangle"/> by creating a <see cref="Rectangle"/> the entirely surrounds the source.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <returns>A <see cref="Rectangle"/> representation of this <see cref="SixLabors.Shapes.Rectangle"/></returns>
public static Rectangle Convert(this SixLabors.Shapes.Rectangle source)
{
int left = (int)Math.Floor(source.Left);
int right = (int)Math.Ceiling(source.Right);
int top = (int)Math.Floor(source.Top);
int bottom = (int)Math.Ceiling(source.Bottom);
return new Rectangle(left, top, right - left, bottom - top);
}
}
}

153
src/ImageSharp.Drawing.Paths/ShapePath.cs

@ -0,0 +1,153 @@
// <copyright file="ShapePath.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing
{
using System.Buffers;
using System.Collections.Immutable;
using System.Numerics;
using ImageSharp.Drawing.Processors;
using SixLabors.Shapes;
using Rectangle = ImageSharp.Rectangle;
/// <summary>
/// A drawable mapping between a <see cref="SixLabors.Shapes.IShape"/>/<see cref="SixLabors.Shapes.IPath"/> and a drawable/fillable region.
/// </summary>
internal class ShapePath : ImageSharp.Drawing.Drawable
{
/// <summary>
/// The fillable shape
/// </summary>
private readonly IShape shape;
/// <summary>
/// Initializes a new instance of the <see cref="ShapePath"/> class.
/// </summary>
/// <param name="path">The path.</param>
public ShapePath(IPath path)
: this(ImmutableArray.Create(path))
{
this.shape = path.AsShape();
this.Bounds = RectangleF.Ceiling(path.Bounds.Convert());
}
/// <summary>
/// Initializes a new instance of the <see cref="ShapePath"/> class.
/// </summary>
/// <param name="shape">The shape.</param>
public ShapePath(IShape shape)
: this(shape.Paths)
{
this.shape = shape;
this.Bounds = RectangleF.Ceiling(shape.Bounds.Convert());
}
/// <summary>
/// Initializes a new instance of the <see cref="ShapePath" /> class.
/// </summary>
/// <param name="paths">The paths.</param>
private ShapePath(ImmutableArray<IPath> paths)
{
this.Paths = paths;
}
/// <summary>
/// Gets the drawable paths
/// </summary>
/// <value>
/// The paths.
/// </value>
public ImmutableArray<IPath> Paths { get; }
/// <inheritdoc/>
public override int MaxIntersections => this.shape.MaxIntersections;
/// <inheritdoc/>
public override Rectangle Bounds { get; }
/// <inheritdoc/>
public override int ScanX(int x, float[] buffer, int length, int offset)
{
Vector2 start = new Vector2(x, this.Bounds.Top - 1);
Vector2 end = new Vector2(x, this.Bounds.Bottom + 1);
Vector2[] innerbuffer = ArrayPool<Vector2>.Shared.Rent(length);
try
{
int count = this.shape.FindIntersections(
start,
end,
innerbuffer,
length,
0);
for (int i = 0; i < count; i++)
{
buffer[i + offset] = innerbuffer[i].Y;
}
return count;
}
finally
{
ArrayPool<Vector2>.Shared.Return(innerbuffer);
}
}
/// <inheritdoc/>
public override int ScanY(int y, float[] buffer, int length, int offset)
{
Vector2 start = new Vector2(this.Bounds.Left - 1, y);
Vector2 end = new Vector2(this.Bounds.Right + 1, y);
Vector2[] innerbuffer = ArrayPool<Vector2>.Shared.Rent(length);
try
{
int count = this.shape.FindIntersections(
start,
end,
innerbuffer,
length,
0);
for (int i = 0; i < count; i++)
{
buffer[i + offset] = innerbuffer[i].X;
}
return count;
}
finally
{
ArrayPool<Vector2>.Shared.Return(innerbuffer);
}
}
/// <inheritdoc/>
public override PointInfo GetPointInfo(int x, int y)
{
Vector2 point = new Vector2(x, y);
float distanceFromPath = float.MaxValue;
float distanceAlongPath = 0;
for (int i = 0; i < this.Paths.Length; i++)
{
SixLabors.Shapes.PointInfo p = this.Paths[i].Distance(point);
if (p.DistanceFromPath < distanceFromPath)
{
distanceFromPath = p.DistanceFromPath;
distanceAlongPath = p.DistanceAlongPath;
}
}
return new PointInfo
{
DistanceAlongPath = distanceAlongPath,
DistanceFromPath = distanceFromPath
};
}
}
}

109
src/ImageSharp.Drawing.Paths/ShapeRegion.cs

@ -0,0 +1,109 @@
// <copyright file="ShapeRegion.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing
{
using System.Buffers;
using System.Collections.Immutable;
using System.Numerics;
using ImageSharp.Drawing.Processors;
using SixLabors.Shapes;
using Rectangle = ImageSharp.Rectangle;
/// <summary>
/// A drawable mapping between a <see cref="SixLabors.Shapes.IShape"/>/<see cref="SixLabors.Shapes.IPath"/> and a drawable/fillable region.
/// </summary>
internal class ShapeRegion : Region
{
/// <summary>
/// Initializes a new instance of the <see cref="ShapeRegion"/> class.
/// </summary>
/// <param name="path">The path.</param>
public ShapeRegion(IPath path)
: this(path.AsShape())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ShapeRegion"/> class.
/// </summary>
/// <param name="shape">The shape.</param>
public ShapeRegion(IShape shape)
{
this.Shape = shape;
this.Bounds = shape.Bounds.Convert();
}
/// <summary>
/// Gets the fillable shape
/// </summary>
public IShape Shape { get; }
/// <inheritdoc/>
public override int MaxIntersections => this.Shape.MaxIntersections;
/// <inheritdoc/>
public override Rectangle Bounds { get; }
/// <inheritdoc/>
public override int ScanX(int x, float[] buffer, int length, int offset)
{
Vector2 start = new Vector2(x, this.Bounds.Top - 1);
Vector2 end = new Vector2(x, this.Bounds.Bottom + 1);
Vector2[] innerbuffer = ArrayPool<Vector2>.Shared.Rent(length);
try
{
int count = this.Shape.FindIntersections(
start,
end,
innerbuffer,
length,
0);
for (int i = 0; i < count; i++)
{
buffer[i + offset] = innerbuffer[i].Y;
}
return count;
}
finally
{
ArrayPool<Vector2>.Shared.Return(innerbuffer);
}
}
/// <inheritdoc/>
public override int ScanY(int y, float[] buffer, int length, int offset)
{
Vector2 start = new Vector2(this.Bounds.Left - 1, y);
Vector2 end = new Vector2(this.Bounds.Right + 1, y);
Vector2[] innerbuffer = ArrayPool<Vector2>.Shared.Rent(length);
try
{
int count = this.Shape.FindIntersections(
start,
end,
innerbuffer,
length,
0);
for (int i = 0; i < count; i++)
{
buffer[i + offset] = innerbuffer[i].X;
}
return count;
}
finally
{
ArrayPool<Vector2>.Shared.Return(innerbuffer);
}
}
}
}

96
src/ImageSharp.Drawing.Paths/project.json

@ -0,0 +1,96 @@
{
"version": "1.0.0-alpha1-*",
"title": "ImageSharp.Drawing.Paths",
"description": "A cross-platform library for the processing of image files; written in C#",
"authors": [
"James Jackson-South and contributors"
],
"packOptions": {
"owners": [
"James Jackson-South and contributors"
],
"projectUrl": "https://github.com/JimBobSquarePants/ImageSharp",
"licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0",
"iconUrl": "https://raw.githubusercontent.com/JimBobSquarePants/ImageSharp/master/build/icons/imagesharp-logo-128.png",
"requireLicenseAcceptance": false,
"repository": {
"type": "git",
"url": "https://github.com/JimBobSquarePants/ImageSharp"
},
"tags": [
"Image Resize Crop Gif Jpg Jpeg Bitmap Png Core"
]
},
"buildOptions": {
"allowUnsafe": true,
"xmlDoc": true,
"additionalArguments": [ "/additionalfile:../Shared/stylecop.json", "/ruleset:../../ImageSharp.ruleset" ],
"compile": [
"../Shared/*.cs"
]
},
"configurations": {
"Release": {
"buildOptions": {
"warningsAsErrors": true,
"optimize": true
}
}
},
"dependencies": {
"ImageSharp": {
"target": "project"
},
"ImageSharp.Drawing": {
"target": "project"
},
"SixLabors.Shapes": "0.1.0-alpha0003",
"StyleCop.Analyzers": {
"version": "1.0.0",
"type": "build"
},
"System.Buffers": "4.0.0",
"System.Runtime.CompilerServices.Unsafe": "4.0.0"
},
"frameworks": {
"netstandard1.1": {
"dependencies": {
"System.Collections": "4.0.11",
"System.Diagnostics.Debug": "4.0.11",
"System.Diagnostics.Tools": "4.0.1",
"System.IO": "4.1.0",
"System.IO.Compression": "4.1.0",
"System.Linq": "4.1.0",
"System.Numerics.Vectors": "4.1.1",
"System.ObjectModel": "4.0.12",
"System.Resources.ResourceManager": "4.0.1",
"System.Runtime.Extensions": "4.1.0",
"System.Runtime.InteropServices": "4.1.0",
"System.Runtime.Numerics": "4.0.1",
"System.Text.Encoding.Extensions": "4.0.11",
"System.Threading": "4.0.11",
"System.Threading.Tasks": "4.0.11",
"System.Threading.Tasks.Parallel": "4.0.1"
}
},
"net45": {
"dependencies": {
"System.Numerics.Vectors": "4.1.1",
"System.Threading.Tasks.Parallel": "4.0.0"
},
"frameworkAssemblies": {
"System.Runtime": { "type": "build" }
}
},
"net461": {
"dependencies": {
"System.Threading.Tasks.Parallel": "4.0.0"
},
"frameworkAssemblies": {
"System.Runtime": { "type": "build" },
"System.Numerics": "4.0.0.0",
"System.Numerics.Vectors": "4.0.0.0"
}
}
}
}

20
src/ImageSharp.Drawing/Brushes/ImageBrush{TColor}.cs

@ -82,18 +82,24 @@ namespace ImageSharp.Drawing.Brushes
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The color
/// </returns>
public override TColor GetColor(Vector2 point)
public override TColor this[int x, int y]
{
// Offset the requested pixel by the value in the rectangle (the shapes position)
point = point - this.offset;
int x = (int)point.X % this.xLength;
int y = (int)point.Y % this.yLength;
get
{
var point = new Vector2(x, y);
return this.source[x, y];
// Offset the requested pixel by the value in the rectangle (the shapes position)
point = point - this.offset;
x = (int)point.X % this.xLength;
y = (int)point.Y % this.yLength;
return this.source[x, y];
}
}
/// <inheritdoc />

18
src/ImageSharp.Drawing/Brushes/PatternBrush{TColor}.cs

@ -134,17 +134,21 @@ namespace ImageSharp.Drawing.Brushes
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// </summary>#
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The color
/// The Color.
/// </returns>
public override TColor GetColor(Vector2 point)
public override TColor this[int x, int y]
{
int x = (int)point.X % this.xLength;
int y = (int)point.Y % this.stride;
get
{
x = x % this.xLength;
y = y % this.stride;
return this.pattern[x][y];
return this.pattern[x][y];
}
}
/// <inheritdoc />

15
src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs

@ -16,16 +16,15 @@ namespace ImageSharp.Drawing.Processors
public abstract class BrushApplicator<TColor> : IDisposable // disposable will be required if/when there is an ImageBrush
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public abstract void Dispose();
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>The color</returns>
public abstract TColor GetColor(Vector2 point);
/// <param name="x">The x cordinate.</param>
/// <param name="y">The y cordinate.</param>
/// <returns>The a <typeparamref name="TColor"/> that should be applied to the pixel.</returns>
public abstract TColor this[int x, int y] { get; }
/// <inheritdoc/>
public abstract void Dispose();
}
}

31
src/ImageSharp.Drawing/Brushes/RecolorBrush{TColor}.cs

@ -109,24 +109,31 @@ namespace ImageSharp.Drawing.Brushes
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The color
/// </returns>
public override TColor GetColor(Vector2 point)
public override TColor this[int x, int y]
{
// Offset the requested pixel by the value in the rectangle (the shapes position)
TColor result = this.source[(int)point.X, (int)point.Y];
Vector4 background = result.ToVector4();
float distance = Vector4.DistanceSquared(background, this.sourceColor);
if (distance <= this.threshold)
get
{
var lerpAmount = (this.threshold - distance) / this.threshold;
Vector4 blended = Vector4BlendTransforms.PremultipliedLerp(background, this.targetColor, lerpAmount);
result.PackFromVector4(blended);
// Offset the requested pixel by the value in the rectangle (the shapes position)
TColor result = this.source[x, y];
Vector4 background = result.ToVector4();
float distance = Vector4.DistanceSquared(background, this.sourceColor);
if (distance <= this.threshold)
{
var lerpAmount = (this.threshold - distance) / this.threshold;
Vector4 blended = Vector4BlendTransforms.PremultipliedLerp(
background,
this.targetColor,
lerpAmount);
result.PackFromVector4(blended);
}
return result;
}
return result;
}
/// <inheritdoc />

8
src/ImageSharp.Drawing/Brushes/SolidBrush{TColor}.cs

@ -67,14 +67,12 @@ namespace ImageSharp.Drawing.Brushes
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The color
/// </returns>
public override TColor GetColor(Vector2 point)
{
return this.color;
}
public override TColor this[int x, int y] => this.color;
/// <inheritdoc />
public override void Dispose()

507
src/ImageSharp.Drawing/Draw.cs

@ -1,507 +0,0 @@
// <copyright file="Draw.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Paths;
using Drawing.Pens;
using Drawing.Processors;
using Drawing.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IPen<TColor> pen, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new DrawPathProcessor<TColor>(pen, shape, options));
}
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IPen<TColor> pen, IShape shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(pen, shape, GraphicsOptions.Default);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new Pen<TColor>(brush, thickness), shape, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, IShape shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new Pen<TColor>(brush, thickness), shape);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, TColor color, float thickness, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new SolidBrush<TColor>(color), thickness, shape, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, TColor color, float thickness, IShape shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new SolidBrush<TColor>(color), thickness, shape);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new Pen<TColor>(brush, thickness), new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new Pen<TColor>(brush, thickness), new Polygon(new LinearLineSegment(points)));
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new SolidBrush<TColor>(color), thickness, points);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(new SolidBrush<TColor>(color), thickness, points, options);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided Pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(pen, new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided Pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPolygon<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPolygon(pen, new Polygon(new LinearLineSegment(points)));
}
/// <summary>
/// Draws the path with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPath<TColor>(this Image<TColor> source, IPen<TColor> pen, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new DrawPathProcessor<TColor>(pen, path, options));
}
/// <summary>
/// Draws the path with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="path">The path.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPath<TColor>(this Image<TColor> source, IPen<TColor> pen, IPath path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new DrawPathProcessor<TColor>(pen, path, GraphicsOptions.Default));
}
/// <summary>
/// Draws the path with the bursh at the privdied thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPath<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(new Pen<TColor>(brush, thickness), path, options);
}
/// <summary>
/// Draws the path with the bursh at the privdied thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPath<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, IPath path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(new Pen<TColor>(brush, thickness), path);
}
/// <summary>
/// Draws the path with the bursh at the privdied thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawPath<TColor>(this Image<TColor> source, TColor color, float thickness, IPath path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(new SolidBrush<TColor>(color), thickness, path, options);
}
/// <summary>
/// Draws the path with the bursh at the privdied thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawPath<TColor>(this Image<TColor> source, TColor color, float thickness, IPath path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(new SolidBrush<TColor>(color), thickness, path);
}
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(new Pen<TColor>(brush, thickness), new Path(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(new Pen<TColor>(brush, thickness), new Path(new LinearLineSegment(points)));
}
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawLines(new SolidBrush<TColor>(color), thickness, points);
}
/// <summary>
/// Draws the provided Points as an open Linear path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawLines(new SolidBrush<TColor>(color), thickness, points, options);
}
/// <summary>
/// Draws the provided Points as an open Linear path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(pen, new Path(new LinearLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Linear path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawLines<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(pen, new Path(new LinearLineSegment(points)));
}
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(new Pen<TColor>(brush, thickness), new Path(new BezierLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(new Pen<TColor>(brush, thickness), new Path(new BezierLineSegment(points)));
}
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawBeziers(new SolidBrush<TColor>(color), thickness, points);
}
/// <summary>
/// Draws the provided Points as an open Bezier path at the provided thickness with the supplied brush
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, TColor color, float thickness, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawBeziers(new SolidBrush<TColor>(color), thickness, points, options);
}
/// <summary>
/// Draws the provided Points as an open Bezier path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(pen, new Path(new BezierLineSegment(points)), options);
}
/// <summary>
/// Draws the provided Points as an open Bezier path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="pen">The pen.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> DrawBeziers<TColor>(this Image<TColor> source, IPen<TColor> pen, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.DrawPath(pen, new Path(new BezierLineSegment(points)));
}
}
}

3
src/ImageSharp.Drawing/DrawImage.cs

@ -51,7 +51,8 @@ namespace ImageSharp
location = Point.Empty;
}
return source.Apply(source.Bounds, new DrawImageProcessor<TColor>(image, size, location, percent));
source.ApplyProcessor(new DrawImageProcessor<TColor>(image, size, location, percent), source.Bounds);
return source;
}
}
}

111
src/ImageSharp.Drawing/DrawPath.cs

@ -0,0 +1,111 @@
// <copyright file="DrawPath.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using Drawing.Processors;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Draws the outline of the region with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IPen<TColor> pen, Drawable path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new DrawPathProcessor<TColor>(pen, path, options));
}
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="pen">The pen.</param>
/// <param name="path">The path.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IPen<TColor> pen, Drawable path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(pen, path, GraphicsOptions.Default);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Drawable path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), path, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, IBrush<TColor> brush, float thickness, Drawable path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new Pen<TColor>(brush, thickness), path);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, TColor color, float thickness, Drawable path, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, path, options);
}
/// <summary>
/// Draws the outline of the polygon with the provided brush at the provided thickness.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="path">The path.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Draw<TColor>(this Image<TColor> source, TColor color, float thickness, Drawable path)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, path);
}
}
}

51
src/ImageSharp.Drawing/Drawable.cs

@ -0,0 +1,51 @@
// <copyright file="Drawable.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing
{
/// <summary>
/// Represents a path or set of paths that can be drawn as an outline.
/// </summary>
public abstract class Drawable
{
/// <summary>
/// Gets the maximum number of intersections to could be returned.
/// </summary>
public abstract int MaxIntersections { get; }
/// <summary>
/// Gets the bounds.
/// </summary>
public abstract Rectangle Bounds { get; }
/// <summary>
/// Gets the point information for the specified x and y location.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>Information about the point in relation to a drawable edge</returns>
public abstract PointInfo GetPointInfo(int x, int y);
/// <summary>
/// Scans the X axis for intersections.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="length">The length.</param>
/// <param name="offset">The offset.</param>
/// <returns>The number of intersections found.</returns>
public abstract int ScanX(int x, float[] buffer, int length, int offset);
/// <summary>
/// Scans the Y axis for intersections.
/// </summary>
/// <param name="y">The position along the y axis to find intersections.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="length">The length.</param>
/// <param name="offset">The offset.</param>
/// <returns>The number of intersections found.</returns>
public abstract int ScanY(int y, float[] buffer, int length, int offset);
}
}

173
src/ImageSharp.Drawing/Fill.cs

@ -1,173 +0,0 @@
// <copyright file="Fill.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Paths;
using Drawing.Processors;
using Drawing.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Flood fills the image with the specified brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <returns>The Image</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new FillProcessor<TColor>(brush));
}
/// <summary>
/// Flood fills the image with the specified color.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <returns>The Image</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color));
}
/// <summary>
/// Flood fills the image in the shape o fhte provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The graphics options.</param>
/// <returns>The Image</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new FillShapeProcessor<TColor>(brush, shape, options));
}
/// <summary>
/// Flood fills the image in the shape of the provided polygon with the specified brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, IShape shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new FillShapeProcessor<TColor>(brush, shape, GraphicsOptions.Default));
}
/// <summary>
/// Flood fills the image in the shape o fhte provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, IShape shape, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), shape, options);
}
/// <summary>
/// Flood fills the image in the shape o fhte provided polygon with the specified brush..
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="shape">The shape.</param>
/// <returns>The Image</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, IShape shape)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), shape);
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> FillPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
// using Polygon directly instead of LinearPolygon as its will have less indirection
return source.Fill(brush, new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="brush">The brush.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> FillPolygon<TColor>(this Image<TColor> source, IBrush<TColor> brush, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
// using Polygon directly instead of LinearPolygon as its will have less indirection
return source.Fill(brush, new Polygon(new LinearLineSegment(points)));
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="points">The points.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The Image
/// </returns>
public static Image<TColor> FillPolygon<TColor>(this Image<TColor> source, TColor color, Vector2[] points, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
// using Polygon directly instead of LinearPolygon as its will have less indirection
return source.Fill(new SolidBrush<TColor>(color), new Polygon(new LinearLineSegment(points)), options);
}
/// <summary>
/// Flood fills the image in the shape of a Linear polygon described by the points
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The source.</param>
/// <param name="color">The color.</param>
/// <param name="points">The points.</param>
/// <returns>The Image</returns>
public static Image<TColor> FillPolygon<TColor>(this Image<TColor> source, TColor color, Vector2[] points)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
// using Polygon directly instead of LinearPolygon as its will have less indirection
return source.Fill(new SolidBrush<TColor>(color), new Polygon(new LinearLineSegment(points)));
}
}
}

103
src/ImageSharp.Drawing/FillRegion.cs

@ -0,0 +1,103 @@
// <copyright file="FillRegion.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Processors;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Flood fills the image with the specified brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The details how to fill the region of interest.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new FillProcessor<TColor>(brush));
}
/// <summary>
/// Flood fills the image with the specified color.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color));
}
/// <summary>
/// Flood fills the image with in the region with the specified brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="region">The region.</param>
/// <param name="options">The graphics options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, Region region, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(new FillRegionProcessor<TColor>(brush, region, options));
}
/// <summary>
/// Flood fills the image with in the region with the specified brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="brush">The brush.</param>
/// <param name="region">The region.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, IBrush<TColor> brush, Region region)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(brush, region, GraphicsOptions.Default);
}
/// <summary>
/// Flood fills the image with in the region with the specified color.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="region">The region.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, Region region, GraphicsOptions options)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), region, options);
}
/// <summary>
/// Flood fills the image with in the region with the specified color.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color.</param>
/// <param name="region">The region.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Fill<TColor>(this Image<TColor> source, TColor color, Region region)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Fill(new SolidBrush<TColor>(color), region);
}
}
}

119
src/ImageSharp.Drawing/Paths/BezierLineSegment.cs

@ -1,119 +0,0 @@
// <copyright file="BezierLineSegment.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Paths
{
using System.Numerics;
/// <summary>
/// Represents a line segment that conistst of control points that will be rendered as a cubic bezier curve
/// </summary>
/// <seealso cref="ImageSharp.Drawing.Paths.ILineSegment" />
public class BezierLineSegment : ILineSegment
{
/// <summary>
/// The segments per curve.
/// code for this taken from <see href="http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/"/>
/// </summary>
private const int SegmentsPerCurve = 50;
/// <summary>
/// The line points.
/// </summary>
private readonly Vector2[] linePoints;
/// <summary>
/// Initializes a new instance of the <see cref="BezierLineSegment"/> class.
/// </summary>
/// <param name="points">The points.</param>
public BezierLineSegment(params Vector2[] points)
{
Guard.NotNull(points, nameof(points));
Guard.MustBeGreaterThanOrEqualTo(points.Length, 4, nameof(points));
this.linePoints = this.GetDrawingPoints(points);
}
/// <summary>
/// Returns the current <see cref="ILineSegment" /> a simple linear path.
/// </summary>
/// <returns>
/// Returns the current <see cref="ILineSegment" /> as simple linear path.
/// </returns>
public Vector2[] AsSimpleLinearPath()
{
return this.linePoints;
}
/// <summary>
/// Returns the drawing points along the line.
/// </summary>
/// <param name="controlPoints">The control points.</param>
/// <returns>
/// The <see cref="T:Vector2[]"/>.
/// </returns>
private Vector2[] GetDrawingPoints(Vector2[] controlPoints)
{
// TODO we need to calculate an optimal SegmentsPerCurve value
// depending on the calcualted length of this curve
int curveCount = (controlPoints.Length - 1) / 3;
int finalPointCount = (SegmentsPerCurve * curveCount) + 1; // we have SegmentsPerCurve for each curve plus the origon point;
Vector2[] drawingPoints = new Vector2[finalPointCount];
int position = 0;
int targetPoint = controlPoints.Length - 3;
for (int i = 0; i < targetPoint; i += 3)
{
Vector2 p0 = controlPoints[i];
Vector2 p1 = controlPoints[i + 1];
Vector2 p2 = controlPoints[i + 2];
Vector2 p3 = controlPoints[i + 3];
// only do this for the first end point. When i != 0, this coincides with the end point of the previous segment,
if (i == 0)
{
drawingPoints[position++] = this.CalculateBezierPoint(0, p0, p1, p2, p3);
}
for (int j = 1; j <= SegmentsPerCurve; j++)
{
float t = j / (float)SegmentsPerCurve;
drawingPoints[position++] = this.CalculateBezierPoint(t, p0, p1, p2, p3);
}
}
return drawingPoints;
}
/// <summary>
/// Calculates the bezier point along the line.
/// </summary>
/// <param name="t">The position within the line.</param>
/// <param name="p0">The p 0.</param>
/// <param name="p1">The p 1.</param>
/// <param name="p2">The p 2.</param>
/// <param name="p3">The p 3.</param>
/// <returns>
/// The <see cref="Vector2"/>.
/// </returns>
private Vector2 CalculateBezierPoint(float t, Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
{
float u = 1 - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
Vector2 p = uuu * p0; // first term
p += 3 * uu * t * p1; // second term
p += 3 * u * tt * p2; // third term
p += ttt * p3; // fourth term
return p;
}
}
}

21
src/ImageSharp.Drawing/Paths/ILineSegment.cs

@ -1,21 +0,0 @@
// <copyright file="ILineSegment.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Paths
{
using System.Numerics;
/// <summary>
/// Represents a simple path segment
/// </summary>
public interface ILineSegment
{
/// <summary>
/// Converts the <see cref="ILineSegment" /> into a simple linear path..
/// </summary>
/// <returns>Returns the current <see cref="ILineSegment" /> as simple linear path.</returns>
Vector2[] AsSimpleLinearPath(); // TODO move this over to ReadonlySpan<Vector2> once available
}
}

48
src/ImageSharp.Drawing/Paths/IPath.cs

@ -1,48 +0,0 @@
// <copyright file="IPath.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Paths
{
using System.Numerics;
/// <summary>
/// Represents a logic path that can be drawn
/// </summary>
public interface IPath : ILineSegment
{
/// <summary>
/// Gets the bounds enclosing the path
/// </summary>
/// <value>
/// The bounds.
/// </value>
RectangleF Bounds { get; }
/// <summary>
/// Gets a value indicating whether this instance is closed.
/// </summary>
/// <value>
/// <c>true</c> if this instance is closed; otherwise, <c>false</c>.
/// </value>
bool IsClosed { get; }
/// <summary>
/// Gets the length of the path
/// </summary>
/// <value>
/// The length.
/// </value>
float Length { get; }
/// <summary>
/// Calculates the distance along and away from the path for a specified point.
/// </summary>
/// <param name="point">The point along the path.</param>
/// <returns>
/// Returns details about the point and its distance away from the path.
/// </returns>
PointInfo Distance(Vector2 point);
}
}

516
src/ImageSharp.Drawing/Paths/InternalPath.cs

@ -1,516 +0,0 @@
// <copyright file="InternalPath.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Paths
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
/// <summary>
/// Internal logic for integrating linear paths.
/// </summary>
internal class InternalPath
{
/// <summary>
/// The maximum vector
/// </summary>
private static readonly Vector2 MaxVector = new Vector2(float.MaxValue);
/// <summary>
/// The locker.
/// </summary>
private static readonly object Locker = new object();
/// <summary>
/// The points.
/// </summary>
private readonly Vector2[] points;
/// <summary>
/// The closed path.
/// </summary>
private readonly bool closedPath;
/// <summary>
/// The total distance.
/// </summary>
private readonly Lazy<float> totalDistance;
/// <summary>
/// The constant.
/// </summary>
private float[] constant;
/// <summary>
/// The multiples.
/// </summary>
private float[] multiple;
/// <summary>
/// The distances.
/// </summary>
private float[] distance;
/// <summary>
/// The calculated.
/// </summary>
private bool calculated = false;
/// <summary>
/// Initializes a new instance of the <see cref="InternalPath"/> class.
/// </summary>
/// <param name="segments">The segments.</param>
/// <param name="isClosedPath">if set to <c>true</c> [is closed path].</param>
internal InternalPath(ILineSegment[] segments, bool isClosedPath)
: this(Simplify(segments), isClosedPath)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="InternalPath" /> class.
/// </summary>
/// <param name="segment">The segment.</param>
/// <param name="isClosedPath">if set to <c>true</c> [is closed path].</param>
internal InternalPath(ILineSegment segment, bool isClosedPath)
: this(segment.AsSimpleLinearPath(), isClosedPath)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="InternalPath" /> class.
/// </summary>
/// <param name="points">The points.</param>
/// <param name="isClosedPath">if set to <c>true</c> [is closed path].</param>
internal InternalPath(Vector2[] points, bool isClosedPath)
{
this.points = points;
this.closedPath = isClosedPath;
float minX = this.points.Min(x => x.X);
float maxX = this.points.Max(x => x.X);
float minY = this.points.Min(x => x.Y);
float maxY = this.points.Max(x => x.Y);
this.Bounds = new RectangleF(minX, minY, maxX - minX, maxY - minY);
this.totalDistance = new Lazy<float>(this.CalculateLength);
}
/// <summary>
/// Gets the bounds.
/// </summary>
/// <value>
/// The bounds.
/// </value>
public RectangleF Bounds
{
get;
}
/// <summary>
/// Gets the length.
/// </summary>
/// <value>
/// The length.
/// </value>
public float Length => this.totalDistance.Value;
/// <summary>
/// Gets the points.
/// </summary>
/// <value>
/// The points.
/// </value>
internal Vector2[] Points => this.points;
/// <summary>
/// Calculates the distance from the path.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>Returns the distance from the path</returns>
public PointInfo DistanceFromPath(Vector2 point)
{
this.CalculateConstants();
PointInfoInternal internalInfo = default(PointInfoInternal);
internalInfo.DistanceSquared = float.MaxValue; // Set it to max so that CalculateShorterDistance can reduce it back down
int polyCorners = this.points.Length;
if (!this.closedPath)
{
polyCorners -= 1;
}
int closestPoint = 0;
for (int i = 0; i < polyCorners; i++)
{
int next = i + 1;
if (this.closedPath && next == polyCorners)
{
next = 0;
}
if (this.CalculateShorterDistance(this.points[i], this.points[next], point, ref internalInfo))
{
closestPoint = i;
}
}
return new PointInfo
{
DistanceAlongPath = this.distance[closestPoint] + Vector2.Distance(this.points[closestPoint], point),
DistanceFromPath = (float)Math.Sqrt(internalInfo.DistanceSquared),
SearchPoint = point,
ClosestPointOnPath = internalInfo.PointOnLine
};
}
/// <summary>
/// Based on a line described by <paramref name="start" /> and <paramref name="end" />
/// populate a buffer for all points on the path that the line intersects.
/// </summary>
/// <param name="start">The start.</param>
/// <param name="end">The end.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="count">The count.</param>
/// <param name="offset">The offset.</param>
/// <returns>number iof intersections hit</returns>
public int FindIntersections(Vector2 start, Vector2 end, Vector2[] buffer, int count, int offset)
{
int polyCorners = this.points.Length;
if (!this.closedPath)
{
polyCorners -= 1;
}
int position = 0;
for (int i = 0; i < polyCorners && count > 0; i++)
{
int next = i + 1;
if (this.closedPath && next == polyCorners)
{
next = 0;
}
Vector2 point = FindIntersection(this.points[i], this.points[next], start, end);
if (point != MaxVector)
{
buffer[position + offset] = point;
position++;
count--;
}
}
return position;
}
/// <summary>
/// Determines if the specified point is inside or outside the path.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>Returns true if the point is inside the closed path.</returns>
public bool PointInPolygon(Vector2 point)
{
// You can only be inside a path if its "closed"
if (!this.closedPath)
{
return false;
}
if (!this.Bounds.Contains(point.X, point.Y))
{
return false;
}
this.CalculateConstants();
Vector2[] poly = this.points;
int polyCorners = poly.Length;
int j = polyCorners - 1;
bool oddNodes = false;
for (int i = 0; i < polyCorners; i++)
{
if ((poly[i].Y < point.Y && poly[j].Y >= point.Y)
|| (poly[j].Y < point.Y && poly[i].Y >= point.Y))
{
oddNodes ^= (point.Y * this.multiple[i]) + this.constant[i] < point.X;
}
j = i;
}
return oddNodes;
}
/// <summary>
/// Determins if the bounding box for 2 lines
/// described by <paramref name="line1Start" /> and <paramref name="line1End" />
/// and <paramref name="line2Start" /> and <paramref name="line2End" /> overlap.
/// </summary>
/// <param name="line1Start">The line1 start.</param>
/// <param name="line1End">The line1 end.</param>
/// <param name="line2Start">The line2 start.</param>
/// <param name="line2End">The line2 end.</param>
/// <returns>Returns true it the bounding box of the 2 lines intersect</returns>
private static bool BoundingBoxesIntersect(Vector2 line1Start, Vector2 line1End, Vector2 line2Start, Vector2 line2End)
{
Vector2 topLeft1 = Vector2.Min(line1Start, line1End);
Vector2 bottomRight1 = Vector2.Max(line1Start, line1End);
Vector2 topLeft2 = Vector2.Min(line2Start, line2End);
Vector2 bottomRight2 = Vector2.Max(line2Start, line2End);
float left1 = topLeft1.X;
float right1 = bottomRight1.X;
float top1 = topLeft1.Y;
float bottom1 = bottomRight1.Y;
float left2 = topLeft2.X;
float right2 = bottomRight2.X;
float top2 = topLeft2.Y;
float bottom2 = bottomRight2.Y;
return left1 <= right2 && right1 >= left2
&&
top1 <= bottom2 && bottom1 >= top2;
}
/// <summary>
/// Finds the point on line described by <paramref name="line1Start" /> and <paramref name="line1End" />
/// that intersects with line described by <paramref name="line2Start" /> and <paramref name="line2End" />
/// </summary>
/// <param name="line1Start">The line1 start.</param>
/// <param name="line1End">The line1 end.</param>
/// <param name="line2Start">The line2 start.</param>
/// <param name="line2End">The line2 end.</param>
/// <returns>
/// A <see cref="Vector2"/> describing the point that the 2 lines cross or <see cref="MaxVector"/> if they do not.
/// </returns>
private static Vector2 FindIntersection(Vector2 line1Start, Vector2 line1End, Vector2 line2Start, Vector2 line2End)
{
// do bounding boxes overlap, if not then the lines can't and return fast.
if (!BoundingBoxesIntersect(line1Start, line1End, line2Start, line2End))
{
return MaxVector;
}
Vector2 line1Diff = line1End - line1Start;
Vector2 line2Diff = line2End - line2Start;
Vector2 point;
if (line1Diff.X == 0)
{
float slope = line2Diff.Y / line2Diff.X;
float yinter = line2Start.Y - (slope * line2Start.X);
float y = (line1Start.X * slope) + yinter;
point = new Vector2(line1Start.X, y);
// horizontal and vertical lines
}
else if (line2Diff.X == 0)
{
float slope = line1Diff.Y / line1Diff.X;
float yinter = line1Start.Y - (slope * line1Start.X);
float y = (line2Start.X * slope) + yinter;
point = new Vector2(line2Start.X, y);
// horizontal and vertical lines
}
else
{
float slope1 = line1Diff.Y / line1Diff.X;
float slope2 = line2Diff.Y / line2Diff.X;
float yinter1 = line1Start.Y - (slope1 * line1Start.X);
float yinter2 = line2Start.Y - (slope2 * line2Start.X);
if (slope1 == slope2 && yinter1 != yinter2)
{
return MaxVector;
}
float x = (yinter2 - yinter1) / (slope1 - slope2);
float y = (slope1 * x) + yinter1;
point = new Vector2(x, y);
}
if (BoundingBoxesIntersect(line1Start, line1End, point, point))
{
return point;
}
else if (BoundingBoxesIntersect(line2Start, line2End, point, point))
{
return point;
}
return MaxVector;
}
/// <summary>
/// Simplifies the collection of segments.
/// </summary>
/// <param name="segments">The segments.</param>
/// <returns>
/// The <see cref="T:Vector2[]"/>.
/// </returns>
private static Vector2[] Simplify(ILineSegment[] segments)
{
List<Vector2> simplified = new List<Vector2>();
foreach (ILineSegment seg in segments)
{
simplified.AddRange(seg.AsSimpleLinearPath());
}
return simplified.ToArray();
}
/// <summary>
/// Returns the length of the path.
/// </summary>
/// <returns>
/// The <see cref="float"/>.
/// </returns>
private float CalculateLength()
{
float length = 0;
int polyCorners = this.points.Length;
if (!this.closedPath)
{
polyCorners -= 1;
}
for (int i = 0; i < polyCorners; i++)
{
int next = i + 1;
if (this.closedPath && next == polyCorners)
{
next = 0;
}
length += Vector2.Distance(this.points[i], this.points[next]);
}
return length;
}
/// <summary>
/// Calculate the constants.
/// </summary>
private void CalculateConstants()
{
// http://alienryderflex.com/polygon/ source for point in polygon logic
if (this.calculated)
{
return;
}
lock (Locker)
{
if (this.calculated)
{
return;
}
Vector2[] poly = this.points;
int polyCorners = poly.Length;
this.constant = new float[polyCorners];
this.multiple = new float[polyCorners];
this.distance = new float[polyCorners];
int i, j = polyCorners - 1;
this.distance[0] = 0;
for (i = 0; i < polyCorners; i++)
{
this.distance[j] = this.distance[i] + Vector2.Distance(poly[i], poly[j]);
if (poly[j].Y == poly[i].Y)
{
this.constant[i] = poly[i].X;
this.multiple[i] = 0;
}
else
{
Vector2 subtracted = poly[j] - poly[i];
this.constant[i] = (poly[i].X - ((poly[i].Y * poly[j].X) / subtracted.Y)) + ((poly[i].Y * poly[i].X) / subtracted.Y);
this.multiple[i] = subtracted.X / subtracted.Y;
}
j = i;
}
this.calculated = true;
}
}
/// <summary>
/// Calculate any shorter distances along the path.
/// </summary>
/// <param name="start">The start position.</param>
/// <param name="end">The end position.</param>
/// <param name="point">The current point.</param>
/// <param name="info">The info.</param>
/// <returns>
/// The <see cref="bool"/>.
/// </returns>
private bool CalculateShorterDistance(Vector2 start, Vector2 end, Vector2 point, ref PointInfoInternal info)
{
Vector2 diffEnds = end - start;
float lengthSquared = diffEnds.LengthSquared();
Vector2 diff = point - start;
Vector2 multiplied = diff * diffEnds;
float u = (multiplied.X + multiplied.Y) / lengthSquared;
if (u > 1)
{
u = 1;
}
else if (u < 0)
{
u = 0;
}
Vector2 multipliedByU = diffEnds * u;
Vector2 pointOnLine = start + multipliedByU;
Vector2 d = pointOnLine - point;
float dist = d.LengthSquared();
if (info.DistanceSquared > dist)
{
info.DistanceSquared = dist;
info.PointOnLine = pointOnLine;
return true;
}
return false;
}
/// <summary>
/// Contains information about the current point.
/// </summary>
private struct PointInfoInternal
{
/// <summary>
/// The distance squared.
/// </summary>
public float DistanceSquared;
/// <summary>
/// The point on the current line.
/// </summary>
public Vector2 PointOnLine;
}
}
}

55
src/ImageSharp.Drawing/Paths/LinearLineSegment.cs

@ -1,55 +0,0 @@
// <copyright file="LinearLineSegment.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Paths
{
using System.Linq;
using System.Numerics;
/// <summary>
/// Represents a series of control points that will be joined by straight lines
/// </summary>
/// <seealso cref="ILineSegment" />
public class LinearLineSegment : ILineSegment
{
/// <summary>
/// The collection of points.
/// </summary>
private readonly Vector2[] points;
/// <summary>
/// Initializes a new instance of the <see cref="LinearLineSegment"/> class.
/// </summary>
/// <param name="start">The start.</param>
/// <param name="end">The end.</param>
public LinearLineSegment(Vector2 start, Vector2 end)
: this(new[] { start, end })
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LinearLineSegment"/> class.
/// </summary>
/// <param name="points">The points.</param>
public LinearLineSegment(params Vector2[] points)
{
Guard.NotNull(points, nameof(points));
Guard.MustBeGreaterThanOrEqualTo(points.Count(), 2, nameof(points));
this.points = points;
}
/// <summary>
/// Converts the <see cref="ILineSegment" /> into a simple linear path..
/// </summary>
/// <returns>
/// Returns the current <see cref="ILineSegment" /> as simple linear path.
/// </returns>
public Vector2[] AsSimpleLinearPath()
{
return this.points;
}
}
}

51
src/ImageSharp.Drawing/Paths/Path.cs

@ -1,51 +0,0 @@
// <copyright file="Path.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Paths
{
using System.Numerics;
/// <summary>
/// A aggregate of <see cref="ILineSegment"/>s making a single logical path
/// </summary>
/// <seealso cref="IPath" />
public class Path : IPath
{
/// <summary>
/// The inner path.
/// </summary>
private readonly InternalPath innerPath;
/// <summary>
/// Initializes a new instance of the <see cref="Path"/> class.
/// </summary>
/// <param name="segment">The segment.</param>
public Path(params ILineSegment[] segment)
{
this.innerPath = new InternalPath(segment, false);
}
/// <inheritdoc />
public RectangleF Bounds => this.innerPath.Bounds;
/// <inheritdoc />
public bool IsClosed => false;
/// <inheritdoc />
public float Length => this.innerPath.Length;
/// <inheritdoc />
public Vector2[] AsSimpleLinearPath()
{
return this.innerPath.Points;
}
/// <inheritdoc />
public PointInfo Distance(Vector2 point)
{
return this.innerPath.DistanceFromPath(point);
}
}
}

35
src/ImageSharp.Drawing/Paths/PointInfo.cs

@ -1,35 +0,0 @@
// <copyright file="PointInfo.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Paths
{
using System.Numerics;
/// <summary>
/// Returns meta data about the nearest point on a path from a vector
/// </summary>
public struct PointInfo
{
/// <summary>
/// The search point
/// </summary>
public Vector2 SearchPoint;
/// <summary>
/// The distance along path <see cref="ClosestPointOnPath"/> is away from the start of the path
/// </summary>
public float DistanceAlongPath;
/// <summary>
/// The distance <see cref="SearchPoint"/> is away from <see cref="ClosestPointOnPath"/>.
/// </summary>
public float DistanceFromPath;
/// <summary>
/// The closest point to <see cref="SearchPoint"/> that lies on the path.
/// </summary>
public Vector2 ClosestPointOnPath;
}
}

9
src/ImageSharp.Drawing/Pens/Pen{TColor}.cs

@ -9,7 +9,6 @@ namespace ImageSharp.Drawing.Pens
using System.Numerics;
using ImageSharp.Drawing.Brushes;
using ImageSharp.Drawing.Paths;
using Processors;
/// <summary>
@ -145,10 +144,10 @@ namespace ImageSharp.Drawing.Pens
this.brush.Dispose();
}
public override ColoredPointInfo<TColor> GetColor(PointInfo info)
public override ColoredPointInfo<TColor> GetColor(int x, int y, PointInfo info)
{
var result = default(ColoredPointInfo<TColor>);
result.Color = this.brush.GetColor(info.SearchPoint);
result.Color = this.brush[x, y];
if (info.DistanceFromPath < this.halfWidth)
{
@ -198,7 +197,7 @@ namespace ImageSharp.Drawing.Pens
this.brush.Dispose();
}
public override ColoredPointInfo<TColor> GetColor(PointInfo info)
public override ColoredPointInfo<TColor> GetColor(int x, int y, PointInfo info)
{
var infoResult = default(ColoredPointInfo<TColor>);
infoResult.DistanceFromElement = float.MaxValue; // is really outside the element
@ -208,7 +207,7 @@ namespace ImageSharp.Drawing.Pens
// we can treat the DistanceAlongPath and DistanceFromPath as x,y coords for the pattern
// we need to calcualte the distance from the outside edge of the pattern
// and set them on the ColoredPointInfo<TColor> along with the color.
infoResult.Color = this.brush.GetColor(info.SearchPoint);
infoResult.Color = this.brush[x, y];
float distanceWAway = 0;

14
src/ImageSharp.Drawing/Pens/Processors/PenApplicator.cs

@ -6,7 +6,7 @@
namespace ImageSharp.Drawing.Processors
{
using System;
using Paths;
using System.Numerics;
/// <summary>
/// primitive that converts a <see cref="PointInfo"/> into a color and a distance away from the drawable part of the path.
@ -23,16 +23,18 @@ namespace ImageSharp.Drawing.Processors
/// </value>
public abstract RectangleF RequiredRegion { get; }
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <inheritdoc/>
public abstract void Dispose();
/// <summary>
/// Gets a <see cref="ColoredPointInfo{TColor}" /> from a point represented by a <see cref="PointInfo" />.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="info">The information to extract color details about.</param>
/// <returns>Returns the color details and distance from a solid bit of the line.</returns>
public abstract ColoredPointInfo<TColor> GetColor(PointInfo info);
/// <returns>
/// Returns the color details and distance from a solid bit of the line.
/// </returns>
public abstract ColoredPointInfo<TColor> GetColor(int x, int y, PointInfo info);
}
}

26
src/ImageSharp.Drawing/PointInfo.cs

@ -0,0 +1,26 @@
// <copyright file="PointInfo.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing
{
using System;
using System.Numerics;
/// <summary>
/// Returns details about how far away from the inside of a shape and the color the pixel could be.
/// </summary>
public struct PointInfo
{
/// <summary>
/// The distance along path
/// </summary>
public float DistanceAlongPath;
/// <summary>
/// The distance from path
/// </summary>
public float DistanceFromPath;
}
}

102
src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs

@ -6,13 +6,12 @@
namespace ImageSharp.Drawing.Processors
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using ImageSharp.Processing;
using Paths;
using Pens;
using Shapes;
using Rectangle = ImageSharp.Rectangle;
/// <summary>
@ -26,65 +25,48 @@ namespace ImageSharp.Drawing.Processors
private const float AntialiasFactor = 1f;
private const int PaddingFactor = 1; // needs to been the same or greater than AntialiasFactor
private readonly IPen<TColor> pen;
private readonly IPath[] paths;
private readonly RectangleF region;
private readonly GraphicsOptions options;
/// <summary>
/// Initializes a new instance of the <see cref="DrawPathProcessor{TColor}" /> class.
/// </summary>
/// <param name="pen">The pen.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
public DrawPathProcessor(IPen<TColor> pen, IShape shape, GraphicsOptions options)
: this(pen, shape.ToArray(), options)
/// <param name="pen">The details how to draw the outline/path.</param>
/// <param name="drawable">The details of the paths and outlines to draw.</param>
/// <param name="options">The drawing configuration options.</param>
public DrawPathProcessor(IPen<TColor> pen, Drawable drawable, GraphicsOptions options)
{
this.Path = drawable;
this.Pen = pen;
this.Options = options;
}
/// <summary>
/// Initializes a new instance of the <see cref="DrawPathProcessor{TColor}"/> class.
/// Gets the options.
/// </summary>
/// <param name="pen">The pen.</param>
/// <param name="path">The path.</param>
/// <param name="options">The options.</param>
public DrawPathProcessor(IPen<TColor> pen, IPath path, GraphicsOptions options)
: this(pen, new[] { path }, options)
{
}
/// <value>
/// The options.
/// </value>
public GraphicsOptions Options { get; }
/// <summary>
/// Initializes a new instance of the <see cref="DrawPathProcessor{TColor}" /> class.
/// Gets the pen.
/// </summary>
/// <param name="pen">The pen.</param>
/// <param name="paths">The paths.</param>
/// <param name="options">The options.</param>
public DrawPathProcessor(IPen<TColor> pen, IPath[] paths, GraphicsOptions options)
{
this.paths = paths;
this.pen = pen;
this.options = options;
if (paths.Length != 1)
{
var maxX = paths.Max(x => x.Bounds.Right);
var minX = paths.Min(x => x.Bounds.Left);
var maxY = paths.Max(x => x.Bounds.Bottom);
var minY = paths.Min(x => x.Bounds.Top);
/// <value>
/// The pen.
/// </value>
public IPen<TColor> Pen { get; }
this.region = new RectangleF(minX, minY, maxX - minX, maxY - minY);
}
else
{
this.region = paths[0].Bounds;
}
}
/// <summary>
/// Gets the path.
/// </summary>
/// <value>
/// The path.
/// </value>
public Drawable Path { get; }
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor> source, Rectangle sourceRectangle)
{
using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PenApplicator<TColor> applicator = this.pen.CreateApplicator(sourcePixels, this.region))
using (PenApplicator<TColor> applicator = this.Pen.CreateApplicator(sourcePixels, this.Path.Bounds))
{
var rect = RectangleF.Ceiling(applicator.RequiredRegion);
@ -119,19 +101,17 @@ namespace ImageSharp.Drawing.Processors
minY,
maxY,
this.ParallelOptions,
y =>
(int y) =>
{
int offsetY = y - polyStartY;
var currentPoint = default(Vector2);
for (int x = minX; x < maxX; x++)
{
// TODO add find intersections code to skip and scan large regions of this.
int offsetX = x - startX;
currentPoint.X = offsetX;
currentPoint.Y = offsetY;
var dist = this.Closest(currentPoint);
var info = this.Path.GetPointInfo(offsetX, offsetY);
var color = applicator.GetColor(dist);
var color = applicator.GetColor(offsetX, offsetY, info);
var opacity = this.Opacity(color.DistanceFromElement);
@ -154,31 +134,13 @@ namespace ImageSharp.Drawing.Processors
}
}
private PointInfo Closest(Vector2 point)
{
PointInfo result = default(PointInfo);
float distance = float.MaxValue;
for (int i = 0; i < this.paths.Length; i++)
{
var p = this.paths[i].Distance(point);
if (p.DistanceFromPath < distance)
{
distance = p.DistanceFromPath;
result = p;
}
}
return result;
}
private float Opacity(float distance)
{
if (distance <= 0)
{
return 1;
}
else if (this.options.Antialias && distance < AntialiasFactor)
else if (this.Options.Antialias && distance < AntialiasFactor)
{
return 1 - (distance / AntialiasFactor);
}

7
src/ImageSharp.Drawing/Processors/FillProcessor.cs

@ -71,17 +71,12 @@ namespace ImageSharp.Drawing.Processors
y =>
{
int offsetY = y - startY;
Vector2 currentPoint = default(Vector2);
for (int x = minX; x < maxX; x++)
{
int offsetX = x - startX;
int offsetColorX = x - minX;
currentPoint.X = offsetX;
currentPoint.Y = offsetY;
Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4();
Vector4 sourceVector = applicator.GetColor(currentPoint).ToVector4();
Vector4 sourceVector = applicator[offsetX, offsetY].ToVector4();
Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, 1);

225
src/ImageSharp.Drawing/Processors/FillShapeProcessor.cs → src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs

@ -1,4 +1,4 @@
// <copyright file="FillShapeProcessor.cs" company="James Jackson-South">
// <copyright file="FillRegionProcessor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -11,45 +11,58 @@ namespace ImageSharp.Drawing.Processors
using System.Threading.Tasks;
using Drawing;
using ImageSharp.Processing;
using Shapes;
using Rectangle = ImageSharp.Rectangle;
/// <summary>
/// Usinf a brsuh and a shape fills shape with contents of brush the
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <seealso cref="ImageSharp.Processing.ImageProcessor{TColor}" />
public class FillShapeProcessor<TColor> : ImageProcessor<TColor>
public class FillRegionProcessor<TColor> : ImageProcessor<TColor>
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
private const float AntialiasFactor = 1f;
private const int DrawPadding = 1;
private readonly IBrush<TColor> fillColor;
private readonly IShape poly;
private readonly GraphicsOptions options;
/// <summary>
/// Initializes a new instance of the <see cref="FillShapeProcessor{TColor}"/> class.
/// Initializes a new instance of the <see cref="FillRegionProcessor{TColor}" /> class.
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="shape">The shape.</param>
/// <param name="options">The options.</param>
public FillShapeProcessor(IBrush<TColor> brush, IShape shape, GraphicsOptions options)
/// <param name="brush">The details how to fill the region of interest.</param>
/// <param name="region">The region of interest to be filled.</param>
/// <param name="options">The configuration options.</param>
public FillRegionProcessor(IBrush<TColor> brush, Region region, GraphicsOptions options)
{
this.poly = shape;
this.fillColor = brush;
this.options = options;
this.Region = region;
this.Brush = brush;
this.Options = options;
}
/// <summary>
/// Gets the brush.
/// </summary>
public IBrush<TColor> Brush { get; }
/// <summary>
/// Gets the region that this processor applies to.
/// </summary>
public Region Region { get; }
/// <summary>
/// Gets the options.
/// </summary>
/// <value>
/// The options.
/// </value>
public GraphicsOptions Options { get; }
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor> source, Rectangle sourceRectangle)
{
Rectangle rect = RectangleF.Ceiling(this.poly.Bounds); // rounds the points out away from the center
Rectangle rect = this.Region.Bounds;
int polyStartY = rect.Y - DrawPadding;
int polyEndY = rect.Bottom + DrawPadding;
int startX = rect.X - DrawPadding;
int endX = rect.Right + DrawPadding;
int polyStartY = sourceRectangle.Y - DrawPadding;
int polyEndY = sourceRectangle.Bottom + DrawPadding;
int startX = sourceRectangle.X - DrawPadding;
int endX = sourceRectangle.Right + DrawPadding;
int minX = Math.Max(sourceRectangle.Left, startX);
int maxX = Math.Min(sourceRectangle.Right - 1, endX);
@ -62,53 +75,60 @@ namespace ImageSharp.Drawing.Processors
minY = Math.Max(0, minY);
maxY = Math.Min(source.Height, maxY);
ArrayPool<Vector2> arrayPool = ArrayPool<Vector2>.Shared;
ArrayPool<float> arrayPool = ArrayPool<float>.Shared;
int maxIntersections = this.poly.MaxIntersections;
int maxIntersections = this.Region.MaxIntersections;
using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (BrushApplicator<TColor> applicator = this.fillColor.CreateApplicator(sourcePixels, rect))
using (BrushApplicator<TColor> applicator = this.Brush.CreateApplicator(sourcePixels, rect))
{
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
(int y) =>
{
Vector2[] buffer = arrayPool.Rent(maxIntersections);
float[] buffer = arrayPool.Rent(maxIntersections);
try
{
Vector2 left = new Vector2(startX, y);
Vector2 right = new Vector2(endX, y);
float right = endX;
// foreach line we get all the points where this line crosses the polygon
int pointsFound = this.poly.FindIntersections(left, right, buffer, maxIntersections, 0);
int pointsFound = this.Region.ScanY(y, buffer, maxIntersections, 0);
if (pointsFound == 0)
{
// nothign on this line skip
return;
}
QuickSortX(buffer, pointsFound);
if (pointsFound == 1 && maxIntersections > 1)
{
// we must have clipped a corner lets just duplicate it into point 2 and continue :)
buffer[1] = buffer[0];
pointsFound++;
}
if (pointsFound % 2 == 1)
{
// we seem to have just clipped a corner lets just skip it
return;
}
QuickSort(buffer, pointsFound);
int currentIntersection = 0;
float nextPoint = buffer[0].X;
float nextPoint = buffer[0];
float lastPoint = float.MinValue;
bool isInside = false;
// every odd point is the start of a line
Vector2 currentPoint = default(Vector2);
for (int x = minX; x < maxX; x++)
{
currentPoint.X = x;
currentPoint.Y = y;
if (!isInside)
{
if (x < (nextPoint - DrawPadding) && x > (lastPoint + DrawPadding))
{
if (nextPoint == right.X)
if (nextPoint == right)
{
// we are in the ends run skip it
x = maxX;
@ -129,11 +149,11 @@ namespace ImageSharp.Drawing.Processors
lastPoint = nextPoint;
if (currentIntersection == pointsFound)
{
nextPoint = right.X;
nextPoint = right;
}
else
{
nextPoint = buffer[currentIntersection].X;
nextPoint = buffer[currentIntersection];
// double point from a corner flip the bit back and move on again
if (nextPoint == lastPoint)
@ -143,11 +163,11 @@ namespace ImageSharp.Drawing.Processors
currentIntersection++;
if (currentIntersection == pointsFound)
{
nextPoint = right.X;
nextPoint = right;
}
else
{
nextPoint = buffer[currentIntersection].X;
nextPoint = buffer[currentIntersection];
}
}
}
@ -158,7 +178,7 @@ namespace ImageSharp.Drawing.Processors
float opacity = 1;
if (!isInside && !onCorner)
{
if (this.options.Antialias)
if (this.Options.Antialias)
{
float distance = float.MaxValue;
if (x == lastPoint || x == nextPoint)
@ -192,7 +212,7 @@ namespace ImageSharp.Drawing.Processors
if (opacity > Constants.Epsilon)
{
Vector4 backgroundVector = sourcePixels[x, y].ToVector4();
Vector4 sourceVector = applicator.GetColor(currentPoint).ToVector4();
Vector4 sourceVector = applicator[x, y].ToVector4();
Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);
finalColor.W = backgroundVector.W;
@ -209,49 +229,57 @@ namespace ImageSharp.Drawing.Processors
}
});
if (this.options.Antialias)
if (this.Options.Antialias)
{
// we only need to do the X can for antialiasing purposes
Parallel.For(
minX,
maxX,
this.ParallelOptions,
x =>
(int x) =>
{
Vector2[] buffer = arrayPool.Rent(maxIntersections);
float[] buffer = arrayPool.Rent(maxIntersections);
try
{
Vector2 left = new Vector2(x, polyStartY);
Vector2 right = new Vector2(x, polyEndY);
float left = polyStartY;
float right = polyEndY;
// foreach line we get all the points where this line crosses the polygon
int pointsFound = this.poly.FindIntersections(left, right, buffer, maxIntersections, 0);
int pointsFound = this.Region.ScanX(x, buffer, maxIntersections, 0);
if (pointsFound == 0)
{
// nothign on this line skip
return;
}
QuickSortY(buffer, pointsFound);
if (pointsFound == 1 && maxIntersections > 1)
{
// we must have clipped a corner lets just duplicate it into point 2 and continue :)
buffer[1] = buffer[0];
pointsFound++;
}
if (pointsFound % 2 == 1)
{
// we seem to have just clipped a corner lets just skip it
return;
}
QuickSort(buffer, pointsFound);
int currentIntersection = 0;
float nextPoint = buffer[0].Y;
float lastPoint = left.Y;
float nextPoint = buffer[0];
float lastPoint = left;
bool isInside = false;
// every odd point is the start of a line
Vector2 currentPoint = default(Vector2);
for (int y = minY; y < maxY; y++)
{
currentPoint.X = x;
currentPoint.Y = y;
if (!isInside)
{
if (y < (nextPoint - DrawPadding) && y > (lastPoint + DrawPadding))
{
if (nextPoint == right.Y)
if (nextPoint == right)
{
// we are in the ends run skip it
y = maxY;
@ -266,7 +294,7 @@ namespace ImageSharp.Drawing.Processors
{
if (y < nextPoint - DrawPadding)
{
if (nextPoint == right.Y)
if (nextPoint == right)
{
// we are in the ends run skip it
y = maxY;
@ -286,11 +314,11 @@ namespace ImageSharp.Drawing.Processors
lastPoint = nextPoint;
if (currentIntersection == pointsFound)
{
nextPoint = right.Y;
nextPoint = right;
}
else
{
nextPoint = buffer[currentIntersection].Y;
nextPoint = buffer[currentIntersection];
// double point from a corner flip the bit back and move on again
if (nextPoint == lastPoint)
@ -300,11 +328,11 @@ namespace ImageSharp.Drawing.Processors
currentIntersection++;
if (currentIntersection == pointsFound)
{
nextPoint = right.Y;
nextPoint = right;
}
else
{
nextPoint = buffer[currentIntersection].Y;
nextPoint = buffer[currentIntersection];
}
}
}
@ -315,7 +343,7 @@ namespace ImageSharp.Drawing.Processors
float opacity = 1;
if (!isInside && !onCorner)
{
if (this.options.Antialias)
if (this.Options.Antialias)
{
float distance = float.MaxValue;
if (y == lastPoint || y == nextPoint)
@ -350,8 +378,7 @@ namespace ImageSharp.Drawing.Processors
if (opacity > Constants.Epsilon && opacity < 1)
{
Vector4 backgroundVector = sourcePixels[x, y].ToVector4();
Vector4 sourceVector = applicator.GetColor(currentPoint).ToVector4();
Vector4 sourceVector = applicator[x, y].ToVector4();
Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);
finalColor.W = backgroundVector.W;
@ -370,76 +397,32 @@ namespace ImageSharp.Drawing.Processors
}
}
private static void Swap(Vector2[] data, int left, int right)
private static void Swap(float[] data, int left, int right)
{
Vector2 tmp = data[left];
float tmp = data[left];
data[left] = data[right];
data[right] = tmp;
}
private static void QuickSortY(Vector2[] data, int size)
{
int hi = Math.Min(data.Length - 1, size - 1);
QuickSortY(data, 0, hi);
}
private static void QuickSortY(Vector2[] data, int lo, int hi)
{
if (lo < hi)
{
int p = PartitionY(data, lo, hi);
QuickSortY(data, lo, p);
QuickSortY(data, p + 1, hi);
}
}
private static void QuickSortX(Vector2[] data, int size)
private static void QuickSort(float[] data, int size)
{
int hi = Math.Min(data.Length - 1, size - 1);
QuickSortX(data, 0, hi);
QuickSort(data, 0, hi);
}
private static void QuickSortX(Vector2[] data, int lo, int hi)
private static void QuickSort(float[] data, int lo, int hi)
{
if (lo < hi)
{
int p = PartitionX(data, lo, hi);
QuickSortX(data, lo, p);
QuickSortX(data, p + 1, hi);
}
}
private static int PartitionX(Vector2[] data, int lo, int hi)
{
float pivot = data[lo].X;
int i = lo - 1;
int j = hi + 1;
while (true)
{
do
{
i = i + 1;
}
while (data[i].X < pivot && i < hi);
do
{
j = j - 1;
}
while (data[j].X > pivot && j > lo);
if (i >= j)
{
return j;
}
Swap(data, i, j);
int p = Partition(data, lo, hi);
QuickSort(data, lo, p);
QuickSort(data, p + 1, hi);
}
}
private static int PartitionY(Vector2[] data, int lo, int hi)
private static int Partition(float[] data, int lo, int hi)
{
float pivot = data[lo].Y;
float pivot = data[lo];
int i = lo - 1;
int j = hi + 1;
while (true)
@ -448,13 +431,13 @@ namespace ImageSharp.Drawing.Processors
{
i = i + 1;
}
while (data[i].Y < pivot && i < hi);
while (data[i] < pivot && i < hi);
do
{
j = j - 1;
}
while (data[j].Y > pivot && j > lo);
while (data[j] > pivot && j > lo);
if (i >= j)
{

46
src/ImageSharp.Drawing/Region.cs

@ -0,0 +1,46 @@
// <copyright file="Region.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing
{
/// <summary>
/// Represents a region of an image.
/// </summary>
public abstract class Region
{
/// <summary>
/// Gets the maximum number of intersections to could be returned.
/// </summary>
public abstract int MaxIntersections { get; }
/// <summary>
/// Gets the bounding box that entirly surrounds this region.
/// </summary>
/// <remarks>
/// This should always contains all possible points returned from eather <see cref="ScanX(int, float[], int, int)"/> or <see cref="ScanY(int, float[], int, int)"/>.
/// </remarks>
public abstract Rectangle Bounds { get; }
/// <summary>
/// Scans the X axis for intersections.
/// </summary>
/// <param name="x">The position along the X axies to find intersections.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="length">The length.</param>
/// <param name="offset">The offset.</param>
/// <returns>The number of intersections found.</returns>
public abstract int ScanX(int x, float[] buffer, int length, int offset);
/// <summary>
/// Scans the Y axis for intersections.
/// </summary>
/// <param name="y">The position along the y axis to find intersections.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="length">The length.</param>
/// <param name="offset">The offset.</param>
/// <returns>The number of intersections found.</returns>
public abstract int ScanY(int y, float[] buffer, int length, int offset);
}
}

93
src/ImageSharp.Drawing/Shapes/BezierPolygon.cs

@ -1,93 +0,0 @@
// <copyright file="BezierPolygon.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes
{
using System.Collections;
using System.Collections.Generic;
using System.Numerics;
using Paths;
/// <summary>
/// Represents a polygon made up exclusivly of a single close cubic Bezier curve.
/// </summary>
public sealed class BezierPolygon : IShape
{
private Polygon innerPolygon;
/// <summary>
/// Initializes a new instance of the <see cref="BezierPolygon"/> class.
/// </summary>
/// <param name="points">The points.</param>
public BezierPolygon(params Vector2[] points)
{
this.innerPolygon = new Polygon(new BezierLineSegment(points));
}
/// <summary>
/// Gets the bounding box of this shape.
/// </summary>
/// <value>
/// The bounds.
/// </value>
public RectangleF Bounds => this.innerPolygon.Bounds;
/// <summary>
/// Gets the maximum number intersections that a shape can have when testing a line.
/// </summary>
/// <value>
/// The maximum intersections.
/// </value>
public int MaxIntersections => this.innerPolygon.MaxIntersections;
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The distance from the shape.
/// </returns>
public float Distance(Vector2 point) => this.innerPolygon.Distance(point);
/// <summary>
/// Based on a line described by <paramref name="start"/> and <paramref name="end"/>
/// populate a buffer for all points on the polygon that the line intersects.
/// </summary>
/// <param name="start">The start point of the line.</param>
/// <param name="end">The end point of the line.</param>
/// <param name="buffer">The buffer that will be populated with intersections.</param>
/// <param name="count">The count.</param>
/// <param name="offset">The offset.</param>
/// <returns>
/// The number of intersections populated into the buffer.
/// </returns>
public int FindIntersections(Vector2 start, Vector2 end, Vector2[] buffer, int count, int offset)
{
return this.innerPolygon.FindIntersections(start, end, buffer, count, offset);
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// An enumerator that can be used to iterate through the collection.
/// </returns>
public IEnumerator<IPath> GetEnumerator()
{
return this.innerPolygon.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this.innerPolygon.GetEnumerator();
}
}
}

246
src/ImageSharp.Drawing/Shapes/ComplexPolygon.cs

@ -1,246 +0,0 @@
// <copyright file="ComplexPolygon.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Paths;
using PolygonClipper;
/// <summary>
/// Represents a complex polygon made up of one or more outline
/// polygons and one or more holes to punch out of them.
/// </summary>
/// <seealso cref="ImageSharp.Drawing.Shapes.IShape" />
public sealed class ComplexPolygon : IShape
{
private const float ClipperScaleFactor = 100f;
private IShape[] shapes;
private IEnumerable<IPath> paths;
/// <summary>
/// Initializes a new instance of the <see cref="ComplexPolygon"/> class.
/// </summary>
/// <param name="outline">The outline.</param>
/// <param name="holes">The holes.</param>
public ComplexPolygon(IShape outline, params IShape[] holes)
: this(new[] { outline }, holes)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ComplexPolygon"/> class.
/// </summary>
/// <param name="outlines">The outlines.</param>
/// <param name="holes">The holes.</param>
public ComplexPolygon(IShape[] outlines, IShape[] holes)
{
Guard.NotNull(outlines, nameof(outlines));
Guard.MustBeGreaterThanOrEqualTo(outlines.Length, 1, nameof(outlines));
this.MaxIntersections = this.FixAndSetShapes(outlines, holes);
float minX = this.shapes.Min(x => x.Bounds.Left);
float maxX = this.shapes.Max(x => x.Bounds.Right);
float minY = this.shapes.Min(x => x.Bounds.Top);
float maxY = this.shapes.Max(x => x.Bounds.Bottom);
this.Bounds = new RectangleF(minX, minY, maxX - minX, maxY - minY);
}
/// <summary>
/// Gets the bounding box of this shape.
/// </summary>
/// <value>
/// The bounds.
/// </value>
public RectangleF Bounds { get; }
/// <summary>
/// Gets the maximum number intersections that a shape can have when testing a line.
/// </summary>
/// <value>
/// The maximum intersections.
/// </value>
public int MaxIntersections { get; }
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// Returns the distance from thr shape to the point
/// </returns>
/// <remarks>
/// Due to the clipping we did during construction we know that out shapes do not overlap at there edges
/// therefore for apoint to be in more that one we must be in a hole of another, theoretically this could
/// then flip again to be in a outlin inside a hole inside an outline :)
/// </remarks>
float IShape.Distance(Vector2 point)
{
float dist = float.MaxValue;
bool inside = false;
foreach (IShape shape in this.shapes)
{
float d = shape.Distance(point);
if (d <= 0)
{
// we are inside a poly
d = -d; // flip the sign
inside ^= true; // flip the inside flag
}
if (d < dist)
{
dist = d;
}
}
if (inside)
{
return -dist;
}
return dist;
}
/// <summary>
/// Based on a line described by <paramref name="start"/> and <paramref name="end"/>
/// populate a buffer for all points on all the polygons, that make up this complex shape,
/// that the line intersects.
/// </summary>
/// <param name="start">The start point of the line.</param>
/// <param name="end">The end point of the line.</param>
/// <param name="buffer">The buffer that will be populated with intersections.</param>
/// <param name="count">The count.</param>
/// <param name="offset">The offset.</param>
/// <returns>
/// The number of intersections populated into the buffer.
/// </returns>
public int FindIntersections(Vector2 start, Vector2 end, Vector2[] buffer, int count, int offset)
{
int totalAdded = 0;
for (int i = 0; i < this.shapes.Length; i++)
{
int added = this.shapes[i].FindIntersections(start, end, buffer, count, offset);
count -= added;
offset += added;
totalAdded += added;
}
return totalAdded;
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// An enumerator that can be used to iterate through the collection.
/// </returns>
public IEnumerator<IPath> GetEnumerator()
{
return this.paths.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
private void AddPoints(Clipper clipper, IShape shape, PolyType polyType)
{
// if the path is already the shape use it directly and skip the path loop.
if (shape is IPath)
{
clipper.AddPath(
(IPath)shape,
polyType);
}
else
{
foreach (IPath path in shape)
{
clipper.AddPath(
path,
polyType);
}
}
}
private void AddPoints(Clipper clipper, IEnumerable<IShape> shapes, PolyType polyType)
{
foreach (IShape shape in shapes)
{
this.AddPoints(clipper, shape, polyType);
}
}
private void ExtractOutlines(PolyNode tree, List<IShape> shapes, List<IPath> paths)
{
if (tree.Contour.Any())
{
// if the source path is set then we clipper retained the full path intact thus we can freely
// use it and get any shape optimisations that are availible.
if (tree.SourcePath != null)
{
shapes.Add((IShape)tree.SourcePath);
paths.Add(tree.SourcePath);
}
else
{
// convert the Clipper Contour from scaled ints back down to the origional size (this is going to be lossy but not significantly)
Polygon polygon = new Polygon(new Paths.LinearLineSegment(tree.Contour.ToArray()));
shapes.Add(polygon);
paths.Add(polygon);
}
}
foreach (PolyNode c in tree.Children)
{
this.ExtractOutlines(c, shapes, paths);
}
}
private int FixAndSetShapes(IEnumerable<IShape> outlines, IEnumerable<IShape> holes)
{
Clipper clipper = new Clipper();
// add the outlines and the holes to clipper, scaling up from the float source to the int based system clipper uses
this.AddPoints(clipper, outlines, PolyType.Subject);
this.AddPoints(clipper, holes, PolyType.Clip);
PolyTree tree = clipper.Execute();
List<IShape> shapes = new List<IShape>();
List<IPath> paths = new List<IPath>();
// convert the 'tree' back to paths
this.ExtractOutlines(tree, shapes, paths);
this.shapes = shapes.ToArray();
this.paths = paths.ToArray();
int intersections = 0;
foreach (IShape s in this.shapes)
{
intersections += s.MaxIntersections;
}
return intersections;
}
}
}

56
src/ImageSharp.Drawing/Shapes/IShape.cs

@ -1,56 +0,0 @@
// <copyright file="IShape.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes
{
using System.Collections.Generic;
using System.Numerics;
using Paths;
/// <summary>
/// Represents a closed set of paths making up a single shape.
/// </summary>
public interface IShape : IEnumerable<IPath>
{
/// <summary>
/// Gets the bounding box of this shape.
/// </summary>
/// <value>
/// The bounds.
/// </value>
RectangleF Bounds { get; }
/// <summary>
/// Gets the maximum number intersections that a shape can have when testing a line.
/// </summary>
/// <value>
/// The maximum intersections.
/// </value>
int MaxIntersections { get; }
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// Returns the distance from the shape to the point
/// </returns>
float Distance(Vector2 point);
/// <summary>
/// Based on a line described by <paramref name="start"/> and <paramref name="end"/>
/// populate a buffer for all points on the polygon that the line intersects.
/// </summary>
/// <param name="start">The start point of the line.</param>
/// <param name="end">The end point of the line.</param>
/// <param name="buffer">The buffer that will be populated with intersections.</param>
/// <param name="count">The count.</param>
/// <param name="offset">The offset.</param>
/// <returns>
/// The number of intersections populated into the buffer.
/// </returns>
int FindIntersections(Vector2 start, Vector2 end, Vector2[] buffer, int count, int offset);
}
}

93
src/ImageSharp.Drawing/Shapes/LinearPolygon.cs

@ -1,93 +0,0 @@
// <copyright file="LinearPolygon.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes
{
using System.Collections;
using System.Collections.Generic;
using System.Numerics;
using Paths;
/// <summary>
/// Represents a polygon made up exclusivly of a single Linear path.
/// </summary>
public sealed class LinearPolygon : IShape
{
private Polygon innerPolygon;
/// <summary>
/// Initializes a new instance of the <see cref="LinearPolygon"/> class.
/// </summary>
/// <param name="points">The points.</param>
public LinearPolygon(params Vector2[] points)
{
this.innerPolygon = new Polygon(new LinearLineSegment(points));
}
/// <summary>
/// Gets the bounding box of this shape.
/// </summary>
/// <value>
/// The bounds.
/// </value>
public RectangleF Bounds => this.innerPolygon.Bounds;
/// <summary>
/// Gets the maximum number intersections that a shape can have when testing a line.
/// </summary>
/// <value>
/// The maximum intersections.
/// </value>
public int MaxIntersections
{
get
{
return this.innerPolygon.MaxIntersections;
}
}
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// Returns the distance from the shape to the point
/// </returns>
public float Distance(Vector2 point) => this.innerPolygon.Distance(point);
/// <summary>
/// Based on a line described by <paramref name="start"/> and <paramref name="end"/>
/// populate a buffer for all points on the polygon that the line intersects.
/// </summary>
/// <param name="start">The start point of the line.</param>
/// <param name="end">The end point of the line.</param>
/// <param name="buffer">The buffer that will be populated with intersections.</param>
/// <param name="count">The count.</param>
/// <param name="offset">The offset.</param>
/// <returns>
/// The number of intersections populated into the buffer.
/// </returns>
public int FindIntersections(Vector2 start, Vector2 end, Vector2[] buffer, int count, int offset)
{
return this.innerPolygon.FindIntersections(start, end, buffer, count, offset);
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// An enumerator that can be used to iterate through the collection.
/// </returns>
public IEnumerator<IPath> GetEnumerator() => this.innerPolygon.GetEnumerator();
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator() => this.innerPolygon.GetEnumerator();
}
}

156
src/ImageSharp.Drawing/Shapes/Polygon.cs

@ -1,156 +0,0 @@
// <copyright file="Polygon.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes
{
using System.Collections;
using System.Collections.Generic;
using System.Numerics;
using Paths;
/// <summary>
/// A shape made up of a single path made up of one of more <see cref="ILineSegment"/>s
/// </summary>
public sealed class Polygon : IShape, IPath
{
private readonly InternalPath innerPath;
private readonly IEnumerable<IPath> pathCollection;
/// <summary>
/// Initializes a new instance of the <see cref="Polygon"/> class.
/// </summary>
/// <param name="segments">The segments.</param>
public Polygon(params ILineSegment[] segments)
{
this.innerPath = new InternalPath(segments, true);
this.pathCollection = new[] { this };
}
/// <summary>
/// Initializes a new instance of the <see cref="Polygon" /> class.
/// </summary>
/// <param name="segment">The segment.</param>
public Polygon(ILineSegment segment)
{
this.innerPath = new InternalPath(segment, true);
this.pathCollection = new[] { this };
}
/// <summary>
/// Gets the bounding box of this shape.
/// </summary>
/// <value>
/// The bounds.
/// </value>
public RectangleF Bounds => this.innerPath.Bounds;
/// <summary>
/// Gets the length of the path
/// </summary>
/// <value>
/// The length.
/// </value>
public float Length => this.innerPath.Length;
/// <summary>
/// Gets a value indicating whether this instance is closed.
/// </summary>
/// <value>
/// <c>true</c> if this instance is closed; otherwise, <c>false</c>.
/// </value>
public bool IsClosed => true;
/// <summary>
/// Gets the maximum number intersections that a shape can have when testing a line.
/// </summary>
/// <value>
/// The maximum intersections.
/// </value>
public int MaxIntersections => this.innerPath.Points.Length;
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The distance of the point away from the shape
/// </returns>
public float Distance(Vector2 point)
{
bool isInside = this.innerPath.PointInPolygon(point);
float distance = this.innerPath.DistanceFromPath(point).DistanceFromPath;
if (isInside)
{
return -distance;
}
return distance;
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// An enumerator that can be used to iterate through the collection.
/// </returns>
public IEnumerator<IPath> GetEnumerator()
{
return this.pathCollection.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this.pathCollection.GetEnumerator();
}
/// <summary>
/// Calcualtes the distance along and away from the path for a specified point.
/// </summary>
/// <param name="point">The point along the path.</param>
/// <returns>
/// distance metadata about the point.
/// </returns>
PointInfo IPath.Distance(Vector2 point)
{
return this.innerPath.DistanceFromPath(point);
}
/// <summary>
/// Returns the current shape as a simple linear path.
/// </summary>
/// <returns>
/// Returns the current <see cref="ILineSegment" /> as simple linear path.
/// </returns>
public Vector2[] AsSimpleLinearPath()
{
return this.innerPath.Points;
}
/// <summary>
/// Based on a line described by <paramref name="start" /> and <paramref name="end" />
/// populate a buffer for all points on the polygon that the line intersects.
/// </summary>
/// <param name="start">The start point of the line.</param>
/// <param name="end">The end point of the line.</param>
/// <param name="buffer">The buffer that will be populated with intersections.</param>
/// <param name="count">The count.</param>
/// <param name="offset">The offset.</param>
/// <returns>
/// The number of intersections populated into the buffer.
/// </returns>
public int FindIntersections(Vector2 start, Vector2 end, Vector2[] buffer, int count, int offset)
{
return this.innerPath.FindIntersections(start, end, buffer, count, offset);
}
}
}

3860
src/ImageSharp.Drawing/Shapes/PolygonClipper/Clipper.cs

File diff suppressed because it is too large

31
src/ImageSharp.Drawing/Shapes/PolygonClipper/ClipperException.cs

@ -1,31 +0,0 @@
// <copyright file="ClipperException.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Clipper Exception
/// </summary>
/// <seealso cref="System.Exception" />
internal class ClipperException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="ClipperException"/> class.
/// </summary>
/// <param name="description">The description.</param>
public ClipperException(string description)
: base(description)
{
}
}
}

31
src/ImageSharp.Drawing/Shapes/PolygonClipper/Direction.cs

@ -1,31 +0,0 @@
// <copyright file="Direction.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ???
/// </summary>
internal enum Direction
{
/// <summary>
/// The right to left
/// </summary>
RightToLeft,
/// <summary>
/// The left to right
/// </summary>
LeftToRight
}
}

31
src/ImageSharp.Drawing/Shapes/PolygonClipper/EdgeSide.cs

@ -1,31 +0,0 @@
// <copyright file="EdgeSide.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal enum EdgeSide
{
/// <summary>
/// The left
/// </summary>
Left,
/// <summary>
/// The right
/// </summary>
Right
}
}

38
src/ImageSharp.Drawing/Shapes/PolygonClipper/IntersectNode.cs

@ -1,38 +0,0 @@
// <copyright file="IntersectNode.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal class IntersectNode
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The edge1
/// </summary>
internal TEdge Edge1;
/// <summary>
/// The edge2
/// </summary>
internal TEdge Edge2;
/// <summary>
/// The pt
/// </summary>
internal System.Numerics.Vector2 Pt;
#pragma warning restore SA1401 // Field must be private
}
}

48
src/ImageSharp.Drawing/Shapes/PolygonClipper/IntersectNodeSort.cs

@ -1,48 +0,0 @@
// <copyright file="IntersectNodeSort.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Compares <see cref="IntersectNode"/>s
/// </summary>
internal class IntersectNodeSort : IComparer<IntersectNode>
{
/// <summary>
/// Compares the specified node1.
/// </summary>
/// <param name="node1">The node1.</param>
/// <param name="node2">The node2.</param>
/// <returns>
/// 1 if node2 %gt; node1
/// -1 if node2 $lt; node1
/// 0 if same
/// </returns>
public int Compare(IntersectNode node1, IntersectNode node2)
{
float i = node2.Pt.Y - node1.Pt.Y;
if (i > 0)
{
return 1;
}
else if (i < 0)
{
return -1;
}
else
{
return 0;
}
}
}
}

38
src/ImageSharp.Drawing/Shapes/PolygonClipper/Join.cs

@ -1,38 +0,0 @@
// <copyright file="Join.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal class Join
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The out PT1
/// </summary>
internal OutPt OutPt1;
/// <summary>
/// The out PT2
/// </summary>
internal OutPt OutPt2;
/// <summary>
/// The off pt
/// </summary>
internal System.Numerics.Vector2 OffPt;
#pragma warning restore SA1401 // Field must be private
}
}

44
src/ImageSharp.Drawing/Shapes/PolygonClipper/LocalMinima.cs

@ -1,44 +0,0 @@
// <copyright file="LocalMinima.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal class LocalMinima
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The y
/// </summary>
internal float Y;
/// <summary>
/// The left bound
/// </summary>
internal TEdge LeftBound;
/// <summary>
/// The right bound
/// </summary>
internal TEdge RightBound;
/// <summary>
/// The next
/// </summary>
internal LocalMinima Next;
#pragma warning restore SA1401 // Field must be private
}
}

38
src/ImageSharp.Drawing/Shapes/PolygonClipper/Maxima.cs

@ -1,38 +0,0 @@
// <copyright file="Maxima.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal class Maxima
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The x
/// </summary>
internal float X;
/// <summary>
/// The next
/// </summary>
internal Maxima Next;
/// <summary>
/// The previous
/// </summary>
internal Maxima Prev;
#pragma warning restore SA1401 // Field must be private
}
}

43
src/ImageSharp.Drawing/Shapes/PolygonClipper/OutPt.cs

@ -1,43 +0,0 @@
// <copyright file="OutPt.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// ??
/// </summary>
internal class OutPt
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The index
/// </summary>
internal int Idx;
/// <summary>
/// The pt
/// </summary>
internal System.Numerics.Vector2 Pt;
/// <summary>
/// The next
/// </summary>
internal OutPt Next;
/// <summary>
/// The previous
/// </summary>
internal OutPt Prev;
#pragma warning restore SA1401 // Field must be private
}
}

64
src/ImageSharp.Drawing/Shapes/PolygonClipper/OutRec.cs

@ -1,64 +0,0 @@
// <copyright file="OutRec.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// OutRec: contains a path in the clipping solution. Edges in the AEL will
/// carry a pointer to an OutRec when they are part of the clipping solution.
/// </summary>
internal class OutRec
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The source path
/// </summary>
internal IPath SourcePath;
/// <summary>
/// The index
/// </summary>
internal int Idx;
/// <summary>
/// The is hole
/// </summary>
internal bool IsHole;
/// <summary>
/// The is open
/// </summary>
internal bool IsOpen;
/// <summary>
/// The first left
/// </summary>
internal OutRec FirstLeft;
/// <summary>
/// The PTS
/// </summary>
internal OutPt Pts;
/// <summary>
/// The bottom pt
/// </summary>
internal OutPt BottomPt;
/// <summary>
/// The poly node
/// </summary>
internal PolyNode PolyNode;
#pragma warning restore SA1401 // Field must be private
}
}

179
src/ImageSharp.Drawing/Shapes/PolygonClipper/PolyNode.cs

@ -1,179 +0,0 @@
// <copyright file="PolyNode.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Poly Node
/// </summary>
internal class PolyNode
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The polygon
/// </summary>
internal List<Vector2> Polygon = new List<Vector2>();
/// <summary>
/// The index
/// </summary>
internal int Index;
/// <summary>
/// The childs
/// </summary>
protected List<PolyNode> children = new List<PolyNode>();
private PolyNode parent;
#pragma warning restore SA1401 // Field must be private
/// <summary>
/// Gets the child count.
/// </summary>
/// <value>
/// The child count.
/// </value>
public int ChildCount
{
get { return this.children.Count; }
}
/// <summary>
/// Gets the contour.
/// </summary>
/// <value>
/// The contour.
/// </value>
public List<Vector2> Contour
{
get { return this.Polygon; }
}
/// <summary>
/// Gets the childs.
/// </summary>
/// <value>
/// The childs.
/// </value>
public List<PolyNode> Children
{
get { return this.children; }
}
/// <summary>
/// Gets or sets the parent.
/// </summary>
/// <value>
/// The parent.
/// </value>
public PolyNode Parent
{
get { return this.parent; }
internal set { this.parent = value; }
}
/// <summary>
/// Gets a value indicating whether this instance is hole.
/// </summary>
/// <value>
/// <c>true</c> if this instance is hole; otherwise, <c>false</c>.
/// </value>
public bool IsHole
{
get { return this.IsHoleNode(); }
}
/// <summary>
/// Gets or sets a value indicating whether this instance is open.
/// </summary>
/// <value>
/// <c>true</c> if this instance is open; otherwise, <c>false</c>.
/// </value>
public bool IsOpen { get; set; }
/// <summary>
/// Gets or sets the source path.
/// </summary>
/// <value>
/// The source path.
/// </value>
public IPath SourcePath { get; internal set; }
/// <summary>
/// Gets the next.
/// </summary>
/// <returns>The next node</returns>
public PolyNode GetNext()
{
if (this.children.Count > 0)
{
return this.children[0];
}
else
{
return this.GetNextSiblingUp();
}
}
/// <summary>
/// Adds the child.
/// </summary>
/// <param name="child">The child.</param>
internal void AddChild(PolyNode child)
{
int cnt = this.children.Count;
this.children.Add(child);
child.parent = this;
child.Index = cnt;
}
/// <summary>
/// Gets the next sibling up.
/// </summary>
/// <returns>The next sibling up</returns>
internal PolyNode GetNextSiblingUp()
{
if (this.parent == null)
{
return null;
}
else if (this.Index == this.parent.children.Count - 1)
{
return this.parent.GetNextSiblingUp();
}
else
{
return this.parent.Children[this.Index + 1];
}
}
/// <summary>
/// Determines whether [is hole node].
/// </summary>
/// <returns>
/// <c>true</c> if [is hole node]; otherwise, <c>false</c>.
/// </returns>
private bool IsHoleNode()
{
bool result = true;
PolyNode node = this.parent;
while (node != null)
{
result = !result;
node = node.parent;
}
return result;
}
}
}

81
src/ImageSharp.Drawing/Shapes/PolygonClipper/PolyTree.cs

@ -1,81 +0,0 @@
// <copyright file="PolyTree.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Poly Tree
/// </summary>
/// <seealso cref="ImageSharp.Drawing.Shapes.PolygonClipper.PolyNode" />
internal class PolyTree : PolyNode
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// All polys
/// </summary>
internal List<PolyNode> AllPolys = new List<PolyNode>();
#pragma warning restore SA1401 // Field must be private
/// <summary>
/// Gets the total.
/// </summary>
/// <value>
/// The total.
/// </value>
public int Total
{
get
{
int result = this.AllPolys.Count;
// with negative offsets, ignore the hidden outer polygon ...
if (result > 0 && this.Children[0] != this.AllPolys[0])
{
result--;
}
return result;
}
}
/// <summary>
/// Clears this instance.
/// </summary>
public void Clear()
{
for (int i = 0; i < this.AllPolys.Count; i++)
{
this.AllPolys[i] = null;
}
this.AllPolys.Clear();
this.Children.Clear();
}
/// <summary>
/// Gets the first.
/// </summary>
/// <returns>the first node</returns>
public PolyNode GetFirst()
{
if (this.Children.Count > 0)
{
return this.Children[0];
}
else
{
return null;
}
}
}
}

31
src/ImageSharp.Drawing/Shapes/PolygonClipper/PolyType.cs

@ -1,31 +0,0 @@
// <copyright file="PolyType.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Poly Type
/// </summary>
internal enum PolyType
{
/// <summary>
/// The subject
/// </summary>
Subject,
/// <summary>
/// The clip
/// </summary>
Clip
}
}

40
src/ImageSharp.Drawing/Shapes/PolygonClipper/README.md

@ -1,40 +0,0 @@
# Clipper
License details for code in this folder, this is code original written by **Angus Johnson**
The license header onthe original file which has now be split across multiple files in this folder.
```
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 6.4.0 *
* Date : 2 July 2015 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2015 *
* *
* License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
* http://www.boost.org/LICENSE_1_0.txt *
* *
* Attributions: *
* The code in this library is an extension of Bala Vatti's clipping algorithm: *
* "A generic solution to polygon clipping" *
* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
* http://portal.acm.org/citation.cfm?id=129906 *
* *
* Computer graphics and geometric modeling: implementation and algorithms *
* By Max K. Agoston *
* Springer; 1 edition (January 4, 2005) *
* http://books.google.com/books?q=vatti+clipping+agoston *
* *
* See also: *
* "Polygon Offsetting by Computing Winding Numbers" *
* Paper no. DETC2005-85513 pp. 565-575 *
* ASME 2005 International Design Engineering Technical Conferences *
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
* September 24-28, 2005 , Long Beach, California, USA *
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
* *
*******************************************************************************/
```

33
src/ImageSharp.Drawing/Shapes/PolygonClipper/Scanbeam.cs

@ -1,33 +0,0 @@
// <copyright file="Scanbeam.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// Scanbeam
/// </summary>
internal class Scanbeam // would this work as a struct?
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The y
/// </summary>
internal float Y;
/// <summary>
/// The next
/// </summary>
internal Scanbeam Next;
#pragma warning restore SA1401 // Field must be private
}
}

118
src/ImageSharp.Drawing/Shapes/PolygonClipper/TEdge.cs

@ -1,118 +0,0 @@
// <copyright file="TEdge.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes.PolygonClipper
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using Paths;
/// <summary>
/// TEdge
/// </summary>
internal class TEdge
{
#pragma warning disable SA1401 // Field must be private
/// <summary>
/// The source path, see if we can link this back later
/// </summary>
internal IPath SourcePath;
/// <summary>
/// The bot
/// </summary>
internal System.Numerics.Vector2 Bot;
/// <summary>
/// The current (updated for every new scanbeam)
/// </summary>
internal System.Numerics.Vector2 Curr;
/// <summary>
/// The top
/// </summary>
internal System.Numerics.Vector2 Top;
/// <summary>
/// The delta
/// </summary>
internal System.Numerics.Vector2 Delta;
/// <summary>
/// The dx
/// </summary>
internal double Dx;
/// <summary>
/// The poly type
/// </summary>
internal PolyType PolyTyp;
/// <summary>
/// Side only refers to current side of solution poly
/// </summary>
internal EdgeSide Side;
/// <summary>
/// 1 or -1 depending on winding direction
/// </summary>
internal int WindDelta;
/// <summary>
/// The winding count
/// </summary>
internal int WindCnt;
/// <summary>
/// The winding count of the opposite polytype
/// </summary>
internal int WindCnt2;
/// <summary>
/// The out index
/// </summary>
internal int OutIdx;
/// <summary>
/// The next
/// </summary>
internal TEdge Next;
/// <summary>
/// The previous
/// </summary>
internal TEdge Prev;
/// <summary>
/// The next in LML
/// </summary>
internal TEdge NextInLML;
/// <summary>
/// The next in ael
/// </summary>
internal TEdge NextInAEL;
/// <summary>
/// The previous in ael
/// </summary>
internal TEdge PrevInAEL;
/// <summary>
/// The next in sel
/// </summary>
internal TEdge NextInSEL;
/// <summary>
/// The previous in sel
/// </summary>
internal TEdge PrevInSEL;
#pragma warning restore SA1401 // Field must be
}
}

281
src/ImageSharp.Drawing/Shapes/RectangularPolygon.cs

@ -1,281 +0,0 @@
// <copyright file="RectangularPolygon.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Shapes
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using Paths;
/// <summary>
/// A way of optermising drawing rectangles.
/// </summary>
/// <seealso cref="ImageSharp.Drawing.Shapes.IShape" />
public class RectangularPolygon : IShape, IPath
{
private readonly RectangleF rectangle;
private readonly Vector2 topLeft;
private readonly Vector2 bottomRight;
private readonly Vector2[] points;
private readonly IEnumerable<IPath> pathCollection;
private readonly float halfLength;
/// <summary>
/// Initializes a new instance of the <see cref="RectangularPolygon"/> class.
/// </summary>
/// <param name="rect">The rect.</param>
public RectangularPolygon(ImageSharp.Rectangle rect)
: this((RectangleF)rect)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RectangularPolygon"/> class.
/// </summary>
/// <param name="rect">The rect.</param>
public RectangularPolygon(ImageSharp.RectangleF rect)
{
this.rectangle = rect;
this.points = new Vector2[4]
{
this.topLeft = new Vector2(rect.Left, rect.Top),
new Vector2(rect.Right, rect.Top),
this.bottomRight = new Vector2(rect.Right, rect.Bottom),
new Vector2(rect.Left, rect.Bottom)
};
this.halfLength = this.rectangle.Width + this.rectangle.Height;
this.Length = this.halfLength * 2;
this.pathCollection = new[] { this };
}
/// <summary>
/// Gets the bounding box of this shape.
/// </summary>
/// <value>
/// The bounds.
/// </value>
public RectangleF Bounds => this.rectangle;
/// <summary>
/// Gets a value indicating whether this instance is closed.
/// </summary>
/// <value>
/// <c>true</c> if this instance is closed; otherwise, <c>false</c>.
/// </value>
public bool IsClosed => true;
/// <summary>
/// Gets the length of the path
/// </summary>
/// <value>
/// The length.
/// </value>
public float Length { get; }
/// <summary>
/// Gets the maximum number intersections that a shape can have when testing a line.
/// </summary>
/// <value>
/// The maximum intersections.
/// </value>
public int MaxIntersections => 4;
/// <summary>
/// Calculates the distance along and away from the path for a specified point.
/// </summary>
/// <param name="point">The point along the path.</param>
/// <returns>
/// Returns details about the point and its distance away from the path.
/// </returns>
PointInfo IPath.Distance(Vector2 point)
{
bool inside; // dont care about inside/outside for paths just distance
return this.Distance(point, false, out inside);
}
/// <summary>
/// the distance of the point from the outline of the shape, if the value is negative it is inside the polygon bounds
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// Returns the distance from the shape to the point
/// </returns>
public float Distance(Vector2 point)
{
bool insidePoly;
PointInfo result = this.Distance(point, true, out insidePoly);
// invert the distance from path when inside
return insidePoly ? -result.DistanceFromPath : result.DistanceFromPath;
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// An enumerator that can be used to iterate through the collection.
/// </returns>
public IEnumerator<IPath> GetEnumerator()
{
return this.pathCollection.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this.pathCollection.GetEnumerator();
}
/// <summary>
/// Converts the <see cref="ILineSegment" /> into a simple linear path..
/// </summary>
/// <returns>
/// Returns the current <see cref="ILineSegment" /> as simple linear path.
/// </returns>
public Vector2[] AsSimpleLinearPath()
{
return this.points;
}
/// <summary>
/// Based on a line described by <paramref name="start"/> and <paramref name="end"/>
/// populate a buffer for all points on the edges of the <see cref="RectangularPolygon"/>
/// that the line intersects.
/// </summary>
/// <param name="start">The start point of the line.</param>
/// <param name="end">The end point of the line.</param>
/// <param name="buffer">The buffer that will be populated with intersections.</param>
/// <param name="count">The count.</param>
/// <param name="offset">The offset.</param>
/// <returns>
/// The number of intersections populated into the buffer.
/// </returns>
public int FindIntersections(Vector2 start, Vector2 end, Vector2[] buffer, int count, int offset)
{
int discovered = 0;
Vector2 startPoint = Vector2.Clamp(start, this.topLeft, this.bottomRight);
Vector2 endPoint = Vector2.Clamp(end, this.topLeft, this.bottomRight);
if (startPoint == Vector2.Clamp(startPoint, start, end))
{
// if start closest is within line then its a valid point
discovered++;
buffer[offset++] = startPoint;
}
if (endPoint == Vector2.Clamp(endPoint, start, end))
{
// if start closest is within line then its a valid point
discovered++;
buffer[offset++] = endPoint;
}
return discovered;
}
private PointInfo Distance(Vector2 point, bool getDistanceAwayOnly, out bool isInside)
{
// point in rectangle
// if after its clamped by the extreams its still the same then it must be inside :)
Vector2 clamped = Vector2.Clamp(point, this.topLeft, this.bottomRight);
isInside = clamped == point;
float distanceFromEdge = float.MaxValue;
float distanceAlongEdge = 0f;
if (isInside)
{
// get the absolute distances from the extreams
Vector2 topLeftDist = Vector2.Abs(point - this.topLeft);
Vector2 bottomRightDist = Vector2.Abs(point - this.bottomRight);
// get the min components
Vector2 minDists = Vector2.Min(topLeftDist, bottomRightDist);
// and then the single smallest (dont have to worry about direction)
distanceFromEdge = Math.Min(minDists.X, minDists.Y);
if (!getDistanceAwayOnly)
{
// we need to make clamped the closest point
if (this.topLeft.X + distanceFromEdge == point.X)
{
// closer to lhf
clamped.X = this.topLeft.X; // y is already the same
// distance along edge is length minus the amout down we are from the top of the rect
distanceAlongEdge = this.Length - (clamped.Y - this.topLeft.Y);
}
else if (this.topLeft.Y + distanceFromEdge == point.Y)
{
// closer to top
clamped.Y = this.topLeft.Y; // x is already the same
distanceAlongEdge = clamped.X - this.topLeft.X;
}
else if (this.bottomRight.Y - distanceFromEdge == point.Y)
{
// closer to bottom
clamped.Y = this.bottomRight.Y; // x is already the same
distanceAlongEdge = (this.bottomRight.X - clamped.X) + this.halfLength;
}
else if (this.bottomRight.X - distanceFromEdge == point.X)
{
// closer to rhs
clamped.X = this.bottomRight.X; // x is already the same
distanceAlongEdge = (this.bottomRight.Y - clamped.Y) + this.rectangle.Width;
}
}
}
else
{
// clamped is the point on the path thats closest no matter what
distanceFromEdge = (clamped - point).Length();
if (!getDistanceAwayOnly)
{
// we need to figure out whats the cloests edge now and thus what distance/poitn is closest
if (this.topLeft.X == clamped.X)
{
// distance along edge is length minus the amout down we are from the top of the rect
distanceAlongEdge = this.Length - (clamped.Y - this.topLeft.Y);
}
else if (this.topLeft.Y == clamped.Y)
{
distanceAlongEdge = clamped.X - this.topLeft.X;
}
else if (this.bottomRight.Y == clamped.Y)
{
distanceAlongEdge = (this.bottomRight.X - clamped.X) + this.halfLength;
}
else if (this.bottomRight.X == clamped.X)
{
distanceAlongEdge = (this.bottomRight.Y - clamped.Y) + this.rectangle.Width;
}
}
}
return new PointInfo
{
SearchPoint = point,
DistanceFromPath = distanceFromEdge,
ClosestPointOnPath = clamped,
DistanceAlongPath = distanceAlongEdge
};
}
}
}

6
src/ImageSharp.Drawing/project.json

@ -39,12 +39,10 @@
},
"dependencies": {
"ImageSharp": {
"target": "project",
"version": "1.0.0-*"
"target": "project"
},
"ImageSharp.Processing": {
"target": "project",
"version": "1.0.0-*"
"target": "project"
},
"StyleCop.Analyzers": {
"version": "1.0.0",

3
src/ImageSharp.Processing/Binarization/BinaryThreshold.cs

@ -40,7 +40,8 @@ namespace ImageSharp
public static Image<TColor> BinaryThreshold<TColor>(this Image<TColor> source, float threshold, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new BinaryThresholdProcessor<TColor>(threshold));
source.ApplyProcessor(new BinaryThresholdProcessor<TColor>(threshold), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/ColorMatrix/BlackWhite.cs

@ -39,7 +39,8 @@ namespace ImageSharp
public static Image<TColor> BlackWhite<TColor>(this Image<TColor> source, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new BlackWhiteProcessor<TColor>());
source.ApplyProcessor(new BlackWhiteProcessor<TColor>(), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/ColorMatrix/ColorBlindness.cs

@ -78,7 +78,8 @@ namespace ImageSharp
break;
}
return source.Apply(rectangle, processor);
source.ApplyProcessor(processor, rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/ColorMatrix/Grayscale.cs

@ -45,7 +45,8 @@ namespace ImageSharp
? (IImageProcessor<TColor>)new GrayscaleBt709Processor<TColor>()
: new GrayscaleBt601Processor<TColor>();
return source.Apply(rectangle, processor);
source.ApplyProcessor(processor, rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/ColorMatrix/Hue.cs

@ -41,7 +41,8 @@ namespace ImageSharp
public static Image<TColor> Hue<TColor>(this Image<TColor> source, float degrees, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new HueProcessor<TColor>(degrees));
source.ApplyProcessor(new HueProcessor<TColor>(degrees), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/ColorMatrix/Kodachrome.cs

@ -39,7 +39,8 @@ namespace ImageSharp
public static Image<TColor> Kodachrome<TColor>(this Image<TColor> source, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new KodachromeProcessor<TColor>());
source.ApplyProcessor(new KodachromeProcessor<TColor>(), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/ColorMatrix/Lomograph.cs

@ -39,7 +39,8 @@ namespace ImageSharp
public static Image<TColor> Lomograph<TColor>(this Image<TColor> source, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new LomographProcessor<TColor>());
source.ApplyProcessor(new LomographProcessor<TColor>(), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/ColorMatrix/Polaroid.cs

@ -39,7 +39,8 @@ namespace ImageSharp
public static Image<TColor> Polaroid<TColor>(this Image<TColor> source, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new PolaroidProcessor<TColor>());
source.ApplyProcessor(new PolaroidProcessor<TColor>(), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/ColorMatrix/Saturation.cs

@ -41,7 +41,8 @@ namespace ImageSharp
public static Image<TColor> Saturation<TColor>(this Image<TColor> source, int amount, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new SaturationProcessor<TColor>(amount));
source.ApplyProcessor(new SaturationProcessor<TColor>(amount), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/ColorMatrix/Sepia.cs

@ -39,7 +39,8 @@ namespace ImageSharp
public static Image<TColor> Sepia<TColor>(this Image<TColor> source, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new SepiaProcessor<TColor>());
source.ApplyProcessor(new SepiaProcessor<TColor>(), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Convolution/BoxBlur.cs

@ -41,7 +41,8 @@ namespace ImageSharp
public static Image<TColor> BoxBlur<TColor>(this Image<TColor> source, int radius, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new BoxBlurProcessor<TColor>(radius));
source.ApplyProcessor(new BoxBlurProcessor<TColor>(), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Convolution/DetectEdges.cs

@ -146,7 +146,8 @@ namespace ImageSharp
public static Image<TColor> DetectEdges<TColor>(this Image<TColor> source, Rectangle rectangle, IEdgeDetectorProcessor<TColor> filter)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, filter);
source.ApplyProcessor(filter, rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Convolution/GaussianBlur.cs

@ -41,7 +41,8 @@ namespace ImageSharp
public static Image<TColor> GaussianBlur<TColor>(this Image<TColor> source, float sigma, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new GaussianBlurProcessor<TColor>(sigma));
source.ApplyProcessor(new GaussianBlurProcessor<TColor>(sigma), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Convolution/GaussianSharpen.cs

@ -41,7 +41,8 @@ namespace ImageSharp
public static Image<TColor> GaussianSharpen<TColor>(this Image<TColor> source, float sigma, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new GaussianSharpenProcessor<TColor>(sigma));
source.ApplyProcessor(new GaussianSharpenProcessor<TColor>(sigma), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Effects/Alpha.cs

@ -40,7 +40,8 @@ namespace ImageSharp
public static Image<TColor> Alpha<TColor>(this Image<TColor> source, int percent, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new AlphaProcessor<TColor>(percent));
source.ApplyProcessor(new AlphaProcessor<TColor>(percent), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Effects/BackgroundColor.cs

@ -24,7 +24,8 @@ namespace ImageSharp
public static Image<TColor> BackgroundColor<TColor>(this Image<TColor> source, TColor color)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(source.Bounds, new BackgroundColorProcessor<TColor>(color));
source.ApplyProcessor(new BackgroundColorProcessor<TColor>(color), source.Bounds);
return source;
}
}
}

5
src/ImageSharp.Processing/Effects/Brightness.cs

@ -39,8 +39,9 @@ namespace ImageSharp
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Brightness<TColor>(this Image<TColor> source, int amount, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new BrightnessProcessor<TColor>(amount));
{
source.ApplyProcessor(new BrightnessProcessor<TColor>(amount), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Effects/Contrast.cs

@ -40,7 +40,8 @@ namespace ImageSharp
public static Image<TColor> Contrast<TColor>(this Image<TColor> source, int amount, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new ContrastProcessor<TColor>(amount));
source.ApplyProcessor(new ContrastProcessor<TColor>(amount), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Effects/Invert.cs

@ -38,7 +38,8 @@ namespace ImageSharp
public static Image<TColor> Invert<TColor>(this Image<TColor> source, Rectangle rectangle)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return source.Apply(rectangle, new InvertProcessor<TColor>());
source.ApplyProcessor(new InvertProcessor<TColor>(), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Effects/OilPainting.cs

@ -49,7 +49,8 @@ namespace ImageSharp
throw new ArgumentOutOfRangeException(nameof(brushSize));
}
return source.Apply(rectangle, new OilPaintingProcessor<TColor>(levels, brushSize));
source.ApplyProcessor(new OilPaintingProcessor<TColor>(levels, brushSize), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Effects/Pixelate.cs

@ -45,7 +45,8 @@ namespace ImageSharp
throw new ArgumentOutOfRangeException(nameof(size));
}
return source.Apply(rectangle, new PixelateProcessor<TColor>(size));
source.ApplyProcessor(new PixelateProcessor<TColor>(size), rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Overlays/Glow.cs

@ -88,7 +88,8 @@ namespace ImageSharp
processor.GlowColor = color;
}
return source.Apply(rectangle, processor);
source.ApplyProcessor(processor, rectangle);
return source;
}
}
}

3
src/ImageSharp.Processing/Overlays/Vignette.cs

@ -90,7 +90,8 @@ namespace ImageSharp
processor.VignetteColor = color;
}
return source.Apply(rectangle, processor);
source.ApplyProcessor(processor, rectangle);
return source;
}
}
}

4
src/ImageSharp.Processing/Transforms/Crop.cs

@ -41,7 +41,9 @@ namespace ImageSharp
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
CropProcessor<TColor> processor = new CropProcessor<TColor>(cropRectangle);
return source.Apply(source.Bounds, processor);
source.ApplyProcessor(processor, source.Bounds);
return source;
}
}
}

4
src/ImageSharp.Processing/Transforms/EntropyCrop.cs

@ -25,7 +25,9 @@ namespace ImageSharp
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
EntropyCropProcessor<TColor> processor = new EntropyCropProcessor<TColor>(threshold);
return source.Apply(source.Bounds, processor);
source.ApplyProcessor(processor, source.Bounds);
return source;
}
}
}

4
src/ImageSharp.Processing/Transforms/Flip.cs

@ -26,7 +26,9 @@ namespace ImageSharp
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
FlipProcessor<TColor> processor = new FlipProcessor<TColor>(flipType);
return source.Apply(source.Bounds, processor);
source.ApplyProcessor(processor, source.Bounds);
return source;
}
}
}

3
src/ImageSharp.Processing/Transforms/Resize.cs

@ -167,7 +167,8 @@ namespace ImageSharp
processor = new ResizeProcessor<TColor>(sampler, width, height, targetRectangle);
}
return source.Apply(sourceRectangle, processor);
source.ApplyProcessor(processor, sourceRectangle);
return source;
}
}
}

4
src/ImageSharp.Processing/Transforms/Rotate.cs

@ -53,7 +53,9 @@ namespace ImageSharp
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
RotateProcessor<TColor> processor = new RotateProcessor<TColor> { Angle = degrees, Expand = expand };
return source.Apply(source.Bounds, processor);
source.ApplyProcessor(processor, source.Bounds);
return source;
}
}
}

4
src/ImageSharp.Processing/Transforms/Skew.cs

@ -41,7 +41,9 @@ namespace ImageSharp
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
SkewProcessor<TColor> processor = new SkewProcessor<TColor> { AngleX = degreesX, AngleY = degreesY, Expand = expand };
return source.Apply(source.Bounds, processor);
source.ApplyProcessor(processor, source.Bounds);
return source;
}
}
}

11
src/ImageSharp/Image/ImageBase{TColor}.cs

@ -7,6 +7,7 @@ namespace ImageSharp
{
using System;
using System.Diagnostics;
using Processing;
/// <summary>
/// The base class of all images. Encapsulates the basic properties and methods required to manipulate
@ -120,6 +121,16 @@ namespace ImageSharp
/// </summary>
public Configuration Configuration { get; private set; }
/// <summary>
/// Applies the processor.
/// </summary>
/// <param name="processor">The processor.</param>
/// <param name="rectangle">The rectangle.</param>
public virtual void ApplyProcessor(IImageProcessor<TColor> processor, Rectangle rectangle)
{
processor.Apply(this, rectangle);
}
/// <inheritdoc />
public void Dispose()
{

25
src/ImageSharp/Image/ImageProcessingExtensions.cs

@ -24,30 +24,7 @@ namespace ImageSharp
public static Image<TColor> Apply<TColor>(this Image<TColor> source, IImageProcessor<TColor> processor)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
return Apply(source, source.Bounds, processor);
}
/// <summary>
/// Applies the processor to the image.
/// <remarks>This method does not resize the target image.</remarks>
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <param name="processor">The processors to apply to the image.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Apply<TColor>(this Image<TColor> source, Rectangle sourceRectangle, IImageProcessor<TColor> processor)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
processor.Apply(source, sourceRectangle);
foreach (ImageFrame<TColor> sourceFrame in source.Frames)
{
processor.Apply(sourceFrame, sourceRectangle);
}
source.ApplyProcessor(processor, source.Bounds);
return source;
}
}

16
src/ImageSharp/Image/Image{TColor}.cs

@ -16,6 +16,7 @@ namespace ImageSharp
using System.Threading.Tasks;
using Formats;
using Processing;
/// <summary>
/// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes.
@ -219,6 +220,21 @@ namespace ImageSharp
/// </summary>
public ExifProfile ExifProfile { get; set; }
/// <summary>
/// Applies the processor to the image.
/// </summary>
/// <param name="processor">The processor to apply to the image.</param>
/// <param name="rectangle">The <see cref="Rectangle" /> structure that specifies the portion of the image object to draw.</param>
public override void ApplyProcessor(IImageProcessor<TColor> processor, Rectangle rectangle)
{
// we want to put this on on here as it gives us a really go place to test/verify processor settings
base.ApplyProcessor(processor, rectangle);
foreach (ImageFrame<TColor> sourceFrame in this.Frames)
{
sourceFrame.ApplyProcessor(processor, rectangle);
}
}
/// <summary>
/// Saves the image to the given stream using the currently loaded image format.
/// </summary>

10
tests/ImageSharp.Benchmarks/Drawing/FillRectangle.cs

@ -39,7 +39,7 @@ namespace ImageSharp.Benchmarks
{
using (CoreImage image = new CoreImage(800, 800))
{
image.Fill(CoreColor.HotPink, new ImageSharp.Drawing.Shapes.RectangularPolygon(new CoreRectangle(10, 10, 190, 140)));
image.Fill(CoreColor.HotPink, new CoreRectangle(10, 10, 190, 140));
return new CoreSize(image.Width, image.Height);
}
@ -53,10 +53,10 @@ namespace ImageSharp.Benchmarks
image.FillPolygon(
CoreColor.HotPink,
new[] {
new Vector2(10, 10),
new Vector2(200, 10),
new Vector2(200, 150),
new Vector2(10, 150) });
new Vector2(10, 10),
new Vector2(200, 10),
new Vector2(200, 150),
new Vector2(10, 150) });
return new CoreSize(image.Width, image.Height);
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save