Browse Source

Merge branch 'master' into tiff-codec

pull/1570/head
Andrew Wilkinson 9 years ago
parent
commit
364df7ba5c
  1. 2
      .editorconfig
  2. 2
      ImageSharp.ruleset
  3. 9
      ImageSharp.sln
  4. 40
      README.md
  5. 249
      Rebracer.xml
  6. 56
      Settings.StyleCop
  7. 6
      features.md
  8. 254
      src/ImageSharp.Drawing/Brushes/Brushes.cs
  9. 168
      src/ImageSharp.Drawing/Brushes/Brushes{TColor}.cs
  10. 16
      src/ImageSharp.Drawing/Brushes/IBrush.cs
  11. 22
      src/ImageSharp.Drawing/Brushes/ImageBrush.cs
  12. 88
      src/ImageSharp.Drawing/Brushes/ImageBrush{TPixel}.cs
  13. 33
      src/ImageSharp.Drawing/Brushes/PatternBrush.cs
  14. 75
      src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs
  15. 71
      src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs
  16. 24
      src/ImageSharp.Drawing/Brushes/RecolorBrush.cs
  17. 97
      src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs
  18. 22
      src/ImageSharp.Drawing/Brushes/SolidBrush.cs
  19. 118
      src/ImageSharp.Drawing/Brushes/SolidBrush{TColor}.cs
  20. 109
      src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs
  21. 185
      src/ImageSharp.Drawing/DrawImage.cs
  22. 63
      src/ImageSharp.Drawing/DrawPath.cs
  23. 77
      src/ImageSharp.Drawing/FillRegion.cs
  24. 38
      src/ImageSharp.Drawing/GraphicsOptions.cs
  25. 6
      src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
  26. 61
      src/ImageSharp.Drawing/Paths/DrawBeziers.cs
  27. 61
      src/ImageSharp.Drawing/Paths/DrawLines.cs
  28. 62
      src/ImageSharp.Drawing/Paths/DrawPath.cs
  29. 61
      src/ImageSharp.Drawing/Paths/DrawPolygon.cs
  30. 61
      src/ImageSharp.Drawing/Paths/DrawRectangle.cs
  31. 42
      src/ImageSharp.Drawing/Paths/FillPaths.cs
  32. 40
      src/ImageSharp.Drawing/Paths/FillPolygon.cs
  33. 41
      src/ImageSharp.Drawing/Paths/FillRectangle.cs
  34. 11
      src/ImageSharp.Drawing/Pens/IPen.cs
  35. 53
      src/ImageSharp.Drawing/Pens/Pen.cs
  36. 59
      src/ImageSharp.Drawing/Pens/Pens.cs
  37. 112
      src/ImageSharp.Drawing/Pens/Pens{TColor}.cs
  38. 69
      src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs
  39. 10
      src/ImageSharp.Drawing/Pens/Processors/ColoredPointInfo.cs
  40. 12
      src/ImageSharp.Drawing/Pens/Processors/PenApplicator.cs
  41. 98
      src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs
  42. 69
      src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs
  43. 52
      src/ImageSharp.Drawing/Processors/FillProcessor.cs
  44. 156
      src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
  45. 78
      src/ImageSharp.Drawing/Text/DrawText.cs
  46. 3
      src/ImageSharp.Drawing/Text/GlyphBuilder.cs
  47. 102
      src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs
  48. 255
      src/ImageSharp/Colors/Color.BulkOperations.cs
  49. 179
      src/ImageSharp/Colors/ColorConstants.cs
  50. 728
      src/ImageSharp/Colors/ColorDefinitions.cs
  51. 255
      src/ImageSharp/Colors/ColorTransforms.cs
  52. 727
      src/ImageSharp/Colors/NamedColors{TColor}.cs
  53. 256
      src/ImageSharp/Colors/PackedPixel/BulkPixelOperations{TColor}.cs
  54. 3
      src/ImageSharp/Colors/PackedPixel/README.md
  55. 7
      src/ImageSharp/Colors/Spaces/Bgra32.cs
  56. 7
      src/ImageSharp/Colors/Spaces/CieLab.cs
  57. 7
      src/ImageSharp/Colors/Spaces/CieXyz.cs
  58. 5
      src/ImageSharp/Colors/Spaces/Cmyk.cs
  59. 7
      src/ImageSharp/Colors/Spaces/Hsl.cs
  60. 7
      src/ImageSharp/Colors/Spaces/Hsv.cs
  61. 6
      src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs
  62. 7
      src/ImageSharp/Colors/Spaces/YCbCr.cs
  63. 292
      src/ImageSharp/Colors/Vector4BlendTransforms.cs
  64. 8
      src/ImageSharp/Common/Extensions/Vector4Extensions.cs
  65. 40
      src/ImageSharp/Common/Helpers/DebugGuard.cs
  66. 19
      src/ImageSharp/Common/Helpers/Guard.cs
  67. 77
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  68. 38
      src/ImageSharp/Common/Helpers/MathF.cs
  69. 129
      src/ImageSharp/Common/Memory/BufferSpan.cs
  70. 237
      src/ImageSharp/Common/Memory/BufferSpan{T}.cs
  71. 2
      src/ImageSharp/Dithering/ErrorDiffusion/Atkinson.cs
  72. 2
      src/ImageSharp/Dithering/ErrorDiffusion/Burks.cs
  73. 24
      src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs
  74. 2
      src/ImageSharp/Dithering/ErrorDiffusion/FloydSteinberg.cs
  75. 26
      src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs
  76. 2
      src/ImageSharp/Dithering/ErrorDiffusion/JarvisJudiceNinke.cs
  77. 2
      src/ImageSharp/Dithering/ErrorDiffusion/Sierra2.cs
  78. 2
      src/ImageSharp/Dithering/ErrorDiffusion/Sierra3.cs
  79. 2
      src/ImageSharp/Dithering/ErrorDiffusion/SierraLite.cs
  80. 2
      src/ImageSharp/Dithering/ErrorDiffusion/Stucki.cs
  81. 2
      src/ImageSharp/Dithering/Ordered/Bayer.cs
  82. 8
      src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
  83. 2
      src/ImageSharp/Dithering/Ordered/Ordered.cs
  84. 7
      src/ImageSharp/Dithering/Ordered/OrderedDither4x4.cs
  85. 8
      src/ImageSharp/Formats/Bmp/BmpDecoder.cs
  86. 58
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  87. 16
      src/ImageSharp/Formats/Bmp/BmpEncoder.cs
  88. 42
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  89. 12
      src/ImageSharp/Formats/Bmp/ImageExtensions.cs
  90. 18
      src/ImageSharp/Formats/Gif/GifDecoder.cs
  91. 60
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  92. 16
      src/ImageSharp/Formats/Gif/GifEncoder.cs
  93. 116
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  94. 20
      src/ImageSharp/Formats/Gif/ImageExtensions.cs
  95. 2476
      src/ImageSharp/Formats/Gif/spec-gif89a.txt
  96. 10
      src/ImageSharp/Formats/IImageDecoder.cs
  97. 12
      src/ImageSharp/Formats/IImageEncoder.cs
  98. 2
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
  99. 52
      src/ImageSharp/Formats/Jpeg/Components/DCT.cs
  100. 55
      src/ImageSharp/Formats/Jpeg/Components/Decoder/DecodedBlockArray.cs

2
.editorconfig

@ -6,7 +6,7 @@ indent_style = space
indent_size = 4
csharp_style_var_for_built_in_types = false:warning
csharp_style_var_elsewhere = false:warning
csharp_style_var_when_type_is_apparent = false:warning
csharp_style_var_when_type_is_apparent = true:warning
end_of_line = crlf
dotnet_sort_system_directives_first = true
dotnet_style_predefined_type_for_locals_parameters_members = true:warning

2
ImageSharp.ruleset

@ -4,7 +4,7 @@
<Rule Id="AD0001" Action="None" />
<Rule Id="SA1405" Action="None" />
<Rule Id="SA1413" Action="None" />
<!-- temp remove the header requiremnet as stylecop is currently failing to read the stylecop.json file from 'dotnet build' -->
<!-- temp remove the header requirement as stylecop is currently failing to read the stylecop.json file from 'dotnet build' -->
<Rule Id="SA1636" Action="None" />
<Rule Id="SA1633" Action="None" />
</Rules>

9
ImageSharp.sln

@ -1,24 +1,21 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.9
VisualStudioVersion = 15.0.26403.7
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{C317F1B1-D75E-4C6D-83EB-80367343E0D7}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.travis.yml = .travis.yml
appveyor.yml = appveyor.yml
codecov.yml = codecov.yml
CodeCoverage.runsettings = CodeCoverage.runsettings
contributing.md = contributing.md
dotnet-latest.ps1 = dotnet-latest.ps1
.github\CONTRIBUTING.md = .github\CONTRIBUTING.md
features.md = features.md
global.json = global.json
ImageSharp.ruleset = ImageSharp.ruleset
ImageSharp.sln.DotSettings = ImageSharp.sln.DotSettings
NuGet.config = NuGet.config
README.md = README.md
Rebracer.xml = Rebracer.xml
Settings.StyleCop = Settings.StyleCop
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{815C0625-CD3D-440F-9F80-2D83856AB7AE}"

40
README.md

@ -1,9 +1,13 @@
# <img src="build/icons/imagesharp-logo-heading.png" alt="ImageSharp"/>
# <img src="https://raw.githubusercontent.com/JimBobSquarePants/ImageSharp/master/build/icons/imagesharp-logo-256.png" alt="ImageSharp" width="52"/> ImageSharp
**ImageSharp** is a new cross-platform 2D graphics API designed to allow the processing of images without the use of `System.Drawing`.
**ImageSharp** is a new, fully featured, fully managed, cross-platform, 2D graphics API designed to allow the processing of images without the use of `System.Drawing`.
> **ImageSharp is still in early stages (alpha) but progress has been pretty quick. As such, please do not use on production environments until the library reaches release candidate status. Pre-release downloads are available from the [MyGet package repository](https://www.myget.org/gallery/imagesharp).**
Built against .Net Standard 1.1 ImageSharp can be used in device, cloud, and embedded/IoT scenarios.
> **ImageSharp** has made excellent progress and contains many great features but is still considered by us to be still in early stages (alpha). As such, we cannot support its use on production environments until the library reaches release candidate status.
>
> Pre-release downloads are available from the [MyGet package repository](https://www.myget.org/gallery/imagesharp).
[![GitHub license](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/JimBobSquarePants/ImageSharp/master/APACHE-2.0-LICENSE.txt)
[![GitHub issues](https://img.shields.io/github/issues/JimBobSquarePants/ImageSharp.svg)](https://github.com/JimBobSquarePants/ImageSharp/issues)
@ -35,8 +39,8 @@ The **ImageSharp** library is made up of multiple packages.
Packages include:
- **ImageSharp**
- Contains the Image classes, Colors, Primitives, Configuration, and other core functionality.
- The IImageFormat interface, Jpeg, Png, Bmp, and Gif formats.
- Contains the generic `Image<TPixel>` class, PixelFormats, Primitives, Configuration, and other core functionality.
- The `IImageFormat` interface, Jpeg, Png, Bmp, and Gif formats.
- Transform methods like Resize, Crop, Skew, Rotate - Anything that alters the dimensions of the image.
- Non-transform methods like Gaussian Blur, Pixelate, Edge Detection - Anything that maintains the original image dimensions.
@ -69,15 +73,20 @@ There's plenty there and more coming. Check out the [current features](features.
### API
Without the constraints of `System.Drawing` We have been able to develop something much more flexible, easier to code against, and much, much less prone to memory leaks. Gone are system-wide process-locks. Images and processors are thread safe usable in parallel processing utilizing all the availables cores.
Without the constraints of `System.Drawing` We have been able to develop something much more flexible, easier to code against, and much, much less prone to memory leaks.
Gone are system-wide process-locks; ImageSharp images are thread-safe and fully supported in web environments.
Many `Image` methods are also fluent.
Many `Image<TPixel>` methods are also fluent.
Here's an example of the code required to resize an image using the default Bicubic resampler then turn the colors into their grayscale equivalent using the BT709 standard matrix.
`Rgba32` is our default PixelFormat, equivalent to `System.Drawing Color`.
On platforms supporting netstandard 1.3+
```csharp
using (Image image = Image.Load("foo.jpg"))
// Image.Load(string path) is a shortcut for our default type. Other pixel formats use Image.Load<TPixel>(string path))
using (Image<Rgba32> image = Image.Load("foo.jpg"))
{
image.Resize(image.Width / 2, image.Height / 2)
.Grayscale()
@ -86,9 +95,10 @@ using (Image image = Image.Load("foo.jpg"))
```
on netstandard 1.1 - 1.2
```csharp
// Image.Load(Stream stream) is a shortcut for our default type. Other pixel formats use Image.Load<TPixel>(Stream stream))
using (FileStream stream = File.OpenRead("foo.jpg"))
using (FileStream output = File.OpenWrite("bar.jpg"))
using (Image image = Image.Load(stream))
using (Image<Rgba32> image = Image.Load<Rgba32>(stream))
{
image.Resize(image.Width / 2, image.Height / 2)
.Grayscale()
@ -99,14 +109,14 @@ using (Image image = Image.Load(stream))
Setting individual pixel values is perfomed as follows:
```csharp
using (image = new Image(400, 400)
using (var pixels = image.Lock())
using (Image<Rgba32> image = new Image<Rgba32>(400, 400)
using (PixelAccessor<Rgba32> pixels = image.Lock())
{
pixels[200, 200] = Color.White;
pixels[200, 200] = Rgba32.White;
}
```
For advanced usage the `Image<TColor>` and `PixelAccessor<TColor>` classes are available allowing developers to implement their own color models in the same manner as Microsoft XNA Game Studio and MonoGame.
For advanced usage there are multiple [PixelFormat implementations](https://github.com/JimBobSquarePants/ImageSharp/tree/master/src/ImageSharp/PixelFormats) available allowing developers to implement their own color models in the same manner as Microsoft XNA Game Studio and MonoGame.
All in all this should allow image processing to be much more accessible to developers which has always been my goal from the start.
@ -114,7 +124,7 @@ All in all this should allow image processing to be much more accessible to deve
Please... Spread the word, contribute algorithms, submit performance improvements, unit tests.
Performance is a biggie, if you know anything about the new vector types and can apply some fancy new stuff with that it would be awesome.
Performance is a biggie, if you know anything about the `System.Numerics.Vectors` types and can apply some fancy new stuff with that it would be awesome.
There's a lot of developers out there who could write this stuff a lot better and faster than I and I would love to see what we collectively can come up with so please, if you can help in any way it would be most welcome and benificial for all.
@ -198,4 +208,4 @@ Become a sponsor and get your logo on our README on Github with a link to your s
<a href="https://opencollective.com/imagesharp/sponsor/26/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/26/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/27/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/27/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/28/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/28/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/29/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/29/avatar.svg"></a>
<a href="https://opencollective.com/imagesharp/sponsor/29/website" target="_blank"><img src="https://opencollective.com/imagesharp/sponsor/29/avatar.svg"></a>

249
Rebracer.xml

@ -1,249 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!--Rebracer Solution Settings File-->
<!--This file contains Visual Studio settings for ImageProcessorCore.sln.-->
<!--Rebracer uses this file to apply settings for this solution-->
<!--when the solution is opened.-->
<!--Install Rebracer from http://visualstudiogallery.msdn.microsoft.com/410e9b9f-65f3-4495-b68e-15567e543c58 -->
<!--See https://github.com/SLaks/Rebracer for more information-->
<UserSettings>
<ToolsOptions>
<ToolsOptionsCategory name="Environment">
<ToolsOptionsSubCategory name="TaskList">
<PropertyValue name="CommentTokens" ArrayType="VT_VARIANT" ArrayElementCount="4">
<PropertyValue name="0">HACK:2</PropertyValue>
<PropertyValue name="1">TODO:2</PropertyValue>
<PropertyValue name="2">UNDONE:2</PropertyValue>
<PropertyValue name="3">UnresolvedMergeConflict:3</PropertyValue>
</PropertyValue>
<PropertyValue name="ConfirmTaskDeletion">false</PropertyValue>
<PropertyValue name="DontShowFilePaths">false</PropertyValue>
<PropertyValue name="WarnOnAddingHiddenItem">false</PropertyValue>
</ToolsOptionsSubCategory>
</ToolsOptionsCategory>
<ToolsOptionsCategory name="TextEditor">
<ToolsOptionsSubCategory name="CSharp-Specific">
<PropertyValue name="AddImport_SuggestForTypesInNuGetPackages">0</PropertyValue>
<PropertyValue name="AddImport_SuggestForTypesInReferenceAssemblies">0</PropertyValue>
<PropertyValue name="AutoComment">1</PropertyValue>
<PropertyValue name="AutoInsertAsteriskForNewLinesOfBlockComments">1</PropertyValue>
<PropertyValue name="CSharpClosedFileDiagnostics">-1</PropertyValue>
<PropertyValue name="ClosedFileDiagnostics">-1</PropertyValue>
<PropertyValue name="DisplayLineSeparators">0</PropertyValue>
<PropertyValue name="EnableHighlightRelatedKeywords">1</PropertyValue>
<PropertyValue name="ExtractMethod_AllowMovingDeclaration">0</PropertyValue>
<PropertyValue name="ExtractMethod_DoNotPutOutOrRefOnStruct">1</PropertyValue>
<PropertyValue name="Formatting_TriggerOnBlockCompletion">1</PropertyValue>
<PropertyValue name="Formatting_TriggerOnPaste">1</PropertyValue>
<PropertyValue name="Formatting_TriggerOnStatementCompletion">1</PropertyValue>
<PropertyValue name="Indent_BlockContents">1</PropertyValue>
<PropertyValue name="Indent_Braces">0</PropertyValue>
<PropertyValue name="Indent_CaseContents">1</PropertyValue>
<PropertyValue name="Indent_CaseLabels">1</PropertyValue>
<PropertyValue name="Indent_FlushLabelsLeft">0</PropertyValue>
<PropertyValue name="Indent_UnindentLabels">2</PropertyValue>
<PropertyValue name="NewLines_AnonymousTypeInitializer_EachMember">1</PropertyValue>
<PropertyValue name="NewLines_Braces_Accessor">1</PropertyValue>
<PropertyValue name="NewLines_Braces_AnonymousMethod">1</PropertyValue>
<PropertyValue name="NewLines_Braces_AnonymousTypeInitializer">1</PropertyValue>
<PropertyValue name="NewLines_Braces_ControlFlow">1</PropertyValue>
<PropertyValue name="NewLines_Braces_LambdaExpressionBody">1</PropertyValue>
<PropertyValue name="NewLines_Braces_Method">1</PropertyValue>
<PropertyValue name="NewLines_Braces_ObjectInitializer">1</PropertyValue>
<PropertyValue name="NewLines_Braces_Property">1</PropertyValue>
<PropertyValue name="NewLines_Braces_Type">1</PropertyValue>
<PropertyValue name="NewLines_Keywords_Catch">1</PropertyValue>
<PropertyValue name="NewLines_Keywords_Else">1</PropertyValue>
<PropertyValue name="NewLines_Keywords_Finally">1</PropertyValue>
<PropertyValue name="NewLines_ObjectInitializer_EachMember">1</PropertyValue>
<PropertyValue name="NewLines_QueryExpression_EachClause">1</PropertyValue>
<PropertyValue name="RenameTrackingPreview">1</PropertyValue>
<PropertyValue name="SortUsings_PlaceSystemFirst">0</PropertyValue>
<PropertyValue name="Space_AfterBasesColon">1</PropertyValue>
<PropertyValue name="Space_AfterCast">0</PropertyValue>
<PropertyValue name="Space_AfterComma">1</PropertyValue>
<PropertyValue name="Space_AfterDot">0</PropertyValue>
<PropertyValue name="Space_AfterMethodCallName">0</PropertyValue>
<PropertyValue name="Space_AfterMethodDeclarationName">0</PropertyValue>
<PropertyValue name="Space_AfterSemicolonsInForStatement">1</PropertyValue>
<PropertyValue name="Space_AroundBinaryOperator">1</PropertyValue>
<PropertyValue name="Space_BeforeBasesColon">1</PropertyValue>
<PropertyValue name="Space_BeforeComma">0</PropertyValue>
<PropertyValue name="Space_BeforeDot">0</PropertyValue>
<PropertyValue name="Space_BeforeOpenSquare">0</PropertyValue>
<PropertyValue name="Space_BeforeSemicolonsInForStatement">0</PropertyValue>
<PropertyValue name="Space_BetweenEmptyMethodCallParentheses">0</PropertyValue>
<PropertyValue name="Space_BetweenEmptyMethodDeclarationParentheses">0</PropertyValue>
<PropertyValue name="Space_BetweenEmptySquares">0</PropertyValue>
<PropertyValue name="Space_InControlFlowConstruct">1</PropertyValue>
<PropertyValue name="Space_WithinCastParentheses">0</PropertyValue>
<PropertyValue name="Space_WithinExpressionParentheses">0</PropertyValue>
<PropertyValue name="Space_WithinMethodCallParentheses">0</PropertyValue>
<PropertyValue name="Space_WithinMethodDeclarationParentheses">0</PropertyValue>
<PropertyValue name="Space_WithinOtherParentheses">0</PropertyValue>
<PropertyValue name="Space_WithinSquares">0</PropertyValue>
<PropertyValue name="Style_PreferIntrinsicPredefinedTypeKeywordInDeclaration">1</PropertyValue>
<PropertyValue name="Style_PreferIntrinsicPredefinedTypeKeywordInMemberAccess">1</PropertyValue>
<PropertyValue name="Style_QualifyMemberAccessWithThisOrMe">0</PropertyValue>
<PropertyValue name="Style_UseVarWhenDeclaringLocals">1</PropertyValue>
<PropertyValue name="WarnOnBuildErrors">0</PropertyValue>
<PropertyValue name="Wrapping_IgnoreSpacesAroundBinaryOperators">0</PropertyValue>
<PropertyValue name="Wrapping_IgnoreSpacesAroundVariableDeclaration">0</PropertyValue>
<PropertyValue name="Wrapping_KeepStatementsOnSingleLine">1</PropertyValue>
<PropertyValue name="Wrapping_PreserveSingleLine">1</PropertyValue>
</ToolsOptionsSubCategory>
<ToolsOptionsSubCategory name="JavaScript Specific">
<PropertyValue name="DownloadRemoteReferences">false</PropertyValue>
<PropertyValue name="FormatCompletedBlockOnRightCurlyBrace">true</PropertyValue>
<PropertyValue name="FormatCompletedLineOnEnter">true</PropertyValue>
<PropertyValue name="FormatCompletedStatementOnSemicolon">true</PropertyValue>
<PropertyValue name="FormatOnPaste">true</PropertyValue>
<PropertyValue name="ImplicitReferencesString">Implicit (Windows)|$(VSInstallDir)\JavaScript\References\libhelp.js|$(VSInstallDir)\JavaScript\References\domWindows.js|$(VSInstallDir)\JavaScript\References\underscorefilter.js|$(VSInstallDir)\JavaScript\References\showPlainComments.js;Implicit (Windows 8.1)|$(VSInstallDir)\JavaScript\References\libhelp.js|$(VSInstallDir)\JavaScript\References\sitetypesWindows.js|$(VSInstallDir)\JavaScript\References\domWindows_8.1.js|$(VSInstallDir)\JavaScript\References\underscorefilter.js|$(VSInstallDir)\JavaScript\References\showPlainComments.js;Implicit (Windows Phone 8.1)|$(VSInstallDir)\JavaScript\References\libhelp.js|$(VSInstallDir)\JavaScript\References\sitetypesWindows.js|$(VSInstallDir)\JavaScript\References\domWindowsPhone_8.1.js|$(VSInstallDir)\JavaScript\References\underscorefilter.js|$(VSInstallDir)\JavaScript\References\showPlainComments.js;Implicit (Web)|$(VSInstallDir)\JavaScript\References\libhelp.js|$(VSInstallDir)\JavaScript\References\sitetypesWeb.js|$(VSInstallDir)\JavaScript\References\domWeb.js|$(VSInstallDir)\JavaScript\References\underscorefilter.js|$(VSInstallDir)\JavaScript\References\showPlainComments.js|C:\Users\james.south\AppData\Local\Web Essentials 2015\Modern.Intellisense.js;Dedicated Worker|$(VSInstallDir)\JavaScript\References\libhelp.js|$(VSInstallDir)\JavaScript\References\dedicatedworker.js|$(VSInstallDir)\JavaScript\References\underscorefilter.js|$(VSInstallDir)\JavaScript\References\showPlainComments.js;Generic|$(VSInstallDir)\JavaScript\References\libhelp.js|$(VSInstallDir)\JavaScript\References\underscorefilter.js|$(VSInstallDir)\JavaScript\References\showPlainComments.js;</PropertyValue>
<PropertyValue name="InsertSpaceAfterCommaDelimiter">true</PropertyValue>
<PropertyValue name="InsertSpaceAfterFunctionKeywordForAnonymousFunctions">true</PropertyValue>
<PropertyValue name="InsertSpaceAfterKeywordsInControlFlowStatements">true</PropertyValue>
<PropertyValue name="InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis">false</PropertyValue>
<PropertyValue name="InsertSpaceAfterSemicolonInForStatements">true</PropertyValue>
<PropertyValue name="InsertSpaceBeforeAndAfterBinaryOperators">true</PropertyValue>
<PropertyValue name="PlaceOpenBraceOnNewLineForControlBlocks">false</PropertyValue>
<PropertyValue name="PlaceOpenBraceOnNewLineForFunctionsAndClasses">false</PropertyValue>
<PropertyValue name="ShowErrorsAsWarnings">true</PropertyValue>
<PropertyValue name="ShowSyntaxErrors">true</PropertyValue>
</ToolsOptionsSubCategory>
<ToolsOptionsSubCategory name="C/C++ Specific">
<PropertyValue name="AddSemicolonForClassTypes">true</PropertyValue>
<PropertyValue name="AlignParameters">false</PropertyValue>
<PropertyValue name="AlwaysUseFallbackLocation">false</PropertyValue>
<PropertyValue name="AutoFormatOnBraceCompletion">true</PropertyValue>
<PropertyValue name="AutoFormatOnClosingBrace">true</PropertyValue>
<PropertyValue name="AutoFormatOnPaste">true</PropertyValue>
<PropertyValue name="AutoFormatOnPaste2">1</PropertyValue>
<PropertyValue name="AutoFormatOnSemicolon">true</PropertyValue>
<PropertyValue name="AutoIndentOnTab">false</PropertyValue>
<PropertyValue name="ColorizeInactiveBlocksDifferently">true</PropertyValue>
<PropertyValue name="DisableBrowsingUpToDateCheck">true</PropertyValue>
<PropertyValue name="DisableCreateDeclDefnScan">false</PropertyValue>
<PropertyValue name="DisableErrorReporting">false</PropertyValue>
<PropertyValue name="DisableIntelliSenseErrorsInErrorList">false</PropertyValue>
<PropertyValue name="EnableChangeSignature">false</PropertyValue>
<PropertyValue name="EnableExpandPrecedence">false</PropertyValue>
<PropertyValue name="EnableExpandScopes">false</PropertyValue>
<PropertyValue name="EnableExtractFunction">false</PropertyValue>
<PropertyValue name="EnableSQLiteStoreEngine">true</PropertyValue>
<PropertyValue name="EnableSingleFileISense">true</PropertyValue>
<PropertyValue name="EnableSingleFileISenseSquiggles">false</PropertyValue>
<PropertyValue name="EnumerateCommentTasks">true</PropertyValue>
<PropertyValue name="GroupBrackets">true</PropertyValue>
<PropertyValue name="HideExperimentalAd">true</PropertyValue>
<PropertyValue name="HighlightMatchingTokens">true</PropertyValue>
<PropertyValue name="IndentAccessSpecifiers">false</PropertyValue>
<PropertyValue name="IndentBlockContents">true</PropertyValue>
<PropertyValue name="IndentBraces">false</PropertyValue>
<PropertyValue name="IndentCaseBraces">false</PropertyValue>
<PropertyValue name="IndentCaseContents">true</PropertyValue>
<PropertyValue name="IndentCaseLabels">false</PropertyValue>
<PropertyValue name="IndentGotoLabels">1</PropertyValue>
<PropertyValue name="IndentNamespaceContents">true</PropertyValue>
<PropertyValue name="IndentPreprocessor">2</PropertyValue>
<PropertyValue name="IndentationReference">2</PropertyValue>
<PropertyValue name="MemberListDotToArrow">false</PropertyValue>
<PropertyValue name="MemberListFilterHeuristic">false</PropertyValue>
<PropertyValue name="NewlineControlBlockBrace">0</PropertyValue>
<PropertyValue name="NewlineEmptyFunctionCloseBrace">true</PropertyValue>
<PropertyValue name="NewlineEmptyTypeCloseBrace">true</PropertyValue>
<PropertyValue name="NewlineFunctionBrace">0</PropertyValue>
<PropertyValue name="NewlineInitListBrace">0</PropertyValue>
<PropertyValue name="NewlineKeywordCatch">true</PropertyValue>
<PropertyValue name="NewlineKeywordElse">true</PropertyValue>
<PropertyValue name="NewlineKeywordWhile">false</PropertyValue>
<PropertyValue name="NewlineLambdaBrace">0</PropertyValue>
<PropertyValue name="NewlineNamespaceBrace">0</PropertyValue>
<PropertyValue name="NewlineScopeBrace">false</PropertyValue>
<PropertyValue name="NewlineTypeBrace">0</PropertyValue>
<PropertyValue name="PreserveBlock">1</PropertyValue>
<PropertyValue name="PreserveCommentIndentation">false</PropertyValue>
<PropertyValue name="PreserveInitListSpace">true</PropertyValue>
<PropertyValue name="PreserveParameterIndentation">false</PropertyValue>
<PropertyValue name="RefactorScope">2</PropertyValue>
<PropertyValue name="RemoveSpaceBeforeSemicolon">true</PropertyValue>
<PropertyValue name="RenameRenameComments">false</PropertyValue>
<PropertyValue name="RenameRenameInactive">false</PropertyValue>
<PropertyValue name="RenameRenameStrings">false</PropertyValue>
<PropertyValue name="RenameRenameUnconfirmed">false</PropertyValue>
<PropertyValue name="RenameSearchComments">true</PropertyValue>
<PropertyValue name="RenameSearchStrings">true</PropertyValue>
<PropertyValue name="RenameShowPreview">false</PropertyValue>
<PropertyValue name="RenameSkipPreviewIfConfirmed">false</PropertyValue>
<PropertyValue name="ShowSingleFileISenseErrorsInTaskList">false</PropertyValue>
<PropertyValue name="SpaceAfterCastParenthesis">false</PropertyValue>
<PropertyValue name="SpaceAfterComma">true</PropertyValue>
<PropertyValue name="SpaceAfterSemicolon">true</PropertyValue>
<PropertyValue name="SpaceAroundAssignmentOperator">2</PropertyValue>
<PropertyValue name="SpaceAroundBinaryOperator">2</PropertyValue>
<PropertyValue name="SpaceAroundConditionalOperator">2</PropertyValue>
<PropertyValue name="SpaceBeforeBlockBrace">true</PropertyValue>
<PropertyValue name="SpaceBeforeBracket">false</PropertyValue>
<PropertyValue name="SpaceBeforeComma">false</PropertyValue>
<PropertyValue name="SpaceBeforeConstructorColon">true</PropertyValue>
<PropertyValue name="SpaceBeforeControlBlockParenthesis">true</PropertyValue>
<PropertyValue name="SpaceBeforeEmptyBracket">false</PropertyValue>
<PropertyValue name="SpaceBeforeFunctionParenthesis">false</PropertyValue>
<PropertyValue name="SpaceBeforeFunctionParenthesis2">1</PropertyValue>
<PropertyValue name="SpaceBeforeInheritanceColon">true</PropertyValue>
<PropertyValue name="SpaceBeforeInitListBrace">false</PropertyValue>
<PropertyValue name="SpaceBeforeLambdaParenthesis">false</PropertyValue>
<PropertyValue name="SpaceBetweenEmptyBraces">false</PropertyValue>
<PropertyValue name="SpaceBetweenEmptyBrackets">false</PropertyValue>
<PropertyValue name="SpaceBetweenEmptyFunctionParentheses">false</PropertyValue>
<PropertyValue name="SpaceBetweenEmptyLambdaBrackets">false</PropertyValue>
<PropertyValue name="SpaceWithinBrackets">false</PropertyValue>
<PropertyValue name="SpaceWithinCastParentheses">false</PropertyValue>
<PropertyValue name="SpaceWithinControlBlockParentheses">false</PropertyValue>
<PropertyValue name="SpaceWithinExpressionParentheses">false</PropertyValue>
<PropertyValue name="SpaceWithinFunctionParentheses">false</PropertyValue>
<PropertyValue name="SpaceWithinInitListBraces">true</PropertyValue>
<PropertyValue name="SpaceWithinLambdaBrackets">false</PropertyValue>
<PropertyValue name="SuspendNewSingleFileISenseDuringDebugging">false</PropertyValue>
<PropertyValue name="TrimSpaceAroundScope">true</PropertyValue>
<PropertyValue name="TrimSpaceUnaryOperator">true</PropertyValue>
</ToolsOptionsSubCategory>
<ToolsOptionsSubCategory name="TypeScript Specific">
<PropertyValue name="AutomaticallyCompileTypeScriptFilesWhenSavedWhenNoSolution">false</PropertyValue>
<PropertyValue name="ES3ForFilesThatAreNotPartOfAProject">false</PropertyValue>
<PropertyValue name="ES5ForFilesThatAreNotPartOfAProject">true</PropertyValue>
<PropertyValue name="ES6ForFilesThatAreNotPartOfAProject">false</PropertyValue>
<PropertyValue name="FormatCompletedBlockOnRightCurlyBrace">true</PropertyValue>
<PropertyValue name="FormatCompletedLineOnEnter">true</PropertyValue>
<PropertyValue name="FormatCompletedStatementOnSemicolon">true</PropertyValue>
<PropertyValue name="FormatOnPaste">true</PropertyValue>
<PropertyValue name="InsertSpaceAfterCommaDelimiter">true</PropertyValue>
<PropertyValue name="InsertSpaceAfterFunctionKeywordForAnonymousFunctions">true</PropertyValue>
<PropertyValue name="InsertSpaceAfterKeywordsInControlFlowStatements">true</PropertyValue>
<PropertyValue name="InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis">false</PropertyValue>
<PropertyValue name="InsertSpaceAfterSemicolonInForStatements">true</PropertyValue>
<PropertyValue name="InsertSpaceBeforeAndAfterBinaryOperators">true</PropertyValue>
<PropertyValue name="PlaceOpenBraceOnNewLineForControlBlocks">false</PropertyValue>
<PropertyValue name="PlaceOpenBraceOnNewLineForFunctions">false</PropertyValue>
<PropertyValue name="ShowGruntGulpDialogForAspNet">true</PropertyValue>
<PropertyValue name="ShowVirtualProjectsInSolutionExplorerWhenNoSolution">true</PropertyValue>
<PropertyValue name="ShowVirtualProjectsInSolutionExplorerWhenSolutionOpen">false</PropertyValue>
<PropertyValue name="UseAMDCodeGenerationForModulesThatAreNotPartOfAProject">false</PropertyValue>
<PropertyValue name="UseCommonJSCodeGenerationForModulesThatAreNotPartOfAProject">false</PropertyValue>
<PropertyValue name="UseES2015CodeGenerationForModulesThatAreNotPartOfAProject">false</PropertyValue>
<PropertyValue name="UseJsxPreserveForFilesThatAreNotPartOfAProject">false</PropertyValue>
<PropertyValue name="UseJsxReactForFilesThatAreNotPartOfAProject">false</PropertyValue>
<PropertyValue name="UseSystemCodeGenerationForModulesThatAreNotPartOfAProject">false</PropertyValue>
<PropertyValue name="UseUMDCodeGenerationForModulesThatAreNotPartOfAProject">false</PropertyValue>
</ToolsOptionsSubCategory>
<ToolsOptionsSubCategory name="HTMLX Specific">
<PropertyValue name="EnableTagNavigator">false</PropertyValue>
<PropertyValue name="EnableValidation">true</PropertyValue>
<PropertyValue name="ErrorsAsWarnings">true</PropertyValue>
<PropertyValue name="FormatOnPaste">true</PropertyValue>
<PropertyValue name="IdentifyHelpfulExtensions">false</PropertyValue>
<PropertyValue name="InsertAttributeValueQuotes">true</PropertyValue>
<PropertyValue name="InsertClosingTag">true</PropertyValue>
<PropertyValue name="XHtmlCodingStyle">true</PropertyValue>
</ToolsOptionsSubCategory>
</ToolsOptionsCategory>
</ToolsOptions>
</UserSettings>

56
Settings.StyleCop

@ -1,56 +0,0 @@
<StyleCopSettings Version="105">
<GlobalSettings>
<CollectionProperty Name="RecognizedWords">
<Value>enum</Value>
<Value>exif</Value>
<Value>uint</Value>
<Value>lossy</Value>
<Value>octree</Value>
<Value>png</Value>
<Value>quantizer</Value>
<Value>unzig</Value>
<Value>cb</Value>
<Value>cr</Value>
<Value>Laplacian</Value>
<Value>Sobel</Value>
<Value>Scharr</Value>
<Value>rgb</Value>
<Value>rgba</Value>
<Value>rrggbb</Value>
<Value>rrggbbaa</Value>
<Value>scanline</Value>
<Value>scanlines</Value>
<Value>png's</Value>
<Value>codeword</Value>
<Value>unscaled</Value>
<Value>zig-zag</Value>
<Value>crc</Value>
<Value>zlib</Value>
<Value>xff</Value>
<Value>xda</Value>
<Value>ss</Value>
<Value>Vol</Value>
<Value>pp</Value>
<Value>cmyk</Value>
<Value>Paeth</Value>
<Value>th</Value>
<Value>bool</Value>
<Value>bools</Value>
<Value>desensitivity</Value>
<Value>premultiplied</Value>
<Value>endianness</Value>
<Value>thresholding</Value>
</CollectionProperty>
</GlobalSettings>
<Analyzers>
<Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
<AnalyzerSettings>
<StringProperty Name="CompanyName">James Jackson-South</StringProperty>
<StringProperty Name="Copyright">
Copyright © James Jackson-South and contributors.
Licensed under the Apache License, Version 2.0.
</StringProperty>
</AnalyzerSettings>
</Analyzer>
</Analyzers>
</StyleCopSettings>

6
features.md

@ -13,6 +13,7 @@ We've achieved a lot so far and hope to do a lot more in the future. We're alway
- [ ] Tiff (Help needed)
- **Metadata**
- [x] EXIF Read/Write (Jpeg just now)
- [ ] ICC (In Progress)
- **Quantizers (IQuantizer with alpha channel support, dithering, and thresholding)**
- [x] Octree
- [x] Xiaolin Wu
@ -28,7 +29,6 @@ We've achieved a lot so far and hope to do a lot more in the future. We're alway
- [x] Bayer
- [x] Ordered
- **Basic color structs with implicit operators.**
- [x] Color - 32bit color in RGBA order (IPackedPixel\<TPacked\>).
- [x] Bgra32
- [x] CIE Lab
- [x] CIE XYZ
@ -38,7 +38,7 @@ We've achieved a lot so far and hope to do a lot more in the future. We're alway
- [x] YCbCr
- **IPackedPixel representations of color models. Compatible with Microsoft XNA Game Studio and MonoGame IPackedVector\<TPacked\>.**
- [x] Alpha8
- [x] Argb
- [x] Argb32
- [x] Bgr565
- [x] Bgra444
- [x] Bgra565
@ -52,7 +52,9 @@ We've achieved a lot so far and hope to do a lot more in the future. We're alway
- [x] NormalizedShort4
- [x] Rg32
- [x] Rgba1010102
- [x] Rgba32 - 32bit color in RGBA order - Our default pixel format.
- [x] Rgba64
- [x] RgbaVector
- [x] Short2
- [x] Short4
- **Basic shape primitives.**

254
src/ImageSharp.Drawing/Brushes/Brushes.cs

@ -5,150 +5,254 @@
namespace ImageSharp.Drawing.Brushes
{
using ImageSharp.PixelFormats;
/// <summary>
/// A collection of methods for creating brushes. Brushes use <see cref="Color"/> for painting.
/// A collection of methods for creating generic brushes.
/// </summary>
public class Brushes
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static class Brushes
{
/// <summary>
/// Percent10 Hatch Pattern
/// </summary>
/// ---> x axis
/// ^
/// | y - axis
/// |
/// see PatternBrush for details about how to make new patterns work
private static readonly bool[,] Percent10Pattern =
{
{ true, false, false, false },
{ false, false, false, false },
{ false, false, true, false },
{ false, false, false, false }
};
/// <summary>
/// Percent20 pattern.
/// </summary>
private static readonly bool[,] Percent20Pattern =
{
{ true, false, false, false },
{ false, false, true, false },
{ true, false, false, false },
{ false, false, true, false }
};
/// <summary>
/// Horizontal Hatch Pattern
/// </summary>
private static readonly bool[,] HorizontalPattern =
{
{ false },
{ true },
{ false },
{ false }
};
/// <summary>
/// Min Pattern
/// </summary>
private static readonly bool[,] MinPattern =
{
{ false },
{ false },
{ false },
{ true }
};
/// <summary>
/// Vertical Pattern
/// </summary>
private static readonly bool[,] VerticalPattern =
{
{ false, true, false, false },
};
/// <summary>
/// Forward Diagonal Pattern
/// </summary>
private static readonly bool[,] ForwardDiagonalPattern =
{
{ false, false, false, true },
{ false, false, true, false },
{ false, true, false, false },
{ true, false, false, false }
};
/// <summary>
/// Backward Diagonal Pattern
/// </summary>
private static readonly bool[,] BackwardDiagonalPattern =
{
{ true, false, false, false },
{ false, true, false, false },
{ false, false, true, false },
{ false, false, false, true }
};
/// <summary>
/// Create as brush that will paint a solid color
/// </summary>
/// <param name="color">The color.</param>
/// <returns>A Brush</returns>
public static SolidBrush Solid(Color color)
=> new SolidBrush(color);
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static SolidBrush<TPixel> Solid<TPixel>(TPixel color)
where TPixel : struct, IPixel<TPixel>
=> new SolidBrush<TPixel>(color);
/// <summary>
/// Create as brush that will paint a Percent10 Hatch Pattern with
/// in the specified foreground color and a transparent background
/// Create as brush that will paint a Percent10 Hatch Pattern with the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <returns>A Brush</returns>
public static PatternBrush Percent10(Color foreColor)
=> new PatternBrush(Brushes<Color>.Percent10(foreColor, Color.Transparent));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> Percent10<TPixel>(TPixel foreColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, NamedColors<TPixel>.Transparent, Percent10Pattern);
/// <summary>
/// Create as brush that will paint a Percent10 Hatch Pattern with
/// in the specified foreground and background colors
/// Create as brush that will paint a Percent10 Hatch Pattern with the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush Percent10(Color foreColor, Color backColor)
=> new PatternBrush(Brushes<Color>.Percent10(foreColor, backColor));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> Percent10<TPixel>(TPixel foreColor, TPixel backColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, backColor, Percent10Pattern);
/// <summary>
/// Create as brush that will paint a Percent20 Hatch Pattern with
/// in the specified foreground color and a transparent background
/// Create as brush that will paint a Percent20 Hatch Pattern with the specified foreground color and a
/// transparent background.
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <returns>A Brush</returns>
public static PatternBrush Percent20(Color foreColor)
=> new PatternBrush(Brushes<Color>.Percent20(foreColor, Color.Transparent));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> Percent20<TPixel>(TPixel foreColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, NamedColors<TPixel>.Transparent, Percent20Pattern);
/// <summary>
/// Create as brush that will paint a Percent20 Hatch Pattern with
/// in the specified foreground and background colors
/// Create as brush that will paint a Percent20 Hatch Pattern with the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush Percent20(Color foreColor, Color backColor)
=> new PatternBrush(Brushes<Color>.Percent20(foreColor, backColor));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> Percent20<TPixel>(TPixel foreColor, TPixel backColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, backColor, Percent20Pattern);
/// <summary>
/// Create as brush that will paint a Horizontal Hatch Pattern with
/// in the specified foreground color and a transparent background
/// Create as brush that will paint a Horizontal Hatch Pattern with the specified foreground color and a
/// transparent background.
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <returns>A Brush</returns>
public static PatternBrush Horizontal(Color foreColor)
=> new PatternBrush(Brushes<Color>.Horizontal(foreColor, Color.Transparent));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> Horizontal<TPixel>(TPixel foreColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, NamedColors<TPixel>.Transparent, HorizontalPattern);
/// <summary>
/// Create as brush that will paint a Horizontal Hatch Pattern with
/// in the specified foreground and background colors
/// Create as brush that will paint a Horizontal Hatch Pattern with the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush Horizontal(Color foreColor, Color backColor)
=> new PatternBrush(Brushes<Color>.Horizontal(foreColor, backColor));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> Horizontal<TPixel>(TPixel foreColor, TPixel backColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, backColor, HorizontalPattern);
/// <summary>
/// Create as brush that will paint a Min Hatch Pattern with
/// in the specified foreground color and a transparent background
/// Create as brush that will paint a Min Hatch Pattern with the specified foreground color and a
/// transparent background.
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <returns>A Brush</returns>
public static PatternBrush Min(Color foreColor)
=> new PatternBrush(Brushes<Color>.Min(foreColor, Color.Transparent));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> Min<TPixel>(TPixel foreColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, NamedColors<TPixel>.Transparent, MinPattern);
/// <summary>
/// Create as brush that will paint a Min Hatch Pattern with
/// in the specified foreground and background colors
/// Create as brush that will paint a Min Hatch Pattern with the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush Min(Color foreColor, Color backColor)
=> new PatternBrush(Brushes<Color>.Min(foreColor, backColor));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> Min<TPixel>(TPixel foreColor, TPixel backColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, backColor, MinPattern);
/// <summary>
/// Create as brush that will paint a Vertical Hatch Pattern with
/// in the specified foreground color and a transparent background
/// Create as brush that will paint a Vertical Hatch Pattern with the specified foreground color and a
/// transparent background.
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <returns>A Brush</returns>
public static PatternBrush Vertical(Color foreColor)
=> new PatternBrush(Brushes<Color>.Vertical(foreColor, Color.Transparent));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> Vertical<TPixel>(TPixel foreColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, NamedColors<TPixel>.Transparent, VerticalPattern);
/// <summary>
/// Create as brush that will paint a Vertical Hatch Pattern with
/// in the specified foreground and background colors
/// Create as brush that will paint a Vertical Hatch Pattern with the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush Vertical(Color foreColor, Color backColor)
=> new PatternBrush(Brushes<Color>.Vertical(foreColor, backColor));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> Vertical<TPixel>(TPixel foreColor, TPixel backColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, backColor, VerticalPattern);
/// <summary>
/// Create as brush that will paint a Forward Diagonal Hatch Pattern with
/// in the specified foreground color and a transparent background
/// Create as brush that will paint a Forward Diagonal Hatch Pattern with the specified foreground color and a
/// transparent background.
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <returns>A Brush</returns>
public static PatternBrush ForwardDiagonal(Color foreColor)
=> new PatternBrush(Brushes<Color>.ForwardDiagonal(foreColor, Color.Transparent));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> ForwardDiagonal<TPixel>(TPixel foreColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, NamedColors<TPixel>.Transparent, ForwardDiagonalPattern);
/// <summary>
/// Create as brush that will paint a Forward Diagonal Hatch Pattern with
/// in the specified foreground and background colors
/// Create as brush that will paint a Forward Diagonal Hatch Pattern with the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush ForwardDiagonal(Color foreColor, Color backColor)
=> new PatternBrush(Brushes<Color>.ForwardDiagonal(foreColor, backColor));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> ForwardDiagonal<TPixel>(TPixel foreColor, TPixel backColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, backColor, ForwardDiagonalPattern);
/// <summary>
/// Create as brush that will paint a Backward Diagonal Hatch Pattern with
/// in the specified foreground color and a transparent background
/// Create as brush that will paint a Backward Diagonal Hatch Pattern with the specified foreground color and a
/// transparent background.
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <returns>A Brush</returns>
public static PatternBrush BackwardDiagonal(Color foreColor)
=> new PatternBrush(Brushes<Color>.BackwardDiagonal(foreColor, Color.Transparent));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> BackwardDiagonal<TPixel>(TPixel foreColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, NamedColors<TPixel>.Transparent, BackwardDiagonalPattern);
/// <summary>
/// Create as brush that will paint a Backward Diagonal Hatch Pattern with
/// in the specified foreground and background colors
/// Create as brush that will paint a Backward Diagonal Hatch Pattern with the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush BackwardDiagonal(Color foreColor, Color backColor)
=> new PatternBrush(Brushes<Color>.BackwardDiagonal(foreColor, backColor));
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A New <see cref="PatternBrush{TPixel}"/></returns>
public static PatternBrush<TPixel> BackwardDiagonal<TPixel>(TPixel foreColor, TPixel backColor)
where TPixel : struct, IPixel<TPixel>
=> new PatternBrush<TPixel>(foreColor, backColor, BackwardDiagonalPattern);
}
}

168
src/ImageSharp.Drawing/Brushes/Brushes{TColor}.cs

@ -1,168 +0,0 @@
// <copyright file="Brushes{TColor}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
using System;
/// <summary>
/// A collection of methods for creating generic brushes.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <returns>A Brush</returns>
public class Brushes<TColor>
where TColor : struct, IPixel<TColor>
{
/// <summary>
/// Percent10 Hatch Pattern
/// </summary>
/// ---> x axis
/// ^
/// | y - axis
/// |
/// see PatternBrush for details about how to make new patterns work
private static readonly bool[,] Percent10Pattern =
{
{ true, false, false, false },
{ false, false, false, false },
{ false, false, true, false },
{ false, false, false, false }
};
/// <summary>
/// Percent20 pattern.
/// </summary>
private static readonly bool[,] Percent20Pattern =
{
{ true, false, false, false },
{ false, false, true, false },
{ true, false, false, false },
{ false, false, true, false }
};
/// <summary>
/// Horizontal Hatch Pattern
/// </summary>
private static readonly bool[,] HorizontalPattern =
{
{ false },
{ true },
{ false },
{ false }
};
/// <summary>
/// Min Pattern
/// </summary>
private static readonly bool[,] MinPattern =
{
{ false },
{ false },
{ false },
{ true }
};
/// <summary>
/// Vertical Pattern
/// </summary>
private static readonly bool[,] VerticalPattern =
{
{ false, true, false, false },
};
/// <summary>
/// Forward Diagonal Pattern
/// </summary>
private static readonly bool[,] ForwardDiagonalPattern =
{
{ false, false, false, true },
{ false, false, true, false },
{ false, true, false, false },
{ true, false, false, false }
};
/// <summary>
/// Backward Diagonal Pattern
/// </summary>
private static readonly bool[,] BackwardDiagonalPattern =
{
{ true, false, false, false },
{ false, true, false, false },
{ false, false, true, false },
{ false, false, false, true }
};
/// <summary>
/// Create as brush that will paint a solid color
/// </summary>
/// <param name="color">The color.</param>
/// <returns>A Brush</returns>
public static SolidBrush<TColor> Solid(TColor color)
=> new SolidBrush<TColor>(color);
/// <summary>
/// Create as brush that will paint a Percent10 Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor> Percent10(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor>(foreColor, backColor, Percent10Pattern);
/// <summary>
/// Create as brush that will paint a Percent20 Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor> Percent20(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor>(foreColor, backColor, Percent20Pattern);
/// <summary>
/// Create as brush that will paint a Horizontal Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor> Horizontal(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor>(foreColor, backColor, HorizontalPattern);
/// <summary>
/// Create as brush that will paint a Min Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor> Min(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor>(foreColor, backColor, MinPattern);
/// <summary>
/// Create as brush that will paint a Vertical Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor> Vertical(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor>(foreColor, backColor, VerticalPattern);
/// <summary>
/// Create as brush that will paint a Forward Diagonal Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor> ForwardDiagonal(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor>(foreColor, backColor, ForwardDiagonalPattern);
/// <summary>
/// Create as brush that will paint a Backward Diagonal Hatch Pattern within the specified colors
/// </summary>
/// <param name="foreColor">Color of the foreground.</param>
/// <param name="backColor">Color of the background.</param>
/// <returns>A Brush</returns>
public static PatternBrush<TColor> BackwardDiagonal(TColor foreColor, TColor backColor)
=> new PatternBrush<TColor>(foreColor, backColor, BackwardDiagonalPattern);
}
}

16
src/ImageSharp.Drawing/Brushes/IBrush.cs

@ -5,26 +5,26 @@
namespace ImageSharp.Drawing
{
using System;
using ImageSharp.PixelFormats;
using Processors;
/// <summary>
/// Brush represents a logical configuration of a brush which can be used to source pixel colors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <remarks>
/// A brush is a simple class that will return an <see cref="BrushApplicator{TColor}" /> that will perform the
/// logic for converting a pixel location to a <typeparamref name="TColor"/>.
/// A brush is a simple class that will return an <see cref="BrushApplicator{TPixel}" /> that will perform the
/// logic for converting a pixel location to a <typeparamref name="TPixel"/>.
/// </remarks>
public interface IBrush<TColor>
where TColor : struct, IPixel<TColor>
public interface IBrush<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// Creates the applicator for this brush.
/// </summary>
/// <param name="pixelSource">The pixel source.</param>
/// <param name="region">The region the brush will be applied to.</param>
/// <param name="options">The graphic options</param>
/// <returns>
/// The brush applicator for this brush
/// </returns>
@ -32,6 +32,6 @@ namespace ImageSharp.Drawing
/// The <paramref name="region" /> when being applied to things like shapes would usually be the
/// bounding box of the shape not necessarily the bounds of the whole image
/// </remarks>
BrushApplicator<TColor> CreateApplicator(PixelAccessor<TColor> pixelSource, RectangleF region);
BrushApplicator<TPixel> CreateApplicator(PixelAccessor<TPixel> pixelSource, RectangleF region, GraphicsOptions options);
}
}

22
src/ImageSharp.Drawing/Brushes/ImageBrush.cs

@ -1,22 +0,0 @@
// <copyright file="ImageBrush.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
/// <summary>
/// Provides an implementation of a solid brush for painting with repeating images. The brush uses <see cref="Color"/> for painting.
/// </summary>
public class ImageBrush : ImageBrush<Color>
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageBrush" /> class.
/// </summary>
/// <param name="image">The image to paint.</param>
public ImageBrush(IImageBase<Color> image)
: base(image)
{
}
}
}

88
src/ImageSharp.Drawing/Brushes/ImageBrush{TColor}.cs → src/ImageSharp.Drawing/Brushes/ImageBrush{TPixel}.cs

@ -1,4 +1,4 @@
// <copyright file="ImageBrush{TColor}.cs" company="James Jackson-South">
// <copyright file="ImageBrush{TPixel}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -8,44 +8,46 @@ namespace ImageSharp.Drawing.Brushes
using System;
using System.Numerics;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
using Processors;
/// <summary>
/// Provides an implementation of an image brush for painting images within areas.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
public class ImageBrush<TColor> : IBrush<TColor>
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The pixel format.</typeparam>
public class ImageBrush<TPixel> : IBrush<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// The image to paint.
/// </summary>
private readonly IImageBase<TColor> image;
private readonly IImageBase<TPixel> image;
/// <summary>
/// Initializes a new instance of the <see cref="ImageBrush{TColor}"/> class.
/// Initializes a new instance of the <see cref="ImageBrush{TPixel}"/> class.
/// </summary>
/// <param name="image">The image.</param>
public ImageBrush(IImageBase<TColor> image)
public ImageBrush(IImageBase<TPixel> image)
{
this.image = image;
}
/// <inheritdoc />
public BrushApplicator<TColor> CreateApplicator(PixelAccessor<TColor> sourcePixels, RectangleF region)
public BrushApplicator<TPixel> CreateApplicator(PixelAccessor<TPixel> sourcePixels, RectangleF region, GraphicsOptions options)
{
return new ImageBrushApplicator(sourcePixels, this.image, region);
return new ImageBrushApplicator(sourcePixels, this.image, region, options);
}
/// <summary>
/// The image brush applicator.
/// </summary>
private class ImageBrushApplicator : BrushApplicator<TColor>
private class ImageBrushApplicator : BrushApplicator<TPixel>
{
/// <summary>
/// The source pixel accessor.
/// </summary>
private readonly PixelAccessor<TColor> source;
private readonly PixelAccessor<TPixel> source;
/// <summary>
/// The y-length.
@ -58,9 +60,14 @@ namespace ImageSharp.Drawing.Brushes
private readonly int xLength;
/// <summary>
/// The offset.
/// The Y offset.
/// </summary>
private readonly Vector2 offset;
private readonly int offsetY;
/// <summary>
/// The X offset.
/// </summary>
private readonly int offsetX;
/// <summary>
/// Initializes a new instance of the <see cref="ImageBrushApplicator"/> class.
@ -71,16 +78,18 @@ namespace ImageSharp.Drawing.Brushes
/// <param name="region">
/// The region.
/// </param>
/// <param name="options">The options</param>
/// <param name="sourcePixels">
/// The sourcePixels.
/// </param>
public ImageBrushApplicator(PixelAccessor<TColor> sourcePixels, IImageBase<TColor> image, RectangleF region)
: base(sourcePixels)
public ImageBrushApplicator(PixelAccessor<TPixel> sourcePixels, IImageBase<TPixel> image, RectangleF region, GraphicsOptions options)
: base(sourcePixels, options)
{
this.source = image.Lock();
this.xLength = image.Width;
this.yLength = image.Height;
this.offset = new Vector2(MathF.Max(MathF.Floor(region.Top), 0), MathF.Max(MathF.Floor(region.Left), 0));
this.offsetY = (int)MathF.Max(MathF.Floor(region.Top), 0);
this.offsetX = (int)MathF.Max(MathF.Floor(region.Left), 0);
}
/// <summary>
@ -91,17 +100,12 @@ namespace ImageSharp.Drawing.Brushes
/// <returns>
/// The color
/// </returns>
internal override TColor this[int x, int y]
internal override TPixel this[int x, int y]
{
get
{
Vector2 point = new Vector2(x, y);
// Offset the requested pixel by the value in the rectangle (the shapes position)
point = point - this.offset;
int srcX = (int)point.X % this.xLength;
int srcY = (int)point.Y % this.yLength;
int srcX = (x - this.offsetX) % this.xLength;
int srcY = (y - this.offsetY) % this.yLength;
return this.source[srcX, srcY];
}
}
@ -113,33 +117,27 @@ namespace ImageSharp.Drawing.Brushes
}
/// <inheritdoc />
internal override void Apply(float[] scanlineBuffer, int scanlineWidth, int offset, int x, int y)
internal override void Apply(Span<float> scanline, int x, int y)
{
Guard.MustBeGreaterThanOrEqualTo(scanlineBuffer.Length, offset + scanlineWidth, nameof(scanlineWidth));
using (PinnedBuffer<float> buffer = new PinnedBuffer<float>(scanlineBuffer))
// create a span for colors
using (Buffer<float> amountBuffer = new Buffer<float>(scanline.Length))
using (Buffer<TPixel> overlay = new Buffer<TPixel>(scanline.Length))
{
BufferSpan<float> slice = buffer.Slice(offset);
int sourceY = (y - this.offsetY) % this.yLength;
int offsetX = x - this.offsetX;
Span<TPixel> sourceRow = this.source.GetRowSpan(sourceY);
for (int xPos = 0; xPos < scanlineWidth; xPos++)
for (int i = 0; i < scanline.Length; i++)
{
int targetX = xPos + x;
int targetY = y;
float opacity = slice[xPos];
if (opacity > Constants.Epsilon)
{
Vector4 backgroundVector = this.Target[targetX, targetY].ToVector4();
Vector4 sourceVector = this[targetX, targetY].ToVector4();
amountBuffer[i] = scanline[i] * this.Options.BlendPercentage;
Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);
TColor packed = default(TColor);
packed.PackFromVector4(finalColor);
this.Target[targetX, targetY] = packed;
}
int sourceX = (i + offsetX) % this.xLength;
TPixel pixel = sourceRow[sourceX];
overlay[i] = pixel;
}
Span<TPixel> destinationRow = this.Target.GetRowSpan(x, y).Slice(0, scanline.Length);
this.Blender.Blend(destinationRow, destinationRow, overlay, amountBuffer);
}
}
}

33
src/ImageSharp.Drawing/Brushes/PatternBrush.cs

@ -1,33 +0,0 @@
// <copyright file="PatternBrush.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
/// <summary>
/// Provides an implementation of a pattern brush for painting patterns. The brush use <see cref="Color"/> for painting.
/// </summary>
public class PatternBrush : PatternBrush<Color>
{
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrush"/> class.
/// </summary>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="backColor">Color of the back.</param>
/// <param name="pattern">The pattern.</param>
public PatternBrush(Color foreColor, Color backColor, bool[,] pattern)
: base(foreColor, backColor, pattern)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrush"/> class.
/// </summary>
/// <param name="brush">The brush.</param>
internal PatternBrush(PatternBrush<Color> brush)
: base(brush)
{
}
}
}

75
src/ImageSharp.Drawing/Brushes/PatternBrush{TColor}.cs → src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs

@ -1,4 +1,4 @@
// <copyright file="PatternBrush{TColor}.cs" company="James Jackson-South">
// <copyright file="PatternBrush{TPixel}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -8,6 +8,8 @@ namespace ImageSharp.Drawing.Brushes
using System;
using System.Numerics;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
using Processors;
/// <summary>
@ -31,38 +33,38 @@ namespace ImageSharp.Drawing.Brushes
/// 0
/// </para>
/// </remarks>
/// <typeparam name="TColor">The pixel format.</typeparam>
public class PatternBrush<TColor> : IBrush<TColor>
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The pixel format.</typeparam>
public class PatternBrush<TPixel> : IBrush<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// The pattern.
/// </summary>
private readonly Fast2DArray<TColor> pattern;
private readonly Fast2DArray<TPixel> pattern;
private readonly Fast2DArray<Vector4> patternVector;
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrush{TColor}"/> class.
/// Initializes a new instance of the <see cref="PatternBrush{TPixel}"/> class.
/// </summary>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="backColor">Color of the back.</param>
/// <param name="pattern">The pattern.</param>
public PatternBrush(TColor foreColor, TColor backColor, bool[,] pattern)
public PatternBrush(TPixel foreColor, TPixel backColor, bool[,] pattern)
: this(foreColor, backColor, new Fast2DArray<bool>(pattern))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrush{TColor}"/> class.
/// Initializes a new instance of the <see cref="PatternBrush{TPixel}"/> class.
/// </summary>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="backColor">Color of the back.</param>
/// <param name="pattern">The pattern.</param>
internal PatternBrush(TColor foreColor, TColor backColor, Fast2DArray<bool> pattern)
internal PatternBrush(TPixel foreColor, TPixel backColor, Fast2DArray<bool> pattern)
{
Vector4 foreColorVector = foreColor.ToVector4();
Vector4 backColorVector = backColor.ToVector4();
this.pattern = new Fast2DArray<TColor>(pattern.Width, pattern.Height);
this.pattern = new Fast2DArray<TPixel>(pattern.Width, pattern.Height);
this.patternVector = new Fast2DArray<Vector4>(pattern.Width, pattern.Height);
for (int i = 0; i < pattern.Data.Length; i++)
{
@ -80,30 +82,30 @@ namespace ImageSharp.Drawing.Brushes
}
/// <summary>
/// Initializes a new instance of the <see cref="PatternBrush{TColor}"/> class.
/// Initializes a new instance of the <see cref="PatternBrush{TPixel}"/> class.
/// </summary>
/// <param name="brush">The brush.</param>
internal PatternBrush(PatternBrush<TColor> brush)
internal PatternBrush(PatternBrush<TPixel> brush)
{
this.pattern = brush.pattern;
this.patternVector = brush.patternVector;
}
/// <inheritdoc />
public BrushApplicator<TColor> CreateApplicator(PixelAccessor<TColor> sourcePixels, RectangleF region)
public BrushApplicator<TPixel> CreateApplicator(PixelAccessor<TPixel> sourcePixels, RectangleF region, GraphicsOptions options)
{
return new PatternBrushApplicator(sourcePixels, this.pattern, this.patternVector);
return new PatternBrushApplicator(sourcePixels, this.pattern, this.patternVector, options);
}
/// <summary>
/// The pattern brush applicator.
/// </summary>
private class PatternBrushApplicator : BrushApplicator<TColor>
private class PatternBrushApplicator : BrushApplicator<TPixel>
{
/// <summary>
/// The pattern.
/// </summary>
private readonly Fast2DArray<TColor> pattern;
private readonly Fast2DArray<TPixel> pattern;
private readonly Fast2DArray<Vector4> patternVector;
/// <summary>
@ -112,8 +114,9 @@ namespace ImageSharp.Drawing.Brushes
/// <param name="sourcePixels">The sourcePixels.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="patternVector">The patternVector.</param>
public PatternBrushApplicator(PixelAccessor<TColor> sourcePixels, Fast2DArray<TColor> pattern, Fast2DArray<Vector4> patternVector)
: base(sourcePixels)
/// <param name="options">The options</param>
public PatternBrushApplicator(PixelAccessor<TPixel> sourcePixels, Fast2DArray<TPixel> pattern, Fast2DArray<Vector4> patternVector, GraphicsOptions options)
: base(sourcePixels, options)
{
this.pattern = pattern;
this.patternVector = patternVector;
@ -127,7 +130,7 @@ namespace ImageSharp.Drawing.Brushes
/// <returns>
/// The Color.
/// </returns>
internal override TColor this[int x, int y]
internal override TPixel this[int x, int y]
{
get
{
@ -146,34 +149,22 @@ namespace ImageSharp.Drawing.Brushes
}
/// <inheritdoc />
internal override void Apply(float[] scanlineBuffer, int scanlineWidth, int offset, int x, int y)
internal override void Apply(Span<float> scanline, int x, int y)
{
Guard.MustBeGreaterThanOrEqualTo(scanlineBuffer.Length, offset + scanlineWidth, nameof(scanlineWidth));
using (PinnedBuffer<float> buffer = new PinnedBuffer<float>(scanlineBuffer))
int patternY = y % this.pattern.Height;
using (Buffer<float> amountBuffer = new Buffer<float>(scanline.Length))
using (Buffer<TPixel> overlay = new Buffer<TPixel>(scanline.Length))
{
BufferSpan<float> slice = buffer.Slice(offset);
for (int xPos = 0; xPos < scanlineWidth; xPos++)
for (int i = 0; i < scanline.Length; i++)
{
int targetX = xPos + x;
int targetY = y;
float opacity = slice[xPos];
if (opacity > Constants.Epsilon)
{
Vector4 backgroundVector = this.Target[targetX, targetY].ToVector4();
amountBuffer[i] = (scanline[i] * this.Options.BlendPercentage).Clamp(0, 1);
// 2d array index at row/column
Vector4 sourceVector = this.patternVector[targetY % this.patternVector.Height, targetX % this.patternVector.Width];
Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);
TColor packed = default(TColor);
packed.PackFromVector4(finalColor);
this.Target[targetX, targetY] = packed;
}
int patternX = (x + i) % this.pattern.Width;
overlay[i] = this.pattern[patternY, patternX];
}
Span<TPixel> destinationRow = this.Target.GetRowSpan(x, y).Slice(0, scanline.Length);
this.Blender.Blend(destinationRow, destinationRow, overlay, amountBuffer);
}
}
}

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

@ -7,37 +7,54 @@ namespace ImageSharp.Drawing.Processors
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
/// <summary>
/// primitive that converts a point in to a color for discovering the fill color based on an implementation
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <seealso cref="System.IDisposable" />
public abstract class BrushApplicator<TColor> : IDisposable // disposable will be required if/when there is an ImageBrush
where TColor : struct, IPixel<TColor>
public abstract class BrushApplicator<TPixel> : IDisposable // disposable will be required if/when there is an ImageBrush
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// Initializes a new instance of the <see cref="BrushApplicator{TColor}"/> class.
/// Initializes a new instance of the <see cref="BrushApplicator{TPixel}"/> class.
/// </summary>
/// <param name="target">The target.</param>
internal BrushApplicator(PixelAccessor<TColor> target)
/// <param name="options">The options.</param>
internal BrushApplicator(PixelAccessor<TPixel> target, GraphicsOptions options)
{
this.Target = target;
this.Options = options;
this.Blender = PixelOperations<TPixel>.Instance.GetPixelBlender(options.BlenderMode);
}
/// <summary>
/// Gets the blendder
/// </summary>
internal PixelBlender<TPixel> Blender { get; }
/// <summary>
/// Gets the destinaion
/// </summary>
protected PixelAccessor<TColor> Target { get; }
protected PixelAccessor<TPixel> Target { get; }
/// <summary>
/// Gets the blend percentage
/// </summary>
protected GraphicsOptions Options { get; private set; }
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <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>
internal abstract TColor this[int x, int y] { get; }
/// <returns>The a <typeparamref name="TPixel"/> that should be applied to the pixel.</returns>
internal abstract TPixel this[int x, int y] { get; }
/// <inheritdoc/>
public abstract void Dispose();
@ -45,39 +62,27 @@ namespace ImageSharp.Drawing.Processors
/// <summary>
/// Applies the opactiy weighting for each pixel in a scanline to the target based on the pattern contained in the brush.
/// </summary>
/// <param name="scanlineBuffer">The a collection of opacity values between 0 and 1 to be merged with the brushed color value before being applied to the target.</param>
/// <param name="scanlineWidth">The number of pixels effected by this scanline.</param>
/// <param name="offset">The offset fromthe begining of <paramref name="scanlineBuffer" /> the opacity data starts.</param>
/// <param name="scanline">The a collection of opacity values between 0 and 1 to be merged with the brushed color value before being applied to the target.</param>
/// <param name="x">The x position in the target pixel space that the start of the scanline data corresponds to.</param>
/// <param name="y">The y position in the target pixel space that whole scanline corresponds to.</param>
/// <remarks>scanlineBuffer will be > scanlineWidth but provide and offset in case we want to share a larger buffer across runs.</remarks>
internal virtual void Apply(float[] scanlineBuffer, int scanlineWidth, int offset, int x, int y)
internal virtual void Apply(Span<float> scanline, int x, int y)
{
DebugGuard.MustBeGreaterThanOrEqualTo(scanlineBuffer.Length, offset + scanlineWidth, nameof(scanlineWidth));
using (PinnedBuffer<float> buffer = new PinnedBuffer<float>(scanlineBuffer))
using (Buffer<float> amountBuffer = new Buffer<float>(scanline.Length))
using (Buffer<TPixel> overlay = new Buffer<TPixel>(scanline.Length))
{
BufferSpan<float> slice = buffer.Slice(offset);
for (int xPos = 0; xPos < scanlineWidth; xPos++)
for (int i = 0; i < scanline.Length; i++)
{
int targetX = xPos + x;
int targetY = y;
float opacity = slice[xPos];
if (opacity > Constants.Epsilon)
if (this.Options.BlendPercentage < 1)
{
Vector4 backgroundVector = this.Target[targetX, targetY].ToVector4();
Vector4 sourceVector = this[targetX, targetY].ToVector4();
Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);
TColor packed = default(TColor);
packed.PackFromVector4(finalColor);
this.Target[targetX, targetY] = packed;
amountBuffer[i] = scanline[i] * this.Options.BlendPercentage;
}
overlay[i] = this[x + i, y];
}
Span<TPixel> destinationRow = this.Target.GetRowSpan(x, y).Slice(0, scanline.Length);
this.Blender.Blend(destinationRow, destinationRow, overlay, amountBuffer);
}
}
}

24
src/ImageSharp.Drawing/Brushes/RecolorBrush.cs

@ -1,24 +0,0 @@
// <copyright file="RecolorBrush.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
/// <summary>
/// Provides an implementation of a recolor brush for painting color changes.
/// </summary>
public class RecolorBrush : RecolorBrush<Color>
{
/// <summary>
/// Initializes a new instance of the <see cref="RecolorBrush" /> class.
/// </summary>
/// <param name="sourceColor">Color of the source.</param>
/// <param name="targetColor">Color of the target.</param>
/// <param name="threshold">The threshold.</param>
public RecolorBrush(Color sourceColor, Color targetColor, float threshold)
: base(sourceColor, targetColor, threshold)
{
}
}
}

97
src/ImageSharp.Drawing/Brushes/RecolorBrush{TColor}.cs → src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs

@ -1,4 +1,4 @@
// <copyright file="RecolorBrush{TColor}.cs" company="James Jackson-South">
// <copyright file="RecolorBrush{TPixel}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -8,26 +8,28 @@ namespace ImageSharp.Drawing.Brushes
using System;
using System.Numerics;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
using Processors;
/// <summary>
/// Provides an implementation of a brush that can recolor an image
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
public class RecolorBrush<TColor> : IBrush<TColor>
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The pixel format.</typeparam>
public class RecolorBrush<TPixel> : IBrush<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// Initializes a new instance of the <see cref="RecolorBrush{TColor}" /> class.
/// Initializes a new instance of the <see cref="RecolorBrush{TPixel}" /> class.
/// </summary>
/// <param name="sourceColor">Color of the source.</param>
/// <param name="targetColor">Color of the target.</param>
/// <param name="targeTPixel">Color of the target.</param>
/// <param name="threshold">The threshold as a value between 0 and 1.</param>
public RecolorBrush(TColor sourceColor, TColor targetColor, float threshold)
public RecolorBrush(TPixel sourceColor, TPixel targeTPixel, float threshold)
{
this.SourceColor = sourceColor;
this.Threshold = threshold;
this.TargetColor = targetColor;
this.TargeTPixel = targeTPixel;
}
/// <summary>
@ -44,7 +46,7 @@ namespace ImageSharp.Drawing.Brushes
/// <value>
/// The color of the source.
/// </value>
public TColor SourceColor { get; }
public TPixel SourceColor { get; }
/// <summary>
/// Gets the target color.
@ -52,18 +54,18 @@ namespace ImageSharp.Drawing.Brushes
/// <value>
/// The color of the target.
/// </value>
public TColor TargetColor { get; }
public TPixel TargeTPixel { get; }
/// <inheritdoc />
public BrushApplicator<TColor> CreateApplicator(PixelAccessor<TColor> sourcePixels, RectangleF region)
public BrushApplicator<TPixel> CreateApplicator(PixelAccessor<TPixel> sourcePixels, RectangleF region, GraphicsOptions options)
{
return new RecolorBrushApplicator(sourcePixels, this.SourceColor, this.TargetColor, this.Threshold);
return new RecolorBrushApplicator(sourcePixels, this.SourceColor, this.TargeTPixel, this.Threshold, options);
}
/// <summary>
/// The recolor brush applicator.
/// </summary>
private class RecolorBrushApplicator : BrushApplicator<TColor>
private class RecolorBrushApplicator : BrushApplicator<TPixel>
{
/// <summary>
/// The source color.
@ -80,6 +82,8 @@ namespace ImageSharp.Drawing.Brushes
/// </summary>
private readonly float threshold;
private readonly TPixel targetColorPixel;
/// <summary>
/// Initializes a new instance of the <see cref="RecolorBrushApplicator" /> class.
/// </summary>
@ -87,16 +91,18 @@ namespace ImageSharp.Drawing.Brushes
/// <param name="sourceColor">Color of the source.</param>
/// <param name="targetColor">Color of the target.</param>
/// <param name="threshold">The threshold .</param>
public RecolorBrushApplicator(PixelAccessor<TColor> sourcePixels, TColor sourceColor, TColor targetColor, float threshold)
: base(sourcePixels)
/// <param name="options">The options</param>
public RecolorBrushApplicator(PixelAccessor<TPixel> sourcePixels, TPixel sourceColor, TPixel targetColor, float threshold, GraphicsOptions options)
: base(sourcePixels, options)
{
this.sourceColor = sourceColor.ToVector4();
this.targetColor = targetColor.ToVector4();
this.targetColorPixel = targetColor;
// Lets hack a min max extreams for a color space by letteing the IPackedPixel clamp our values to something in the correct spaces :)
TColor maxColor = default(TColor);
TPixel maxColor = default(TPixel);
maxColor.PackFromVector4(new Vector4(float.MaxValue));
TColor minColor = default(TColor);
TPixel minColor = default(TPixel);
minColor.PackFromVector4(new Vector4(float.MinValue));
this.threshold = Vector4.DistanceSquared(maxColor.ToVector4(), minColor.ToVector4()) * threshold;
}
@ -109,22 +115,21 @@ namespace ImageSharp.Drawing.Brushes
/// <returns>
/// The color
/// </returns>
internal override TColor this[int x, int y]
internal override TPixel this[int x, int y]
{
get
{
// Offset the requested pixel by the value in the rectangle (the shapes position)
TColor result = this.Target[x, y];
TPixel result = this.Target[x, y];
Vector4 background = result.ToVector4();
float distance = Vector4.DistanceSquared(background, this.sourceColor);
if (distance <= this.threshold)
{
float lerpAmount = (this.threshold - distance) / this.threshold;
Vector4 blended = Vector4BlendTransforms.PremultipliedLerp(
background,
this.targetColor,
return this.Blender.Blend(
result,
this.targetColorPixel,
lerpAmount);
result.PackFromVector4(blended);
}
return result;
@ -137,42 +142,24 @@ namespace ImageSharp.Drawing.Brushes
}
/// <inheritdoc />
internal override void Apply(float[] scanlineBuffer, int scanlineWidth, int offset, int x, int y)
internal override void Apply(Span<float> scanline, int x, int y)
{
Guard.MustBeGreaterThanOrEqualTo(scanlineBuffer.Length, offset + scanlineWidth, nameof(scanlineWidth));
using (PinnedBuffer<float> buffer = new PinnedBuffer<float>(scanlineBuffer))
using (Buffer<float> amountBuffer = new Buffer<float>(scanline.Length))
using (Buffer<TPixel> overlay = new Buffer<TPixel>(scanline.Length))
{
BufferSpan<float> slice = buffer.Slice(offset);
for (int xPos = 0; xPos < scanlineWidth; xPos++)
for (int i = 0; i < scanline.Length; i++)
{
int targetX = xPos + x;
int targetY = y;
float opacity = slice[xPos];
if (opacity > Constants.Epsilon)
{
Vector4 backgroundVector = this.Target[targetX, targetY].ToVector4();
Vector4 sourceVector = backgroundVector;
float distance = Vector4.DistanceSquared(sourceVector, this.sourceColor);
if (distance <= this.threshold)
{
float lerpAmount = (this.threshold - distance) / this.threshold;
sourceVector = Vector4BlendTransforms.PremultipliedLerp(
sourceVector,
this.targetColor,
lerpAmount);
Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);
TColor packed = default(TColor);
packed.PackFromVector4(finalColor);
this.Target[targetX, targetY] = packed;
}
}
amountBuffer[i] = scanline[i] * this.Options.BlendPercentage;
int offsetX = x + i;
// no doubt this one can be optermised further but I can't imagine its
// actually being used and can probably be removed/interalised for now
overlay[i] = this[offsetX, y];
}
Span<TPixel> destinationRow = this.Target.GetRowSpan(x, y).Slice(0, scanline.Length);
this.Blender.Blend(destinationRow, destinationRow, overlay, amountBuffer);
}
}
}

22
src/ImageSharp.Drawing/Brushes/SolidBrush.cs

@ -1,22 +0,0 @@
// <copyright file="SolidBrush.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
/// <summary>
/// Provides an implementation of a solid brush for painting solid color areas. The brush uses <see cref="Color"/> for painting.
/// </summary>
public class SolidBrush : SolidBrush<Color>
{
/// <summary>
/// Initializes a new instance of the <see cref="SolidBrush" /> class.
/// </summary>
/// <param name="color">The color.</param>
public SolidBrush(Color color)
: base(color)
{
}
}
}

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

@ -1,118 +0,0 @@
// <copyright file="SolidBrush{TColor}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
using System;
using System.Numerics;
using Processors;
/// <summary>
/// Provides an implementation of a solid brush for painting solid color areas.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
public class SolidBrush<TColor> : IBrush<TColor>
where TColor : struct, IPixel<TColor>
{
/// <summary>
/// The color to paint.
/// </summary>
private readonly TColor color;
/// <summary>
/// Initializes a new instance of the <see cref="SolidBrush{TColor}"/> class.
/// </summary>
/// <param name="color">The color.</param>
public SolidBrush(TColor color)
{
this.color = color;
}
/// <summary>
/// Gets the color.
/// </summary>
/// <value>
/// The color.
/// </value>
public TColor Color => this.color;
/// <inheritdoc />
public BrushApplicator<TColor> CreateApplicator(PixelAccessor<TColor> sourcePixels, RectangleF region)
{
return new SolidBrushApplicator(sourcePixels, this.color);
}
/// <summary>
/// The solid brush applicator.
/// </summary>
private class SolidBrushApplicator : BrushApplicator<TColor>
{
/// <summary>
/// The solid color.
/// </summary>
private readonly TColor color;
private readonly Vector4 colorVector;
/// <summary>
/// Initializes a new instance of the <see cref="SolidBrushApplicator"/> class.
/// </summary>
/// <param name="color">The color.</param>
/// <param name="sourcePixels">The sourcePixels.</param>
public SolidBrushApplicator(PixelAccessor<TColor> sourcePixels, TColor color)
: base(sourcePixels)
{
this.color = color;
this.colorVector = color.ToVector4();
}
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The color
/// </returns>
internal override TColor this[int x, int y] => this.color;
/// <inheritdoc />
public override void Dispose()
{
// noop
}
/// <inheritdoc />
internal override void Apply(float[] scanlineBuffer, int scanlineWidth, int offset, int x, int y)
{
Guard.MustBeGreaterThanOrEqualTo(scanlineBuffer.Length, offset + scanlineWidth, nameof(scanlineWidth));
using (PinnedBuffer<float> buffer = new PinnedBuffer<float>(scanlineBuffer))
{
BufferSpan<float> slice = buffer.Slice(offset);
for (int xPos = 0; xPos < scanlineWidth; xPos++)
{
int targetX = xPos + x;
int targetY = y;
float opacity = slice[xPos];
if (opacity > Constants.Epsilon)
{
Vector4 backgroundVector = this.Target[targetX, targetY].ToVector4();
Vector4 sourceVector = this.colorVector;
Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);
TColor packed = default(TColor);
packed.PackFromVector4(finalColor);
this.Target[targetX, targetY] = packed;
}
}
}
}
}
}
}

109
src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs

@ -0,0 +1,109 @@
// <copyright file="SolidBrush{TPixel}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Brushes
{
using System;
using System.Numerics;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
using Processors;
/// <summary>
/// Provides an implementation of a solid brush for painting solid color areas.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
public class SolidBrush<TPixel> : IBrush<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// The color to paint.
/// </summary>
private readonly TPixel color;
/// <summary>
/// Initializes a new instance of the <see cref="SolidBrush{TPixel}"/> class.
/// </summary>
/// <param name="color">The color.</param>
public SolidBrush(TPixel color)
{
this.color = color;
}
/// <summary>
/// Gets the color.
/// </summary>
/// <value>
/// The color.
/// </value>
public TPixel Color => this.color;
/// <inheritdoc />
public BrushApplicator<TPixel> CreateApplicator(PixelAccessor<TPixel> sourcePixels, RectangleF region, GraphicsOptions options)
{
return new SolidBrushApplicator(sourcePixels, this.color, options);
}
/// <summary>
/// The solid brush applicator.
/// </summary>
private class SolidBrushApplicator : BrushApplicator<TPixel>
{
/// <summary>
/// Initializes a new instance of the <see cref="SolidBrushApplicator"/> class.
/// </summary>
/// <param name="color">The color.</param>
/// <param name="options">The options</param>
/// <param name="sourcePixels">The sourcePixels.</param>
public SolidBrushApplicator(PixelAccessor<TPixel> sourcePixels, TPixel color, GraphicsOptions options)
: base(sourcePixels, options)
{
this.Colors = new Buffer<TPixel>(sourcePixels.Width);
for (int i = 0; i < this.Colors.Length; i++)
{
this.Colors[i] = color;
}
}
/// <summary>
/// Gets the colors.
/// </summary>
protected Buffer<TPixel> Colors { get; }
/// <summary>
/// Gets the color for a single pixel.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns>
/// The color
/// </returns>
internal override TPixel this[int x, int y] => this.Colors[x];
/// <inheritdoc />
public override void Dispose()
{
this.Colors.Dispose();
}
/// <inheritdoc />
internal override void Apply(Span<float> scanline, int x, int y)
{
Span<TPixel> destinationRow = this.Target.GetRowSpan(x, y).Slice(0, scanline.Length);
using (Buffer<float> amountBuffer = new Buffer<float>(scanline.Length))
{
for (int i = 0; i < scanline.Length; i++)
{
amountBuffer[i] = scanline[i] * this.Options.BlendPercentage;
}
this.Blender.Blend(destinationRow, destinationRow, this.Colors, amountBuffer);
}
}
}
}
}

185
src/ImageSharp.Drawing/DrawImage.cs

@ -1,58 +1,129 @@
// <copyright file="DrawImage.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 Drawing.Processors;
/// <summary>
/// Extension methods for the <see cref="Image"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Draws the given image together with the current one by blending their pixels.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 100.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> Blend<TColor>(this Image<TColor> source, Image<TColor> image, int percent = 50)
where TColor : struct, IPixel<TColor>
{
return DrawImage(source, image, percent, default(Size), default(Point));
}
/// <summary>
/// Draws the given image together with the current one by blending their pixels.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 100.</param>
/// <param name="size">The size to draw the blended image.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <returns>The <see cref="Image{TColor}"/>.</returns>
public static Image<TColor> DrawImage<TColor>(this Image<TColor> source, Image<TColor> image, int percent, Size size, Point location)
where TColor : struct, IPixel<TColor>
{
if (size == default(Size))
{
size = new Size(image.Width, image.Height);
}
if (location == default(Point))
{
location = Point.Empty;
}
source.ApplyProcessor(new DrawImageProcessor<TColor>(image, size, location, percent), source.Bounds);
return source;
}
}
// <copyright file="DrawImage.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using Drawing.Processors;
using ImageSharp.PixelFormats;
/// <summary>
/// Extension methods for the <see cref="Image{TPixel}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Draws the given image together with the current one by blending their pixels.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="size">The size to draw the blended image.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <param name="options">The options.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawImage<TPixel>(this Image<TPixel> source, Image<TPixel> image, Size size, Point location, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
if (size == default(Size))
{
size = new Size(image.Width, image.Height);
}
if (location == default(Point))
{
location = Point.Empty;
}
source.ApplyProcessor(new DrawImageProcessor<TPixel>(image, size, location, options), source.Bounds);
return source;
}
/// <summary>
/// Draws the given image together with the current one by blending their pixels.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Blend<TPixel>(this Image<TPixel> source, Image<TPixel> image, float percent)
where TPixel : struct, IPixel<TPixel>
{
GraphicsOptions options = GraphicsOptions.Default;
options.BlendPercentage = percent;
return DrawImage(source, image, default(Size), default(Point), options);
}
/// <summary>
/// Draws the given image together with the current one by blending their pixels.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="blender">The blending mode.</param>
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Blend<TPixel>(this Image<TPixel> source, Image<TPixel> image, PixelBlenderMode blender, float percent)
where TPixel : struct, IPixel<TPixel>
{
GraphicsOptions options = GraphicsOptions.Default;
options.BlendPercentage = percent;
options.BlenderMode = blender;
return DrawImage(source, image, default(Size), default(Point), options);
}
/// <summary>
/// Draws the given image together with the current one by blending their pixels.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="options">The options, including the blending type and belnding amount.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Blend<TPixel>(this Image<TPixel> source, Image<TPixel> image, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return DrawImage(source, image, default(Size), default(Point), options);
}
/// <summary>
/// Draws the given image together with the current one by blending their pixels.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
/// <param name="size">The size to draw the blended image.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawImage<TPixel>(this Image<TPixel> source, Image<TPixel> image, float percent, Size size, Point location)
where TPixel : struct, IPixel<TPixel>
{
GraphicsOptions options = GraphicsOptions.Default;
options.BlendPercentage = percent;
return source.DrawImage(image, size, location, options);
}
/// <summary>
/// Draws the given image together with the current one by blending their pixels.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="blender">The type of bending to apply.</param>
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 1.</param>
/// <param name="size">The size to draw the blended image.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawImage<TPixel>(this Image<TPixel> source, Image<TPixel> image, PixelBlenderMode blender, float percent, Size size, Point location)
where TPixel : struct, IPixel<TPixel>
{
GraphicsOptions options = GraphicsOptions.Default;
options.BlenderMode = blender;
options.BlendPercentage = percent;
return source.DrawImage(image, size, location, options);
}
}
}

63
src/ImageSharp.Drawing/DrawPath.cs

@ -5,43 +5,42 @@
namespace ImageSharp
{
using System;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using Drawing.Processors;
using ImageSharp.PixelFormats;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> 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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, Drawable path, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Apply(new DrawPathProcessor<TColor>(pen, path, options));
return source.Apply(new DrawPathProcessor<TPixel>(pen, path, options));
}
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, Drawable path)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, path, GraphicsOptions.Default);
}
@ -49,63 +48,63 @@ namespace ImageSharp
/// <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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, Drawable path, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), path, options);
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, Drawable path)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), path);
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, TPixel color, float thickness, Drawable path, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, path, options);
return source.Draw(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, TPixel color, float thickness, Drawable path)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, path);
return source.Draw(new SolidBrush<TPixel>(color), thickness, path);
}
}
}

77
src/ImageSharp.Drawing/FillRegion.cs

@ -5,68 +5,81 @@
namespace ImageSharp
{
using System;
using Drawing;
using Drawing.Brushes;
using Drawing.Processors;
using ImageSharp.PixelFormats;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> 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>
/// <typeparam name="TPixel">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>
/// <param name="options">The graphics options.</param>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Apply(new FillProcessor<TPixel>(brush, options));
}
/// <summary>
/// Flood fills the image with the specified brush.
/// </summary>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush)
where TPixel : struct, IPixel<TPixel>
{
return source.Apply(new FillProcessor<TColor>(brush));
return source.Fill(brush, GraphicsOptions.Default);
}
/// <summary>
/// Flood fills the image with the specified color.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(new SolidBrush<TColor>(color));
return source.Fill(new SolidBrush<TPixel>(color));
}
/// <summary>
/// Flood fills the image with in the region with the specified brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, Region region, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Apply(new FillRegionProcessor<TColor>(brush, region, options));
return source.Apply(new FillRegionProcessor<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, Region region)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(brush, region, GraphicsOptions.Default);
}
@ -74,30 +87,30 @@ namespace ImageSharp
/// <summary>
/// Flood fills the image with in the region with the specified color.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color, Region region, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(new SolidBrush<TColor>(color), region, options);
return source.Fill(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color, Region region)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(new SolidBrush<TColor>(color), region);
return source.Fill(new SolidBrush<TPixel>(color), region);
}
}
}

38
src/ImageSharp.Drawing/GraphicsOptions.cs

@ -1,38 +0,0 @@
// <copyright file="GraphicsOptions.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>
/// Options for influencing the drawing functions.
/// </summary>
public struct GraphicsOptions
{
/// <summary>
/// Represents the default <see cref="GraphicsOptions"/>.
/// </summary>
public static readonly GraphicsOptions Default = new GraphicsOptions(true);
/// <summary>
/// Whether antialiasing should be applied.
/// </summary>
public bool Antialias;
/// <summary>
/// The number of subpixels to use while rendering with antialiasing enabled.
/// </summary>
public int AntialiasSubpixelDepth;
/// <summary>
/// Initializes a new instance of the <see cref="GraphicsOptions"/> struct.
/// </summary>
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
public GraphicsOptions(bool enableAntialiasing)
{
this.Antialias = enableAntialiasing;
this.AntialiasSubpixelDepth = 16;
}
}
}

6
src/ImageSharp.Drawing/ImageSharp.Drawing.csproj

@ -2,7 +2,7 @@
<PropertyGroup>
<Description>An extension to ImageSharp that allows the drawing of images, paths, and text.</Description>
<AssemblyTitle>ImageSharp.Drawing</AssemblyTitle>
<VersionPrefix>1.0.0-alpha5</VersionPrefix>
<VersionPrefix>1.0.0-alpha9</VersionPrefix>
<Authors>James Jackson-South and contributors</Authors>
<TargetFramework>netstandard1.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -39,8 +39,8 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta001">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="SixLabors.Fonts" Version="0.1.0-alpha0002" />
<PackageReference Include="SixLabors.Shapes" Version="0.1.0-alpha0009" />
<PackageReference Include="SixLabors.Fonts" Version="0.1.0-alpha0010" />
<PackageReference Include="SixLabors.Shapes" Version="0.1.0-alpha0012" />
</ItemGroup>
<PropertyGroup>
<CodeAnalysisRuleSet>..\..\ImageSharp.ruleset</CodeAnalysisRuleSet>

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

@ -5,92 +5,91 @@
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using ImageSharp.PixelFormats;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> 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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawBeziers<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Path(new BezierLineSegment(points)), options);
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawBeziers<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Path(new BezierLineSegment(points)));
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawBeziers<TPixel>(this Image<TPixel> source, TPixel color, float thickness, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawBeziers(new SolidBrush<TColor>(color), thickness, points);
return source.DrawBeziers(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawBeziers<TPixel>(this Image<TPixel> source, TPixel color, float thickness, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawBeziers(new SolidBrush<TColor>(color), thickness, points, options);
return source.DrawBeziers(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawBeziers<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, new Path(new BezierLineSegment(points)), options);
}
@ -98,13 +97,13 @@ namespace ImageSharp
/// <summary>
/// Draws the provided Points as an open Bezier path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawBeziers<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, new Path(new BezierLineSegment(points)));
}

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

@ -5,92 +5,91 @@
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using ImageSharp.PixelFormats;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> 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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawLines<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Path(new LinearLineSegment(points)), options);
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawLines<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Path(new LinearLineSegment(points)));
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawLines<TPixel>(this Image<TPixel> source, TPixel color, float thickness, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawLines(new SolidBrush<TColor>(color), thickness, points);
return source.DrawLines(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> DrawLines<TPixel>(this Image<TPixel> source, TPixel color, float thickness, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawLines(new SolidBrush<TColor>(color), thickness, points, options);
return source.DrawLines(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawLines<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, new Path(new LinearLineSegment(points)), options);
}
@ -98,13 +97,13 @@ namespace ImageSharp
/// <summary>
/// Draws the provided Points as an open Linear path with the supplied pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawLines<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, new Path(new LinearLineSegment(points)));
}

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

@ -5,30 +5,28 @@
namespace ImageSharp
{
using System;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using ImageSharp.PixelFormats;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> 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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, IPath path, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, new ShapePath(path), options);
}
@ -36,13 +34,13 @@ namespace ImageSharp
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, IPath path)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, path, GraphicsOptions.Default);
}
@ -50,63 +48,63 @@ namespace ImageSharp
/// <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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, IPath path, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), path, options);
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, IPath path)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), path);
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, TPixel color, float thickness, IPath path, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, path, options);
return source.Draw(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, TPixel color, float thickness, IPath path)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, path);
return source.Draw(new SolidBrush<TPixel>(color), thickness, path);
}
}
}

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

@ -5,91 +5,90 @@
namespace ImageSharp
{
using System;
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using ImageSharp.PixelFormats;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> 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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawPolygon<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Polygon(new LinearLineSegment(points)), options);
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawPolygon<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), new Polygon(new LinearLineSegment(points)));
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawPolygon<TPixel>(this Image<TPixel> source, TPixel color, float thickness, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawPolygon(new SolidBrush<TColor>(color), thickness, points);
return source.DrawPolygon(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawPolygon<TPixel>(this Image<TPixel> source, TPixel color, float thickness, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawPolygon(new SolidBrush<TColor>(color), thickness, points, options);
return source.DrawPolygon(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawPolygon<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, new Polygon(new LinearLineSegment(points)), GraphicsOptions.Default);
}
@ -97,14 +96,14 @@ namespace ImageSharp
/// <summary>
/// Draws the provided Points as a closed Linear Polygon with the provided Pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> DrawPolygon<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, new Polygon(new LinearLineSegment(points)), options);
}

61
src/ImageSharp.Drawing/Paths/DrawRectangle.cs

@ -5,28 +5,27 @@
namespace ImageSharp
{
using System;
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using ImageSharp.PixelFormats;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> 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>
/// <typeparam name="TPixel">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, Rectangle shape, GraphicsOptions options)
where TColor : struct, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, Rectangle shape, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, new SixLabors.Shapes.Rectangle(shape.X, shape.Y, shape.Width, shape.Height), options);
}
@ -34,13 +33,13 @@ namespace ImageSharp
/// <summary>
/// Draws the outline of the polygon with the provided pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">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, Rectangle shape)
where TColor : struct, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IPen<TPixel> pen, Rectangle shape)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(pen, shape, GraphicsOptions.Default);
}
@ -48,63 +47,63 @@ namespace ImageSharp
/// <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>
/// <typeparam name="TPixel">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, Rectangle shape, GraphicsOptions options)
where TColor : struct, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, Rectangle shape, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), shape, options);
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, Rectangle shape)
where TColor : struct, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, float thickness, Rectangle shape)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new Pen<TColor>(brush, thickness), shape);
return source.Draw(new Pen<TPixel>(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>
/// <typeparam name="TPixel">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, Rectangle shape, GraphicsOptions options)
where TColor : struct, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, TPixel color, float thickness, Rectangle shape, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, shape, options);
return source.Draw(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, Rectangle shape)
where TColor : struct, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Draw<TPixel>(this Image<TPixel> source, TPixel color, float thickness, Rectangle shape)
where TPixel : struct, IPixel<TPixel>
{
return source.Draw(new SolidBrush<TColor>(color), thickness, shape);
return source.Draw(new SolidBrush<TPixel>(color), thickness, shape);
}
}
}

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

@ -5,29 +5,27 @@
namespace ImageSharp
{
using System;
using Drawing;
using Drawing.Brushes;
using ImageSharp.PixelFormats;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> 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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, IPath path, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(brush, new ShapeRegion(path), options);
}
@ -35,13 +33,13 @@ namespace ImageSharp
/// <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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, IPath path)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(brush, new ShapeRegion(path), GraphicsOptions.Default);
}
@ -49,30 +47,30 @@ namespace ImageSharp
/// <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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color, IPath path, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(new SolidBrush<TColor>(color), path, options);
return source.Fill(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color, IPath path)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(new SolidBrush<TColor>(color), path);
return source.Fill(new SolidBrush<TPixel>(color), path);
}
}
}

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

@ -9,25 +9,25 @@ namespace ImageSharp
using System.Numerics;
using Drawing;
using Drawing.Brushes;
using ImageSharp.PixelFormats;
using SixLabors.Shapes;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> 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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> FillPolygon<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(brush, new Polygon(new LinearLineSegment(points)), options);
}
@ -35,13 +35,13 @@ namespace ImageSharp
/// <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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> FillPolygon<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(brush, new Polygon(new LinearLineSegment(points)));
}
@ -49,30 +49,30 @@ namespace ImageSharp
/// <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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> FillPolygon<TPixel>(this Image<TPixel> source, TPixel color, Vector2[] points, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(new SolidBrush<TColor>(color), new Polygon(new LinearLineSegment(points)), options);
return source.Fill(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> FillPolygon<TPixel>(this Image<TPixel> source, TPixel color, Vector2[] points)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(new SolidBrush<TColor>(color), new Polygon(new LinearLineSegment(points)));
return source.Fill(new SolidBrush<TPixel>(color), new Polygon(new LinearLineSegment(points)));
}
}
}

41
src/ImageSharp.Drawing/Paths/FillRectangle.cs

@ -5,27 +5,26 @@
namespace ImageSharp
{
using System;
using Drawing;
using Drawing.Brushes;
using ImageSharp.PixelFormats;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> 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>
/// <typeparam name="TPixel">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 options.</param>
/// <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, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, Rectangle shape, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(brush, new SixLabors.Shapes.Rectangle(shape.X, shape.Y, shape.Width, shape.Height), options);
}
@ -33,13 +32,13 @@ namespace ImageSharp
/// <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>
/// <typeparam name="TPixel">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, Rectangle shape)
where TColor : struct, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, Rectangle shape)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(brush, new SixLabors.Shapes.Rectangle(shape.X, shape.Y, shape.Width, shape.Height));
}
@ -47,30 +46,30 @@ namespace ImageSharp
/// <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>
/// <typeparam name="TPixel">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, Rectangle shape, GraphicsOptions options)
where TColor : struct, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color, Rectangle shape, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(new SolidBrush<TColor>(color), shape, options);
return source.Fill(new SolidBrush<TPixel>(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>
/// <typeparam name="TPixel">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, Rectangle shape)
where TColor : struct, IPixel<TColor>
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color, Rectangle shape)
where TPixel : struct, IPixel<TPixel>
{
return source.Fill(new SolidBrush<TColor>(color), shape);
return source.Fill(new SolidBrush<TPixel>(color), shape);
}
}
}

11
src/ImageSharp.Drawing/Pens/IPen.cs

@ -5,27 +5,28 @@
namespace ImageSharp.Drawing.Pens
{
using System;
using ImageSharp.PixelFormats;
using Processors;
/// <summary>
/// Interface representing a Pen
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
public interface IPen<TColor>
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The type of the color.</typeparam>
public interface IPen<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// Creates the applicator for applying this pen to an Image
/// </summary>
/// <param name="pixelSource">The pixel source.</param>
/// <param name="region">The region the pen will be applied to.</param>
/// <param name="options">The currently active graphic options.</param>
/// <returns>
/// Returns a the applicator for the pen.
/// </returns>
/// <remarks>
/// The <paramref name="region" /> when being applied to things like shapes would usually be the bounding box of the shape not necessarily the shape of the whole image.
/// </remarks>
PenApplicator<TColor> CreateApplicator(PixelAccessor<TColor> pixelSource, RectangleF region);
PenApplicator<TPixel> CreateApplicator(PixelAccessor<TPixel> pixelSource, RectangleF region, GraphicsOptions options);
}
}

53
src/ImageSharp.Drawing/Pens/Pen.cs

@ -1,53 +0,0 @@
// <copyright file="Pen.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Pens
{
/// <summary>
/// Represents a <see cref="Pen{TColor}"/> in the <see cref="Color"/> color space.
/// </summary>
public class Pen : Pen<Color>
{
/// <summary>
/// Initializes a new instance of the <see cref="Pen"/> class.
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
public Pen(Color color, float width)
: base(color, width)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Pen"/> class.
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
public Pen(IBrush<Color> brush, float width)
: base(brush, width)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Pen"/> class.
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <param name="pattern">The pattern.</param>
public Pen(IBrush<Color> brush, float width, float[] pattern)
: base(brush, width, pattern)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Pen"/> class.
/// </summary>
/// <param name="pen">The pen.</param>
internal Pen(Pen<Color> pen)
: base(pen)
{
}
}
}

59
src/ImageSharp.Drawing/Pens/Pens.cs

@ -5,89 +5,126 @@
namespace ImageSharp.Drawing.Pens
{
using ImageSharp.PixelFormats;
/// <summary>
/// Common Pen styles
/// </summary>
public class Pens
public static class Pens
{
private static readonly float[] DashDotPattern = new[] { 3f, 1f, 1f, 1f };
private static readonly float[] DashDotDotPattern = new[] { 3f, 1f, 1f, 1f, 1f, 1f };
private static readonly float[] DottedPattern = new[] { 1f, 1f };
private static readonly float[] DashedPattern = new[] { 3f, 1f };
/// <summary>
/// Create a solid pen with out any drawing patterns
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <returns>The Pen</returns>
public static Pen Solid(Color color, float width) => new Pen(color, width);
public static Pen<TPixel> Solid<TPixel>(TPixel color, float width)
where TPixel : struct, IPixel<TPixel>
=> new Pen<TPixel>(color, width);
/// <summary>
/// Create a solid pen with out any drawing patterns
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <returns>The Pen</returns>
public static Pen Solid(IBrush<Color> brush, float width) => new Pen(brush, width);
public static Pen<TPixel> Solid<TPixel>(IBrush<TPixel> brush, float width)
where TPixel : struct, IPixel<TPixel>
=> new Pen<TPixel>(brush, width);
/// <summary>
/// Create a pen with a 'Dash' drawing patterns
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <returns>The Pen</returns>
public static Pen Dash(Color color, float width) => new Pen(Pens<Color>.Dash(color, width));
public static Pen<TPixel> Dash<TPixel>(TPixel color, float width)
where TPixel : struct, IPixel<TPixel>
=> new Pen<TPixel>(color, width, DashedPattern);
/// <summary>
/// Create a pen with a 'Dash' drawing patterns
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <returns>The Pen</returns>
public static Pen Dash(IBrush<Color> brush, float width) => new Pen(Pens<Color>.Dash(brush, width));
public static Pen<TPixel> Dash<TPixel>(IBrush<TPixel> brush, float width)
where TPixel : struct, IPixel<TPixel>
=> new Pen<TPixel>(brush, width, DashedPattern);
/// <summary>
/// Create a pen with a 'Dot' drawing patterns
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <returns>The Pen</returns>
public static Pen Dot(Color color, float width) => new Pen(Pens<Color>.Dot(color, width));
public static Pen<TPixel> Dot<TPixel>(TPixel color, float width)
where TPixel : struct, IPixel<TPixel>
=> new Pen<TPixel>(color, width, DottedPattern);
/// <summary>
/// Create a pen with a 'Dot' drawing patterns
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <returns>The Pen</returns>
public static Pen Dot(IBrush<Color> brush, float width) => new Pen(Pens<Color>.Dot(brush, width));
public static Pen<TPixel> Dot<TPixel>(IBrush<TPixel> brush, float width)
where TPixel : struct, IPixel<TPixel>
=> new Pen<TPixel>(brush, width, DottedPattern);
/// <summary>
/// Create a pen with a 'Dash Dot' drawing patterns
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <returns>The Pen</returns>
public static Pen DashDot(Color color, float width) => new Pen(Pens<Color>.DashDot(color, width));
public static Pen<TPixel> DashDot<TPixel>(TPixel color, float width)
where TPixel : struct, IPixel<TPixel>
=> new Pen<TPixel>(color, width, DashDotPattern);
/// <summary>
/// Create a pen with a 'Dash Dot' drawing patterns
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <returns>The Pen</returns>
public static Pen DashDot(IBrush<Color> brush, float width) => new Pen(Pens<Color>.DashDot(brush, width));
public static Pen<TPixel> DashDot<TPixel>(IBrush<TPixel> brush, float width)
where TPixel : struct, IPixel<TPixel>
=> new Pen<TPixel>(brush, width, DashDotPattern);
/// <summary>
/// Create a pen with a 'Dash Dot Dot' drawing patterns
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <returns>The Pen</returns>
public static Pen DashDotDot(Color color, float width) => new Pen(Pens<Color>.DashDotDot(color, width));
public static Pen<TPixel> DashDotDot<TPixel>(TPixel color, float width)
where TPixel : struct, IPixel<TPixel>
=> new Pen<TPixel>(color, width, DashDotDotPattern);
/// <summary>
/// Create a pen with a 'Dash Dot Dot' drawing patterns
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <returns>The Pen</returns>
public static Pen DashDotDot(IBrush<Color> brush, float width) => new Pen(Pens<Color>.DashDotDot(brush, width));
public static Pen<TPixel> DashDotDot<TPixel>(IBrush<TPixel> brush, float width)
where TPixel : struct, IPixel<TPixel>
=> new Pen<TPixel>(brush, width, DashDotDotPattern);
}
}

112
src/ImageSharp.Drawing/Pens/Pens{TColor}.cs

@ -1,112 +0,0 @@
// <copyright file="Pens{TColor}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Pens
{
using System;
/// <summary>
/// Common Pen styles
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
public class Pens<TColor>
where TColor : struct, IPixel<TColor>
{
private static readonly float[] DashDotPattern = new[] { 3f, 1f, 1f, 1f };
private static readonly float[] DashDotDotPattern = new[] { 3f, 1f, 1f, 1f, 1f, 1f };
private static readonly float[] DottedPattern = new[] { 1f, 1f };
private static readonly float[] DashedPattern = new[] { 3f, 1f };
/// <summary>
/// Create a solid pen with out any drawing patterns
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <returns>The Pen</returns>
public static Pen<TColor> Solid(TColor color, float width)
=> new Pen<TColor>(color, width);
/// <summary>
/// Create a solid pen with out any drawing patterns
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <returns>The Pen</returns>
public static Pen<TColor> Solid(IBrush<TColor> brush, float width)
=> new Pen<TColor>(brush, width);
/// <summary>
/// Create a pen with a 'Dash' drawing patterns
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <returns>The Pen</returns>
public static Pen<TColor> Dash(TColor color, float width)
=> new Pen<TColor>(color, width, DashedPattern);
/// <summary>
/// Create a pen with a 'Dash' drawing patterns
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <returns>The Pen</returns>
public static Pen<TColor> Dash(IBrush<TColor> brush, float width)
=> new Pen<TColor>(brush, width, DashedPattern);
/// <summary>
/// Create a pen with a 'Dot' drawing patterns
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <returns>The Pen</returns>
public static Pen<TColor> Dot(TColor color, float width)
=> new Pen<TColor>(color, width, DottedPattern);
/// <summary>
/// Create a pen with a 'Dot' drawing patterns
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <returns>The Pen</returns>
public static Pen<TColor> Dot(IBrush<TColor> brush, float width)
=> new Pen<TColor>(brush, width, DottedPattern);
/// <summary>
/// Create a pen with a 'Dash Dot' drawing patterns
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <returns>The Pen</returns>
public static Pen<TColor> DashDot(TColor color, float width)
=> new Pen<TColor>(color, width, DashDotPattern);
/// <summary>
/// Create a pen with a 'Dash Dot' drawing patterns
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <returns>The Pen</returns>
public static Pen<TColor> DashDot(IBrush<TColor> brush, float width)
=> new Pen<TColor>(brush, width, DashDotPattern);
/// <summary>
/// Create a pen with a 'Dash Dot Dot' drawing patterns
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <returns>The Pen</returns>
public static Pen<TColor> DashDotDot(TColor color, float width)
=> new Pen<TColor>(color, width, DashDotDotPattern);
/// <summary>
/// Create a pen with a 'Dash Dot Dot' drawing patterns
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <returns>The Pen</returns>
public static Pen<TColor> DashDotDot(IBrush<TColor> brush, float width)
=> new Pen<TColor>(brush, width, DashDotDotPattern);
}
}

69
src/ImageSharp.Drawing/Pens/Pen{TColor}.cs → src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs

@ -1,20 +1,20 @@
// <copyright file="Pen{TColor}.cs" company="James Jackson-South">
// <copyright file="Pen{TPixel}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing.Pens
{
using System;
using System.Numerics;
using ImageSharp.Drawing.Brushes;
using ImageSharp.PixelFormats;
using Processors;
/// <summary>
/// Provides a pen that can apply a pattern to a line with a set brush and thickness
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <remarks>
/// The pattern will be in to the form of new float[]{ 1f, 2f, 0.5f} this will be
/// converted into a pattern that is 3.5 times longer that the width with 3 sections
@ -23,30 +23,30 @@ namespace ImageSharp.Drawing.Pens
/// section 3 will be width/2 long and will be filled
/// the the pattern will imidiatly repeat without gap.
/// </remarks>
public class Pen<TColor> : IPen<TColor>
where TColor : struct, IPixel<TColor>
public class Pen<TPixel> : IPen<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private static readonly float[] EmptyPattern = new float[0];
private readonly float[] pattern;
/// <summary>
/// Initializes a new instance of the <see cref="ImageSharp.Drawing.Pens.Pen{TColor}"/> class.
/// Initializes a new instance of the <see cref="ImageSharp.Drawing.Pens.Pen{TPixel}"/> class.
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
/// <param name="pattern">The pattern.</param>
public Pen(TColor color, float width, float[] pattern)
: this(new SolidBrush<TColor>(color), width, pattern)
public Pen(TPixel color, float width, float[] pattern)
: this(new SolidBrush<TPixel>(color), width, pattern)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ImageSharp.Drawing.Pens.Pen{TColor}"/> class.
/// Initializes a new instance of the <see cref="ImageSharp.Drawing.Pens.Pen{TPixel}"/> class.
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
/// <param name="pattern">The pattern.</param>
public Pen(IBrush<TColor> brush, float width, float[] pattern)
public Pen(IBrush<TPixel> brush, float width, float[] pattern)
{
this.Brush = brush;
this.Width = width;
@ -54,30 +54,30 @@ namespace ImageSharp.Drawing.Pens
}
/// <summary>
/// Initializes a new instance of the <see cref="ImageSharp.Drawing.Pens.Pen{TColor}"/> class.
/// Initializes a new instance of the <see cref="ImageSharp.Drawing.Pens.Pen{TPixel}"/> class.
/// </summary>
/// <param name="color">The color.</param>
/// <param name="width">The width.</param>
public Pen(TColor color, float width)
: this(new SolidBrush<TColor>(color), width)
public Pen(TPixel color, float width)
: this(new SolidBrush<TPixel>(color), width)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ImageSharp.Drawing.Pens.Pen{TColor}"/> class.
/// Initializes a new instance of the <see cref="ImageSharp.Drawing.Pens.Pen{TPixel}"/> class.
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="width">The width.</param>
public Pen(IBrush<TColor> brush, float width)
public Pen(IBrush<TPixel> brush, float width)
: this(brush, width, EmptyPattern)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ImageSharp.Drawing.Pens.Pen{TColor}"/> class.
/// Initializes a new instance of the <see cref="ImageSharp.Drawing.Pens.Pen{TPixel}"/> class.
/// </summary>
/// <param name="pen">The pen.</param>
internal Pen(Pen<TColor> pen)
internal Pen(Pen<TPixel> pen)
: this(pen.Brush, pen.Width, pen.pattern)
{
}
@ -88,7 +88,7 @@ namespace ImageSharp.Drawing.Pens
/// <value>
/// The brush.
/// </value>
public IBrush<TColor> Brush { get; }
public IBrush<TPixel> Brush { get; }
/// <summary>
/// Gets the width.
@ -103,6 +103,7 @@ namespace ImageSharp.Drawing.Pens
/// </summary>
/// <param name="sourcePixels">The source pixels.</param>
/// <param name="region">The region the pen will be applied to.</param>
/// <param name="options">The Graphics options</param>
/// <returns>
/// Returns a the applicator for the pen.
/// </returns>
@ -110,26 +111,26 @@ namespace ImageSharp.Drawing.Pens
/// The <paramref name="region" /> when being applied to things like shapes would ussually be the
/// bounding box of the shape not necorserrally the shape of the whole image
/// </remarks>
public PenApplicator<TColor> CreateApplicator(PixelAccessor<TColor> sourcePixels, RectangleF region)
public PenApplicator<TPixel> CreateApplicator(PixelAccessor<TPixel> sourcePixels, RectangleF region, GraphicsOptions options)
{
if (this.pattern == null || this.pattern.Length < 2)
{
// if there is only one item in the pattern then 100% of it will
// be solid so use the quicker applicator
return new SolidPenApplicator(sourcePixels, this.Brush, region, this.Width);
return new SolidPenApplicator(sourcePixels, this.Brush, region, this.Width, options);
}
return new PatternPenApplicator(sourcePixels, this.Brush, region, this.Width, this.pattern);
return new PatternPenApplicator(sourcePixels, this.Brush, region, this.Width, this.pattern, options);
}
private class SolidPenApplicator : PenApplicator<TColor>
private class SolidPenApplicator : PenApplicator<TPixel>
{
private readonly BrushApplicator<TColor> brush;
private readonly BrushApplicator<TPixel> brush;
private readonly float halfWidth;
public SolidPenApplicator(PixelAccessor<TColor> sourcePixels, IBrush<TColor> brush, RectangleF region, float width)
public SolidPenApplicator(PixelAccessor<TPixel> sourcePixels, IBrush<TPixel> brush, RectangleF region, float width, GraphicsOptions options)
{
this.brush = brush.CreateApplicator(sourcePixels, region);
this.brush = brush.CreateApplicator(sourcePixels, region, options);
this.halfWidth = width / 2;
this.RequiredRegion = RectangleF.Outset(region, width);
}
@ -144,9 +145,9 @@ namespace ImageSharp.Drawing.Pens
this.brush.Dispose();
}
public override ColoredPointInfo<TColor> GetColor(int x, int y, PointInfo info)
public override ColoredPointInfo<TPixel> GetColor(int x, int y, PointInfo info)
{
ColoredPointInfo<TColor> result = default(ColoredPointInfo<TColor>);
ColoredPointInfo<TPixel> result = default(ColoredPointInfo<TPixel>);
result.Color = this.brush[x, y];
if (info.DistanceFromPath < this.halfWidth)
@ -163,16 +164,16 @@ namespace ImageSharp.Drawing.Pens
}
}
private class PatternPenApplicator : PenApplicator<TColor>
private class PatternPenApplicator : PenApplicator<TPixel>
{
private readonly BrushApplicator<TColor> brush;
private readonly BrushApplicator<TPixel> brush;
private readonly float halfWidth;
private readonly float[] pattern;
private readonly float totalLength;
public PatternPenApplicator(PixelAccessor<TColor> sourcePixels, IBrush<TColor> brush, RectangleF region, float width, float[] pattern)
public PatternPenApplicator(PixelAccessor<TPixel> sourcePixels, IBrush<TPixel> brush, RectangleF region, float width, float[] pattern, GraphicsOptions options)
{
this.brush = brush.CreateApplicator(sourcePixels, region);
this.brush = brush.CreateApplicator(sourcePixels, region, options);
this.halfWidth = width / 2;
this.totalLength = 0;
@ -197,16 +198,16 @@ namespace ImageSharp.Drawing.Pens
this.brush.Dispose();
}
public override ColoredPointInfo<TColor> GetColor(int x, int y, PointInfo info)
public override ColoredPointInfo<TPixel> GetColor(int x, int y, PointInfo info)
{
ColoredPointInfo<TColor> infoResult = default(ColoredPointInfo<TColor>);
ColoredPointInfo<TPixel> infoResult = default(ColoredPointInfo<TPixel>);
infoResult.DistanceFromElement = float.MaxValue; // is really outside the element
float length = info.DistanceAlongPath % this.totalLength;
// 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.
// and set them on the ColoredPointInfo<TPixel> along with the color.
infoResult.Color = this.brush[x, y];
float distanceWAway = 0;

10
src/ImageSharp.Drawing/Pens/Processors/ColoredPointInfo.cs

@ -5,19 +5,19 @@
namespace ImageSharp.Drawing.Processors
{
using System;
using ImageSharp.PixelFormats;
/// <summary>
/// Returns details about how far away from the inside of a shape and the color the pixel could be.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
public struct ColoredPointInfo<TColor>
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The type of the color.</typeparam>
public struct ColoredPointInfo<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// The color
/// </summary>
public TColor Color;
public TPixel Color;
/// <summary>
/// The distance from element

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

@ -6,14 +6,14 @@
namespace ImageSharp.Drawing.Processors
{
using System;
using System.Numerics;
using ImageSharp.PixelFormats;
/// <summary>
/// primitive that converts a <see cref="PointInfo"/> into a color and a distance away from the drawable part of the path.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
public abstract class PenApplicator<TColor> : IDisposable
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The type of the color.</typeparam>
public abstract class PenApplicator<TPixel> : IDisposable
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// Gets the required region.
@ -27,7 +27,7 @@ namespace ImageSharp.Drawing.Processors
public abstract void Dispose();
/// <summary>
/// Gets a <see cref="ColoredPointInfo{TColor}" /> from a point represented by a <see cref="PointInfo" />.
/// Gets a <see cref="ColoredPointInfo{TPixel}" /> from a point represented by a <see cref="PointInfo" />.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
@ -35,6 +35,6 @@ namespace ImageSharp.Drawing.Processors
/// <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);
public abstract ColoredPointInfo<TPixel> GetColor(int x, int y, PointInfo info);
}
}

98
src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs

@ -9,40 +9,45 @@ namespace ImageSharp.Drawing.Processors
using System.Numerics;
using System.Threading.Tasks;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
using ImageSharp.Processing;
/// <summary>
/// Combines two images together by blending the pixels.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
internal class DrawImageProcessor<TColor> : ImageProcessor<TColor>
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal class DrawImageProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private readonly PixelBlender<TPixel> blender;
/// <summary>
/// Initializes a new instance of the <see cref="DrawImageProcessor{TColor}"/> class.
/// Initializes a new instance of the <see cref="DrawImageProcessor{TPixel}"/> class.
/// </summary>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="size">The size to draw the blended image.</param>
/// <param name="location">The location to draw the blended image.</param>
/// <param name="alpha">The opacity of the image to blend. Between 0 and 100.</param>
public DrawImageProcessor(Image<TColor> image, Size size, Point location, int alpha = 100)
/// <param name="options">The opacity of the image to blend. Between 0 and 100.</param>
public DrawImageProcessor(Image<TPixel> image, Size size, Point location, GraphicsOptions options)
{
Guard.MustBeBetweenOrEqualTo(alpha, 0, 100, nameof(alpha));
Guard.MustBeBetweenOrEqualTo(options.BlendPercentage, 0, 1, nameof(options.BlendPercentage));
this.Image = image;
this.Size = size;
this.Alpha = alpha;
this.Alpha = options.BlendPercentage;
this.blender = PixelOperations<TPixel>.Instance.GetPixelBlender(options.BlenderMode);
this.Location = location;
}
/// <summary>
/// Gets the image to blend.
/// </summary>
public Image<TColor> Image { get; private set; }
public Image<TPixel> Image { get; private set; }
/// <summary>
/// Gets the alpha percentage value.
/// </summary>
public int Alpha { get; }
public float Alpha { get; }
/// <summary>
/// Gets the size to draw the blended image.
@ -55,45 +60,54 @@ namespace ImageSharp.Drawing.Processors
public Point Location { get; }
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor> source, Rectangle sourceRectangle)
protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle)
{
if (this.Image.Bounds.Size != this.Size)
Image<TPixel> disposableImage = null;
Image<TPixel> targetImage = this.Image;
try
{
// should Resize be moved to core?
this.Image = this.Image.Resize(this.Size.Width, this.Size.Height);
}
if (targetImage.Bounds.Size != this.Size)
{
targetImage = disposableImage = new Image<TPixel>(this.Image).Resize(this.Size.Width, this.Size.Height);
}
// Align start/end positions.
Rectangle bounds = this.Image.Bounds;
int minX = Math.Max(this.Location.X, sourceRectangle.X);
int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width);
int minY = Math.Max(this.Location.Y, sourceRectangle.Y);
int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom);
// Align start/end positions.
Rectangle bounds = this.Image.Bounds;
int minX = Math.Max(this.Location.X, sourceRectangle.X);
int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width);
maxX = Math.Min(this.Location.X + this.Size.Width, maxX);
float alpha = this.Alpha / 100F;
int minY = Math.Max(this.Location.Y, sourceRectangle.Y);
int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom);
using (PixelAccessor<TColor> toBlendPixels = this.Image.Lock())
using (PixelAccessor<TColor> sourcePixels = source.Lock())
{
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
{
for (int x = minX; x < maxX; x++)
{
Vector4 backgroundVector = sourcePixels[x, y].ToVector4();
Vector4 sourceVector = toBlendPixels[x - minX, y - minY].ToVector4();
maxY = Math.Min(this.Location.Y + this.Size.Height, maxY);
// Lerping colors is dependent on the alpha of the blended color
backgroundVector = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, alpha);
int width = maxX - minX;
using (Buffer<float> amount = new Buffer<float>(width))
using (PixelAccessor<TPixel> toBlendPixels = targetImage.Lock())
using (PixelAccessor<TPixel> sourcePixels = source.Lock())
{
for (int i = 0; i < width; i++)
{
amount[i] = this.Alpha;
}
TColor packed = default(TColor);
packed.PackFromVector4(backgroundVector);
sourcePixels[x, y] = packed;
}
});
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
{
Span<TPixel> background = sourcePixels.GetRowSpan(y).Slice(minX, width);
Span<TPixel> foreground = toBlendPixels.GetRowSpan(y - this.Location.Y).Slice(0, width);
this.blender.Blend(background, background, foreground, amount);
});
}
}
finally
{
disposableImage?.Dispose();
}
}
}

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

@ -9,27 +9,29 @@ namespace ImageSharp.Drawing.Processors
using System.Numerics;
using System.Threading.Tasks;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
using ImageSharp.Processing;
using Pens;
/// <summary>
/// Draws a path using the processor pipeline
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <seealso cref="ImageSharp.Processing.ImageProcessor{TColor}" />
internal class DrawPathProcessor<TColor> : ImageProcessor<TColor>
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <seealso cref="ImageSharp.Processing.ImageProcessor{TPixel}" />
internal class DrawPathProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private const float AntialiasFactor = 1f;
private const int PaddingFactor = 1; // needs to been the same or greater than AntialiasFactor
/// <summary>
/// Initializes a new instance of the <see cref="DrawPathProcessor{TColor}" /> class.
/// Initializes a new instance of the <see cref="DrawPathProcessor{TPixel}" /> class.
/// </summary>
/// <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)
public DrawPathProcessor(IPen<TPixel> pen, Drawable drawable, GraphicsOptions options)
{
this.Path = drawable;
this.Pen = pen;
@ -44,7 +46,7 @@ namespace ImageSharp.Drawing.Processors
/// <summary>
/// Gets the pen.
/// </summary>
public IPen<TColor> Pen { get; }
public IPen<TPixel> Pen { get; }
/// <summary>
/// Gets the path.
@ -52,10 +54,10 @@ namespace ImageSharp.Drawing.Processors
public Drawable Path { get; }
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor> source, Rectangle sourceRectangle)
protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle)
{
using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (PenApplicator<TColor> applicator = this.Pen.CreateApplicator(sourcePixels, this.Path.Bounds))
using (PixelAccessor<TPixel> sourcePixels = source.Lock())
using (PenApplicator<TPixel> applicator = this.Pen.CreateApplicator(sourcePixels, this.Path.Bounds, this.Options))
{
Rectangle rect = RectangleF.Ceiling(applicator.RequiredRegion);
@ -86,37 +88,34 @@ namespace ImageSharp.Drawing.Processors
polyStartY = 0;
}
int width = maxX - minX;
PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.Options.BlenderMode);
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
{
int offsetY = y - polyStartY;
minY,
maxY,
this.ParallelOptions,
y =>
{
int offsetY = y - polyStartY;
for (int x = minX; x < maxX; x++)
using (Buffer<float> amount = new Buffer<float>(width))
using (Buffer<TPixel> colors = new Buffer<TPixel>(width))
{
for (int i = 0; i < width; i++)
{
// TODO add find intersections code to skip and scan large regions of this.
int x = i + minX;
int offsetX = x - startX;
PointInfo info = this.Path.GetPointInfo(offsetX, offsetY);
ColoredPointInfo<TColor> color = applicator.GetColor(offsetX, offsetY, info);
float opacity = this.Opacity(color.DistanceFromElement);
if (opacity > Constants.Epsilon)
{
Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4();
Vector4 sourceVector = color.Color.ToVector4();
Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, opacity);
TColor packed = default(TColor);
packed.PackFromVector4(finalColor);
sourcePixels[offsetX, offsetY] = packed;
}
ColoredPointInfo<TPixel> color = applicator.GetColor(offsetX, offsetY, info);
amount[i] = (this.Opacity(color.DistanceFromElement) * this.Options.BlendPercentage).Clamp(0, 1);
colors[i] = color.Color;
}
});
Span<TPixel> destination = sourcePixels.GetRowSpan(offsetY).Slice(minX - startX, width);
blender.Blend(destination, destination, colors, amount);
}
});
}
}

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

@ -10,31 +10,37 @@ namespace ImageSharp.Drawing.Processors
using System.Threading.Tasks;
using Drawing;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
using ImageSharp.Processing;
/// <summary>
/// Using the bursh as a source of pixels colors blends the brush color with source.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
internal class FillProcessor<TColor> : ImageProcessor<TColor>
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal class FillProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// The brush.
/// </summary>
private readonly IBrush<TColor> brush;
private readonly IBrush<TPixel> brush;
private readonly GraphicsOptions options;
/// <summary>
/// Initializes a new instance of the <see cref="FillProcessor{TColor}"/> class.
/// Initializes a new instance of the <see cref="FillProcessor{TPixel}"/> class.
/// </summary>
/// <param name="brush">The brush to source pixel colors from.</param>
public FillProcessor(IBrush<TColor> brush)
/// <param name="options">The options</param>
public FillProcessor(IBrush<TPixel> brush, GraphicsOptions options)
{
this.brush = brush;
this.options = options;
}
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor> source, Rectangle sourceRectangle)
protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle)
{
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
@ -58,32 +64,30 @@ namespace ImageSharp.Drawing.Processors
startY = 0;
}
int width = maxX - minX;
// we could possibly do some optermising by having knowledge about the individual brushes operate
// for example If brush is SolidBrush<TColor> then we could just get the color upfront
// and skip using the IBrushApplicator<TColor>?.
using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (BrushApplicator<TColor> applicator = this.brush.CreateApplicator(sourcePixels, sourceRectangle))
// for example If brush is SolidBrush<TPixel> then we could just get the color upfront
// and skip using the IBrushApplicator<TPixel>?.
using (PixelAccessor<TPixel> sourcePixels = source.Lock())
using (Buffer<float> amount = new Buffer<float>(width))
using (BrushApplicator<TPixel> applicator = this.brush.CreateApplicator(sourcePixels, sourceRectangle, this.options))
{
Parallel.For(
for (int i = 0; i < width; i++)
{
amount[i] = this.options.BlendPercentage;
}
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
{
int offsetY = y - startY;
for (int x = minX; x < maxX; x++)
{
int offsetX = x - startX;
Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4();
Vector4 sourceVector = applicator[offsetX, offsetY].ToVector4();
Vector4 finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, 1);
int offsetX = minX - startX;
TColor packed = default(TColor);
packed.PackFromVector4(finalColor);
sourcePixels[offsetX, offsetY] = packed;
}
applicator.Apply(amount, offsetX, offsetY);
});
}
}

156
src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs

@ -7,29 +7,30 @@ namespace ImageSharp.Drawing.Processors
{
using System;
using System.Buffers;
using System.Numerics;
using System.Threading.Tasks;
using Drawing;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
using ImageSharp.Processing;
/// <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}" />
internal class FillRegionProcessor<TColor> : ImageProcessor<TColor>
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <seealso cref="ImageSharp.Processing.ImageProcessor{TPixel}" />
internal class FillRegionProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private const float AntialiasFactor = 1f;
private const int DrawPadding = 1;
/// <summary>
/// Initializes a new instance of the <see cref="FillRegionProcessor{TColor}" /> class.
/// Initializes a new instance of the <see cref="FillRegionProcessor{TPixel}" /> class.
/// </summary>
/// <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)
public FillRegionProcessor(IBrush<TPixel> brush, Region region, GraphicsOptions options)
{
this.Region = region;
this.Brush = brush;
@ -39,7 +40,7 @@ namespace ImageSharp.Drawing.Processors
/// <summary>
/// Gets the brush.
/// </summary>
public IBrush<TColor> Brush { get; }
public IBrush<TPixel> Brush { get; }
/// <summary>
/// Gets the region that this processor applies to.
@ -55,7 +56,7 @@ namespace ImageSharp.Drawing.Processors
public GraphicsOptions Options { get; }
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor> source, Rectangle sourceRectangle)
protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle)
{
Region region = this.Region;
Rectangle rect = region.Bounds;
@ -88,105 +89,106 @@ namespace ImageSharp.Drawing.Processors
}
}
using (PixelAccessor<TColor> sourcePixels = source.Lock())
using (BrushApplicator<TColor> applicator = this.Brush.CreateApplicator(sourcePixels, rect))
using (PixelAccessor<TPixel> sourcePixels = source.Lock())
using (BrushApplicator<TPixel> applicator = this.Brush.CreateApplicator(sourcePixels, rect, this.Options))
{
float[] buffer = arrayPool.Rent(maxIntersections);
int scanlineWidth = maxX - minX;
float[] scanline = ArrayPool<float>.Shared.Rent(scanlineWidth);
try
using (Buffer<float> scanline = new Buffer<float>(scanlineWidth))
{
bool scanlineDirty = true;
for (int y = minY; y < maxY; y++)
try
{
if (scanlineDirty)
bool scanlineDirty = true;
for (int y = minY; y < maxY; y++)
{
// clear the buffer
for (int x = 0; x < scanlineWidth; x++)
if (scanlineDirty)
{
scanline[x] = 0;
}
scanlineDirty = false;
}
// clear the buffer
for (int x = 0; x < scanlineWidth; x++)
{
scanline[x] = 0;
}
float subpixelFraction = 1f / subpixelCount;
float subpixelFractionPoint = subpixelFraction / subpixelCount;
for (float subPixel = (float)y; subPixel < y + 1; subPixel += subpixelFraction)
{
int pointsFound = region.Scan(subPixel, buffer, maxIntersections, 0);
if (pointsFound == 0)
{
// nothing on this line skip
continue;
scanlineDirty = false;
}
QuickSort(buffer, pointsFound);
for (int point = 0; point < pointsFound; point += 2)
float subpixelFraction = 1f / subpixelCount;
float subpixelFractionPoint = subpixelFraction / subpixelCount;
for (float subPixel = (float)y; subPixel < y + 1; subPixel += subpixelFraction)
{
// points will be paired up
float scanStart = buffer[point] - minX;
float scanEnd = buffer[point + 1] - minX;
int startX = (int)MathF.Floor(scanStart);
int endX = (int)MathF.Floor(scanEnd);
int pointsFound = region.Scan(subPixel, buffer, maxIntersections, 0);
if (pointsFound == 0)
{
// nothing on this line skip
continue;
}
if (startX >= 0 && startX < scanline.Length)
QuickSort(buffer, pointsFound);
for (int point = 0; point < pointsFound; point += 2)
{
for (float x = scanStart; x < startX + 1; x += subpixelFraction)
// points will be paired up
float scanStart = buffer[point] - minX;
float scanEnd = buffer[point + 1] - minX;
int startX = (int)MathF.Floor(scanStart);
int endX = (int)MathF.Floor(scanEnd);
if (startX >= 0 && startX < scanline.Length)
{
scanline[startX] += subpixelFractionPoint;
scanlineDirty = true;
for (float x = scanStart; x < startX + 1; x += subpixelFraction)
{
scanline[startX] += subpixelFractionPoint;
scanlineDirty = true;
}
}
}
if (endX >= 0 && endX < scanline.Length)
{
for (float x = endX; x < scanEnd; x += subpixelFraction)
if (endX >= 0 && endX < scanline.Length)
{
scanline[endX] += subpixelFractionPoint;
scanlineDirty = true;
for (float x = endX; x < scanEnd; x += subpixelFraction)
{
scanline[endX] += subpixelFractionPoint;
scanlineDirty = true;
}
}
}
int nextX = startX + 1;
endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge
if (nextX >= 0)
{
for (int x = nextX; x < endX; x++)
int nextX = startX + 1;
endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge
if (nextX >= 0)
{
scanline[x] += subpixelFraction;
scanlineDirty = true;
for (int x = nextX; x < endX; x++)
{
scanline[x] += subpixelFraction;
scanlineDirty = true;
}
}
}
}
}
if (scanlineDirty)
{
if (!this.Options.Antialias)
if (scanlineDirty)
{
for (int x = 0; x < scanlineWidth; x++)
if (!this.Options.Antialias)
{
if (scanline[x] > 0.5)
{
scanline[x] = 1;
}
else
for (int x = 0; x < scanlineWidth; x++)
{
scanline[x] = 0;
if (scanline[x] > 0.5)
{
scanline[x] = 1;
}
else
{
scanline[x] = 0;
}
}
}
}
applicator.Apply(scanline, scanlineWidth, 0, minX, y);
applicator.Apply(scanline, minX, y);
}
}
}
}
finally
{
arrayPool.Return(buffer);
ArrayPool<float>.Shared.Return(scanline);
finally
{
arrayPool.Return(buffer);
}
}
}
}

78
src/ImageSharp.Drawing/Text/DrawText.cs

@ -10,11 +10,11 @@ namespace ImageSharp
using Drawing;
using Drawing.Brushes;
using Drawing.Pens;
using ImageSharp.PixelFormats;
using SixLabors.Fonts;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> type.
/// </summary>
public static partial class ImageExtensions
{
@ -23,17 +23,17 @@ namespace ImageSharp
/// <summary>
/// Draws the text onto the the image filled via the brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
/// <param name="color">The color.</param>
/// <param name="location">The location.</param>
/// <returns>
/// The <see cref="Image{TColor}" />.
/// The <see cref="Image{TPixel}" />.
/// </returns>
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, TColor color, Vector2 location)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, TPixel color, Vector2 location)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawText(text, font, color, location, TextGraphicsOptions.Default);
}
@ -41,7 +41,7 @@ namespace ImageSharp
/// <summary>
/// Draws the text onto the the image filled via the brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
@ -49,28 +49,28 @@ namespace ImageSharp
/// <param name="location">The location.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The <see cref="Image{TColor}" />.
/// The <see cref="Image{TPixel}" />.
/// </returns>
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, TColor color, Vector2 location, TextGraphicsOptions options)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, TPixel color, Vector2 location, TextGraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawText(text, font, Brushes<TColor>.Solid(color), null, location, options);
return source.DrawText(text, font, Brushes.Solid(color), null, location, options);
}
/// <summary>
/// Draws the text onto the the image filled via the brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
/// <param name="brush">The brush.</param>
/// <param name="location">The location.</param>
/// <returns>
/// The <see cref="Image{TColor}" />.
/// The <see cref="Image{TPixel}" />.
/// </returns>
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IBrush<TColor> brush, Vector2 location)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, Vector2 location)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawText(text, font, brush, location, TextGraphicsOptions.Default);
}
@ -78,7 +78,7 @@ namespace ImageSharp
/// <summary>
/// Draws the text onto the the image filled via the brush.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
@ -86,10 +86,10 @@ namespace ImageSharp
/// <param name="location">The location.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The <see cref="Image{TColor}" />.
/// The <see cref="Image{TPixel}" />.
/// </returns>
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IBrush<TColor> brush, Vector2 location, TextGraphicsOptions options)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, Vector2 location, TextGraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawText(text, font, brush, null, location, options);
}
@ -97,17 +97,17 @@ namespace ImageSharp
/// <summary>
/// Draws the text onto the the image outlined via the pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
/// <param name="pen">The pen.</param>
/// <param name="location">The location.</param>
/// <returns>
/// The <see cref="Image{TColor}" />.
/// The <see cref="Image{TPixel}" />.
/// </returns>
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IPen<TColor> pen, Vector2 location)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IPen<TPixel> pen, Vector2 location)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawText(text, font, pen, location, TextGraphicsOptions.Default);
}
@ -115,7 +115,7 @@ namespace ImageSharp
/// <summary>
/// Draws the text onto the the image outlined via the pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
@ -123,10 +123,10 @@ namespace ImageSharp
/// <param name="location">The location.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The <see cref="Image{TColor}" />.
/// The <see cref="Image{TPixel}" />.
/// </returns>
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IPen<TColor> pen, Vector2 location, TextGraphicsOptions options)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IPen<TPixel> pen, Vector2 location, TextGraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawText(text, font, null, pen, location, options);
}
@ -134,7 +134,7 @@ namespace ImageSharp
/// <summary>
/// Draws the text onto the the image filled via the brush then outlined via the pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
@ -142,10 +142,10 @@ namespace ImageSharp
/// <param name="pen">The pen.</param>
/// <param name="location">The location.</param>
/// <returns>
/// The <see cref="Image{TColor}" />.
/// The <see cref="Image{TPixel}" />.
/// </returns>
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IBrush<TColor> brush, IPen<TColor> pen, Vector2 location)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, IPen<TPixel> pen, Vector2 location)
where TPixel : struct, IPixel<TPixel>
{
return source.DrawText(text, font, brush, pen, location, TextGraphicsOptions.Default);
}
@ -153,7 +153,7 @@ namespace ImageSharp
/// <summary>
/// Draws the text onto the the image filled via the brush then outlined via the pen.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
/// <typeparam name="TPixel">The type of the color.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="text">The text.</param>
/// <param name="font">The font.</param>
@ -162,10 +162,10 @@ namespace ImageSharp
/// <param name="location">The location.</param>
/// <param name="options">The options.</param>
/// <returns>
/// The <see cref="Image{TColor}" />.
/// The <see cref="Image{TPixel}" />.
/// </returns>
public static Image<TColor> DrawText<TColor>(this Image<TColor> source, string text, Font font, IBrush<TColor> brush, IPen<TColor> pen, Vector2 location, TextGraphicsOptions options)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, IPen<TPixel> pen, Vector2 location, TextGraphicsOptions options)
where TPixel : struct, IPixel<TPixel>
{
GlyphBuilder glyphBuilder = new GlyphBuilder(location);
@ -177,13 +177,15 @@ namespace ImageSharp
dpi = new Vector2((float)source.MetaData.HorizontalResolution, (float)source.MetaData.VerticalResolution);
}
FontSpan style = new FontSpan(font)
FontSpan style = new FontSpan(font, dpi)
{
ApplyKerning = options.ApplyKerning,
TabWidth = options.TabWidth
TabWidth = options.TabWidth,
WrappingWidth = options.WrapTextWidth,
Alignment = options.TextAlignment
};
renderer.RenderText(text, style, dpi);
renderer.RenderText(text, style);
System.Collections.Generic.IEnumerable<SixLabors.Shapes.IPath> shapesToDraw = glyphBuilder.Paths;

3
src/ImageSharp.Drawing/Text/GlyphBuilder.cs

@ -48,7 +48,8 @@ namespace ImageSharp.Drawing
/// <summary>
/// Begins the glyph.
/// </summary>
void IGlyphRenderer.BeginGlyph()
/// <param name="location">The offset that the glyph will be rendered at.</param>
void IGlyphRenderer.BeginGlyph(Vector2 location)
{
this.builder.Clear();
}

102
src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs

@ -2,9 +2,11 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Drawing
{
using ImageSharp.PixelFormats;
using SixLabors.Fonts;
/// <summary>
/// Options for influencing the drawing functions.
/// </summary>
@ -15,44 +17,94 @@ namespace ImageSharp.Drawing
/// </summary>
public static readonly TextGraphicsOptions Default = new TextGraphicsOptions(true);
private float? blendPercentage;
private int? antialiasSubpixelDepth;
private bool? antialias;
private bool? applyKerning;
private float? tabWidth;
private PixelBlenderMode blenderMode;
private bool? useImageResolution;
private float wrapTextWidth;
private SixLabors.Fonts.TextAlignment? textAlignment;
/// <summary>
/// Whether antialiasing should be applied.
/// Initializes a new instance of the <see cref="TextGraphicsOptions" /> struct.
/// </summary>
public bool Antialias;
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
public TextGraphicsOptions(bool enableAntialiasing)
{
this.applyKerning = true;
this.tabWidth = 4;
this.useImageResolution = false;
this.wrapTextWidth = 0;
this.textAlignment = SixLabors.Fonts.TextAlignment.Left;
this.antialiasSubpixelDepth = 16;
this.blenderMode = PixelBlenderMode.Normal;
this.blendPercentage = 1;
this.antialias = enableAntialiasing;
}
/// <summary>
/// The number of subpixels to use while rendering with antialiasing enabled.
/// Gets or sets a value indicating whether antialiasing should be applied.
/// </summary>
public int AntialiasSubpixelDepth;
public bool Antialias { get => this.antialias ?? true; set => this.antialias = value; }
/// <summary>
/// Whether the text should be drawing with kerning enabled.
/// Gets or sets a value indicating the number of subpixels to use while rendering with antialiasing enabled.
/// </summary>
public bool ApplyKerning;
public int AntialiasSubpixelDepth { get => this.antialiasSubpixelDepth ?? 16; set => this.antialiasSubpixelDepth = value; }
/// <summary>
/// The number of space widths a tab should lock to.
/// Gets or sets a value indicating the blending percentage to apply to the drawing operation
/// </summary>
public float TabWidth;
public float BlendPercentage { get => (this.blendPercentage ?? 1).Clamp(0, 1); set => this.blendPercentage = value; }
// In the future we could expose a PixelBlender<TPixel> directly on here
// or some forms of PixelBlender factory for each pixel type. Will need
// some API thought post V1.
/// <summary>
/// Flag weather to use the current image resultion to for point size scaling.
/// Gets or sets a value indicating the blending percentage to apply to the drawing operation
/// </summary>
public PixelBlenderMode BlenderMode { get => this.blenderMode; set => this.blenderMode = value; }
/// <summary>
/// Gets or sets a value indicating whether the text should be drawing with kerning enabled.
/// </summary>
public bool ApplyKerning { get => this.applyKerning ?? true; set => this.applyKerning = value; }
/// <summary>
/// Gets or sets a value indicating the number of space widths a tab should lock to.
/// </summary>
public float TabWidth { get => this.tabWidth ?? 4; set => this.tabWidth = value; }
/// <summary>
/// Gets or sets a value indicating whether to use the current image resultion to for point size scaling.
/// If this is [false] the text renders at 72dpi otherwise it renders at Image resolution
/// </summary>
public bool UseImageResolution;
public bool UseImageResolution { get => this.useImageResolution ?? false; set => this.useImageResolution = value; }
/// <summary>
/// Initializes a new instance of the <see cref="TextGraphicsOptions" /> struct.
/// Gets or sets a value indicating if greater than zero determine the width at which text should wrap.
/// </summary>
/// <param name="enableAntialiasing">If set to <c>true</c> [enable antialiasing].</param>
public TextGraphicsOptions(bool enableAntialiasing)
{
this.Antialias = enableAntialiasing;
this.ApplyKerning = true;
this.TabWidth = 4;
this.AntialiasSubpixelDepth = 16;
this.UseImageResolution = false;
}
public float WrapTextWidth { get => this.wrapTextWidth; set => this.wrapTextWidth = value; }
/// <summary>
/// Gets or sets a value indicating how to align the text relative to the rendering space.
/// If <see cref="WrapTextWidth"/> is greater than zero it will align relative to the space
/// defined by the location and width, if <see cref="WrapTextWidth"/> equals zero, and thus
/// wrapping disabled, then the alignment is relative to the drawing location.
/// </summary>
public TextAlignment TextAlignment { get => this.textAlignment ?? TextAlignment.Left; set => this.textAlignment = value; }
/// <summary>
/// Performs an implicit conversion from <see cref="GraphicsOptions"/> to <see cref="TextGraphicsOptions"/>.
@ -65,7 +117,9 @@ namespace ImageSharp.Drawing
{
return new TextGraphicsOptions(options.Antialias)
{
AntialiasSubpixelDepth = options.AntialiasSubpixelDepth
AntialiasSubpixelDepth = options.AntialiasSubpixelDepth,
blendPercentage = options.BlendPercentage,
blenderMode = options.BlenderMode
};
}
@ -80,7 +134,9 @@ namespace ImageSharp.Drawing
{
return new GraphicsOptions(options.Antialias)
{
AntialiasSubpixelDepth = options.AntialiasSubpixelDepth
AntialiasSubpixelDepth = options.AntialiasSubpixelDepth,
BlenderMode = options.BlenderMode,
BlendPercentage = options.BlendPercentage
};
}
}

255
src/ImageSharp/Colors/Color.BulkOperations.cs

@ -1,255 +0,0 @@
// <copyright file="Color.BulkOperations.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 System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Conains the definition of <see cref="BulkOperations"/>
/// </content>
public partial struct Color
{
/// <summary>
/// <see cref="BulkPixelOperations{TColor}"/> implementation optimized for <see cref="Color"/>.
/// </summary>
internal class BulkOperations : BulkPixelOperations<Color>
{
/// <summary>
/// SIMD optimized bulk implementation of <see cref="IPixel.PackFromVector4(Vector4)"/>
/// that works only with `count` divisible by <see cref="Vector{UInt32}.Count"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="BufferSpan{T}"/> to the source colors.</param>
/// <param name="destVectors">The <see cref="BufferSpan{T}"/> to the dstination vectors.</param>
/// <param name="count">The number of pixels to convert.</param>
/// <remarks>
/// Implementation adapted from:
/// <see>
/// <cref>http://stackoverflow.com/a/5362789</cref>
/// </see>
/// TODO: We can replace this implementation in the future using new Vector API-s:
/// <see>
/// <cref>https://github.com/dotnet/corefx/issues/15957</cref>
/// </see>
/// </remarks>
internal static unsafe void ToVector4SimdAligned(
BufferSpan<Color> sourceColors,
BufferSpan<Vector4> destVectors,
int count)
{
if (!Vector.IsHardwareAccelerated)
{
throw new InvalidOperationException(
"Color.BulkOperations.ToVector4SimdAligned() should not be called when Vector.IsHardwareAccelerated == false!");
}
int vecSize = Vector<uint>.Count;
DebugGuard.IsTrue(
count % vecSize == 0,
nameof(count),
"Argument 'count' should divisible by Vector<uint>.Count!");
Vector<float> bVec = new Vector<float>(256.0f / 255.0f);
Vector<float> magicFloat = new Vector<float>(32768.0f);
Vector<uint> magicInt = new Vector<uint>(1191182336); // reinterpreded value of 32768.0f
Vector<uint> mask = new Vector<uint>(255);
int unpackedRawCount = count * 4;
uint* src = (uint*)sourceColors.PointerAtOffset;
uint* srcEnd = src + count;
using (PinnedBuffer<uint> tempBuf = new PinnedBuffer<uint>(
unpackedRawCount + Vector<uint>.Count))
{
uint* tPtr = (uint*)tempBuf.Pointer;
uint[] temp = tempBuf.Array;
float[] fTemp = Unsafe.As<float[]>(temp);
UnpackedRGBA* dst = (UnpackedRGBA*)tPtr;
for (; src < srcEnd; src++, dst++)
{
// This call is the bottleneck now:
dst->Load(*src);
}
for (int i = 0; i < unpackedRawCount; i += vecSize)
{
Vector<uint> vi = new Vector<uint>(temp, i);
vi &= mask;
vi |= magicInt;
Vector<float> vf = Vector.AsVectorSingle(vi);
vf = (vf - magicFloat) * bVec;
vf.CopyTo(fTemp, i);
}
BufferSpan.Copy<uint>(tempBuf, (BufferSpan<byte>)destVectors, unpackedRawCount);
}
}
/// <inheritdoc />
internal override void ToVector4(BufferSpan<Color> sourceColors, BufferSpan<Vector4> destVectors, int count)
{
if (count < 256 || !Vector.IsHardwareAccelerated)
{
// Doesn't worth to bother with SIMD:
base.ToVector4(sourceColors, destVectors, count);
return;
}
int remainder = count % Vector<uint>.Count;
int alignedCount = count - remainder;
if (alignedCount > 0)
{
ToVector4SimdAligned(sourceColors, destVectors, alignedCount);
}
if (remainder > 0)
{
sourceColors = sourceColors.Slice(alignedCount);
destVectors = destVectors.Slice(alignedCount);
base.ToVector4(sourceColors, destVectors, remainder);
}
}
/// <inheritdoc />
internal override unsafe void PackFromXyzBytes(BufferSpan<byte> sourceBytes, BufferSpan<Color> destColors, int count)
{
byte* source = (byte*)sourceBytes;
byte* destination = (byte*)destColors;
for (int x = 0; x < count; x++)
{
Unsafe.Write(destination, (uint)(*source << 0 | *(source + 1) << 8 | *(source + 2) << 16 | 255 << 24));
source += 3;
destination += 4;
}
}
/// <inheritdoc />
internal override unsafe void ToXyzBytes(BufferSpan<Color> sourceColors, BufferSpan<byte> destBytes, int count)
{
byte* source = (byte*)sourceColors;
byte* destination = (byte*)destBytes;
for (int x = 0; x < count; x++)
{
*destination = *(source + 0);
*(destination + 1) = *(source + 1);
*(destination + 2) = *(source + 2);
source += 4;
destination += 3;
}
}
/// <inheritdoc />
internal override void PackFromXyzwBytes(BufferSpan<byte> sourceBytes, BufferSpan<Color> destColors, int count)
{
BufferSpan.Copy(sourceBytes, destColors, count);
}
/// <inheritdoc />
internal override void ToXyzwBytes(BufferSpan<Color> sourceColors, BufferSpan<byte> destBytes, int count)
{
BufferSpan.Copy(sourceColors, destBytes, count);
}
/// <inheritdoc />
internal override unsafe void PackFromZyxBytes(BufferSpan<byte> sourceBytes, BufferSpan<Color> destColors, int count)
{
byte* source = (byte*)sourceBytes;
byte* destination = (byte*)destColors;
for (int x = 0; x < count; x++)
{
Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | 255 << 24));
source += 3;
destination += 4;
}
}
/// <inheritdoc />
internal override unsafe void ToZyxBytes(BufferSpan<Color> sourceColors, BufferSpan<byte> destBytes, int count)
{
byte* source = (byte*)sourceColors;
byte* destination = (byte*)destBytes;
for (int x = 0; x < count; x++)
{
*destination = *(source + 2);
*(destination + 1) = *(source + 1);
*(destination + 2) = *(source + 0);
source += 4;
destination += 3;
}
}
/// <inheritdoc />
internal override unsafe void PackFromZyxwBytes(BufferSpan<byte> sourceBytes, BufferSpan<Color> destColors, int count)
{
byte* source = (byte*)sourceBytes;
byte* destination = (byte*)destColors;
for (int x = 0; x < count; x++)
{
Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | *(source + 3) << 24));
source += 4;
destination += 4;
}
}
/// <inheritdoc />
internal override unsafe void ToZyxwBytes(BufferSpan<Color> sourceColors, BufferSpan<byte> destBytes, int count)
{
byte* source = (byte*)sourceColors;
byte* destination = (byte*)destBytes;
for (int x = 0; x < count; x++)
{
*destination = *(source + 2);
*(destination + 1) = *(source + 1);
*(destination + 2) = *(source + 0);
*(destination + 3) = *(source + 3);
source += 4;
destination += 4;
}
}
/// <summary>
/// Value type to store <see cref="Color"/>-s unpacked into multiple <see cref="uint"/>-s.
/// </summary>
private struct UnpackedRGBA
{
private uint r;
private uint g;
private uint b;
private uint a;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Load(uint p)
{
this.r = p;
this.g = p >> Color.GreenShift;
this.b = p >> Color.BlueShift;
this.a = p >> Color.AlphaShift;
}
}
}
}
}

179
src/ImageSharp/Colors/ColorConstants.cs

@ -1,179 +0,0 @@
// <copyright file="ColorConstants.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.Collections.Generic;
/// <summary>
/// Provides useful color definitions.
/// </summary>
public static class ColorConstants
{
/// <summary>
/// Provides a lazy, one time method of returning the colors.
/// </summary>
private static readonly Lazy<Color[]> SafeColors = new Lazy<Color[]>(GetWebSafeColors);
/// <summary>
/// Gets a collection of named, web safe, colors as defined in the CSS Color Module Level 4.
/// </summary>
public static Color[] WebSafeColors => SafeColors.Value;
/// <summary>
/// Returns an array of web safe colors.
/// </summary>
/// <returns>The <see cref="T:Color[]"/></returns>
private static Color[] GetWebSafeColors()
{
return new List<Color>
{
Color.AliceBlue,
Color.AntiqueWhite,
Color.Aqua,
Color.Aquamarine,
Color.Azure,
Color.Beige,
Color.Bisque,
Color.Black,
Color.BlanchedAlmond,
Color.Blue,
Color.BlueViolet,
Color.Brown,
Color.BurlyWood,
Color.CadetBlue,
Color.Chartreuse,
Color.Chocolate,
Color.Coral,
Color.CornflowerBlue,
Color.Cornsilk,
Color.Crimson,
Color.Cyan,
Color.DarkBlue,
Color.DarkCyan,
Color.DarkGoldenrod,
Color.DarkGray,
Color.DarkGreen,
Color.DarkKhaki,
Color.DarkMagenta,
Color.DarkOliveGreen,
Color.DarkOrange,
Color.DarkOrchid,
Color.DarkRed,
Color.DarkSalmon,
Color.DarkSeaGreen,
Color.DarkSlateBlue,
Color.DarkSlateGray,
Color.DarkTurquoise,
Color.DarkViolet,
Color.DeepPink,
Color.DeepSkyBlue,
Color.DimGray,
Color.DodgerBlue,
Color.Firebrick,
Color.FloralWhite,
Color.ForestGreen,
Color.Fuchsia,
Color.Gainsboro,
Color.GhostWhite,
Color.Gold,
Color.Goldenrod,
Color.Gray,
Color.Green,
Color.GreenYellow,
Color.Honeydew,
Color.HotPink,
Color.IndianRed,
Color.Indigo,
Color.Ivory,
Color.Khaki,
Color.Lavender,
Color.LavenderBlush,
Color.LawnGreen,
Color.LemonChiffon,
Color.LightBlue,
Color.LightCoral,
Color.LightCyan,
Color.LightGoldenrodYellow,
Color.LightGray,
Color.LightGreen,
Color.LightPink,
Color.LightSalmon,
Color.LightSeaGreen,
Color.LightSkyBlue,
Color.LightSlateGray,
Color.LightSteelBlue,
Color.LightYellow,
Color.Lime,
Color.LimeGreen,
Color.Linen,
Color.Magenta,
Color.Maroon,
Color.MediumAquamarine,
Color.MediumBlue,
Color.MediumOrchid,
Color.MediumPurple,
Color.MediumSeaGreen,
Color.MediumSlateBlue,
Color.MediumSpringGreen,
Color.MediumTurquoise,
Color.MediumVioletRed,
Color.MidnightBlue,
Color.MintCream,
Color.MistyRose,
Color.Moccasin,
Color.NavajoWhite,
Color.Navy,
Color.OldLace,
Color.Olive,
Color.OliveDrab,
Color.Orange,
Color.OrangeRed,
Color.Orchid,
Color.PaleGoldenrod,
Color.PaleGreen,
Color.PaleTurquoise,
Color.PaleVioletRed,
Color.PapayaWhip,
Color.PeachPuff,
Color.Peru,
Color.Pink,
Color.Plum,
Color.PowderBlue,
Color.Purple,
Color.RebeccaPurple,
Color.Red,
Color.RosyBrown,
Color.RoyalBlue,
Color.SaddleBrown,
Color.Salmon,
Color.SandyBrown,
Color.SeaGreen,
Color.SeaShell,
Color.Sienna,
Color.Silver,
Color.SkyBlue,
Color.SlateBlue,
Color.SlateGray,
Color.Snow,
Color.SpringGreen,
Color.SteelBlue,
Color.Tan,
Color.Teal,
Color.Thistle,
Color.Tomato,
Color.Transparent,
Color.Turquoise,
Color.Violet,
Color.Wheat,
Color.White,
Color.WhiteSmoke,
Color.Yellow,
Color.YellowGreen
}.ToArray();
}
}
}

728
src/ImageSharp/Colors/ColorDefinitions.cs

@ -1,728 +0,0 @@
// <copyright file="ColorDefinitions.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
/// <summary>
/// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255.
/// The color components are stored in red, green, blue, and alpha order.
/// </summary>
/// <remarks>
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
/// </remarks>
public partial struct Color
{
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0F8FF.
/// </summary>
public static readonly Color AliceBlue = NamedColors<Color>.AliceBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FAEBD7.
/// </summary>
public static readonly Color AntiqueWhite = NamedColors<Color>.AntiqueWhite;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FFFF.
/// </summary>
public static readonly Color Aqua = NamedColors<Color>.Aqua;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7FFFD4.
/// </summary>
public static readonly Color Aquamarine = NamedColors<Color>.Aquamarine;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0FFFF.
/// </summary>
public static readonly Color Azure = NamedColors<Color>.Azure;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5F5DC.
/// </summary>
public static readonly Color Beige = NamedColors<Color>.Beige;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFE4C4.
/// </summary>
public static readonly Color Bisque = NamedColors<Color>.Bisque;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #000000.
/// </summary>
public static readonly Color Black = NamedColors<Color>.Black;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFEBCD.
/// </summary>
public static readonly Color BlanchedAlmond = NamedColors<Color>.BlanchedAlmond;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #0000FF.
/// </summary>
public static readonly Color Blue = NamedColors<Color>.Blue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8A2BE2.
/// </summary>
public static readonly Color BlueViolet = NamedColors<Color>.BlueViolet;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #A52A2A.
/// </summary>
public static readonly Color Brown = NamedColors<Color>.Brown;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DEB887.
/// </summary>
public static readonly Color BurlyWood = NamedColors<Color>.BurlyWood;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #5F9EA0.
/// </summary>
public static readonly Color CadetBlue = NamedColors<Color>.CadetBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7FFF00.
/// </summary>
public static readonly Color Chartreuse = NamedColors<Color>.Chartreuse;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D2691E.
/// </summary>
public static readonly Color Chocolate = NamedColors<Color>.Chocolate;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF7F50.
/// </summary>
public static readonly Color Coral = NamedColors<Color>.Coral;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #6495ED.
/// </summary>
public static readonly Color CornflowerBlue = NamedColors<Color>.CornflowerBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFF8DC.
/// </summary>
public static readonly Color Cornsilk = NamedColors<Color>.Cornsilk;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DC143C.
/// </summary>
public static readonly Color Crimson = NamedColors<Color>.Crimson;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FFFF.
/// </summary>
public static readonly Color Cyan = NamedColors<Color>.Cyan;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00008B.
/// </summary>
public static readonly Color DarkBlue = NamedColors<Color>.DarkBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #008B8B.
/// </summary>
public static readonly Color DarkCyan = NamedColors<Color>.DarkCyan;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B8860B.
/// </summary>
public static readonly Color DarkGoldenrod = NamedColors<Color>.DarkGoldenrod;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #A9A9A9.
/// </summary>
public static readonly Color DarkGray = NamedColors<Color>.DarkGray;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #006400.
/// </summary>
public static readonly Color DarkGreen = NamedColors<Color>.DarkGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #BDB76B.
/// </summary>
public static readonly Color DarkKhaki = NamedColors<Color>.DarkKhaki;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8B008B.
/// </summary>
public static readonly Color DarkMagenta = NamedColors<Color>.DarkMagenta;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #556B2F.
/// </summary>
public static readonly Color DarkOliveGreen = NamedColors<Color>.DarkOliveGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF8C00.
/// </summary>
public static readonly Color DarkOrange = NamedColors<Color>.DarkOrange;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9932CC.
/// </summary>
public static readonly Color DarkOrchid = NamedColors<Color>.DarkOrchid;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8B0000.
/// </summary>
public static readonly Color DarkRed = NamedColors<Color>.DarkRed;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #E9967A.
/// </summary>
public static readonly Color DarkSalmon = NamedColors<Color>.DarkSalmon;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8FBC8B.
/// </summary>
public static readonly Color DarkSeaGreen = NamedColors<Color>.DarkSeaGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #483D8B.
/// </summary>
public static readonly Color DarkSlateBlue = NamedColors<Color>.DarkSlateBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #2F4F4F.
/// </summary>
public static readonly Color DarkSlateGray = NamedColors<Color>.DarkSlateGray;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00CED1.
/// </summary>
public static readonly Color DarkTurquoise = NamedColors<Color>.DarkTurquoise;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9400D3.
/// </summary>
public static readonly Color DarkViolet = NamedColors<Color>.DarkViolet;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF1493.
/// </summary>
public static readonly Color DeepPink = NamedColors<Color>.DeepPink;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00BFFF.
/// </summary>
public static readonly Color DeepSkyBlue = NamedColors<Color>.DeepSkyBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #696969.
/// </summary>
public static readonly Color DimGray = NamedColors<Color>.DimGray;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #1E90FF.
/// </summary>
public static readonly Color DodgerBlue = NamedColors<Color>.DodgerBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B22222.
/// </summary>
public static readonly Color Firebrick = NamedColors<Color>.Firebrick;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFAF0.
/// </summary>
public static readonly Color FloralWhite = NamedColors<Color>.FloralWhite;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #228B22.
/// </summary>
public static readonly Color ForestGreen = NamedColors<Color>.ForestGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF00FF.
/// </summary>
public static readonly Color Fuchsia = NamedColors<Color>.Fuchsia;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DCDCDC.
/// </summary>
public static readonly Color Gainsboro = NamedColors<Color>.Gainsboro;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F8F8FF.
/// </summary>
public static readonly Color GhostWhite = NamedColors<Color>.GhostWhite;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFD700.
/// </summary>
public static readonly Color Gold = NamedColors<Color>.Gold;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DAA520.
/// </summary>
public static readonly Color Goldenrod = NamedColors<Color>.Goldenrod;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #808080.
/// </summary>
public static readonly Color Gray = NamedColors<Color>.Gray;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #008000.
/// </summary>
public static readonly Color Green = NamedColors<Color>.Green;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #ADFF2F.
/// </summary>
public static readonly Color GreenYellow = NamedColors<Color>.GreenYellow;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0FFF0.
/// </summary>
public static readonly Color Honeydew = NamedColors<Color>.Honeydew;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF69B4.
/// </summary>
public static readonly Color HotPink = NamedColors<Color>.HotPink;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #CD5C5C.
/// </summary>
public static readonly Color IndianRed = NamedColors<Color>.IndianRed;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #4B0082.
/// </summary>
public static readonly Color Indigo = NamedColors<Color>.Indigo;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFF0.
/// </summary>
public static readonly Color Ivory = NamedColors<Color>.Ivory;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0E68C.
/// </summary>
public static readonly Color Khaki = NamedColors<Color>.Khaki;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #E6E6FA.
/// </summary>
public static readonly Color Lavender = NamedColors<Color>.Lavender;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFF0F5.
/// </summary>
public static readonly Color LavenderBlush = NamedColors<Color>.LavenderBlush;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7CFC00.
/// </summary>
public static readonly Color LawnGreen = NamedColors<Color>.LawnGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFACD.
/// </summary>
public static readonly Color LemonChiffon = NamedColors<Color>.LemonChiffon;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #ADD8E6.
/// </summary>
public static readonly Color LightBlue = NamedColors<Color>.LightBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F08080.
/// </summary>
public static readonly Color LightCoral = NamedColors<Color>.LightCoral;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #E0FFFF.
/// </summary>
public static readonly Color LightCyan = NamedColors<Color>.LightCyan;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FAFAD2.
/// </summary>
public static readonly Color LightGoldenrodYellow = NamedColors<Color>.LightGoldenrodYellow;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D3D3D3.
/// </summary>
public static readonly Color LightGray = NamedColors<Color>.LightGray;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #90EE90.
/// </summary>
public static readonly Color LightGreen = NamedColors<Color>.LightGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFB6C1.
/// </summary>
public static readonly Color LightPink = NamedColors<Color>.LightPink;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFA07A.
/// </summary>
public static readonly Color LightSalmon = NamedColors<Color>.LightSalmon;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #20B2AA.
/// </summary>
public static readonly Color LightSeaGreen = NamedColors<Color>.LightSeaGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #87CEFA.
/// </summary>
public static readonly Color LightSkyBlue = NamedColors<Color>.LightSkyBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #778899.
/// </summary>
public static readonly Color LightSlateGray = NamedColors<Color>.LightSlateGray;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B0C4DE.
/// </summary>
public static readonly Color LightSteelBlue = NamedColors<Color>.LightSteelBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFE0.
/// </summary>
public static readonly Color LightYellow = NamedColors<Color>.LightYellow;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FF00.
/// </summary>
public static readonly Color Lime = NamedColors<Color>.Lime;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #32CD32.
/// </summary>
public static readonly Color LimeGreen = NamedColors<Color>.LimeGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FAF0E6.
/// </summary>
public static readonly Color Linen = NamedColors<Color>.Linen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF00FF.
/// </summary>
public static readonly Color Magenta = NamedColors<Color>.Magenta;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #800000.
/// </summary>
public static readonly Color Maroon = NamedColors<Color>.Maroon;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #66CDAA.
/// </summary>
public static readonly Color MediumAquamarine = NamedColors<Color>.MediumAquamarine;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #0000CD.
/// </summary>
public static readonly Color MediumBlue = NamedColors<Color>.MediumBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #BA55D3.
/// </summary>
public static readonly Color MediumOrchid = NamedColors<Color>.MediumOrchid;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9370DB.
/// </summary>
public static readonly Color MediumPurple = NamedColors<Color>.MediumPurple;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #3CB371.
/// </summary>
public static readonly Color MediumSeaGreen = NamedColors<Color>.MediumSeaGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7B68EE.
/// </summary>
public static readonly Color MediumSlateBlue = NamedColors<Color>.MediumSlateBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FA9A.
/// </summary>
public static readonly Color MediumSpringGreen = NamedColors<Color>.MediumSpringGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #48D1CC.
/// </summary>
public static readonly Color MediumTurquoise = NamedColors<Color>.MediumTurquoise;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #C71585.
/// </summary>
public static readonly Color MediumVioletRed = NamedColors<Color>.MediumVioletRed;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #191970.
/// </summary>
public static readonly Color MidnightBlue = NamedColors<Color>.MidnightBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5FFFA.
/// </summary>
public static readonly Color MintCream = NamedColors<Color>.MintCream;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFE4E1.
/// </summary>
public static readonly Color MistyRose = NamedColors<Color>.MistyRose;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFE4B5.
/// </summary>
public static readonly Color Moccasin = NamedColors<Color>.Moccasin;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFDEAD.
/// </summary>
public static readonly Color NavajoWhite = NamedColors<Color>.NavajoWhite;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #000080.
/// </summary>
public static readonly Color Navy = NamedColors<Color>.Navy;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FDF5E6.
/// </summary>
public static readonly Color OldLace = NamedColors<Color>.OldLace;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #808000.
/// </summary>
public static readonly Color Olive = NamedColors<Color>.Olive;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #6B8E23.
/// </summary>
public static readonly Color OliveDrab = NamedColors<Color>.OliveDrab;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFA500.
/// </summary>
public static readonly Color Orange = NamedColors<Color>.Orange;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF4500.
/// </summary>
public static readonly Color OrangeRed = NamedColors<Color>.OrangeRed;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DA70D6.
/// </summary>
public static readonly Color Orchid = NamedColors<Color>.Orchid;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #EEE8AA.
/// </summary>
public static readonly Color PaleGoldenrod = NamedColors<Color>.PaleGoldenrod;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #98FB98.
/// </summary>
public static readonly Color PaleGreen = NamedColors<Color>.PaleGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #AFEEEE.
/// </summary>
public static readonly Color PaleTurquoise = NamedColors<Color>.PaleTurquoise;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DB7093.
/// </summary>
public static readonly Color PaleVioletRed = NamedColors<Color>.PaleVioletRed;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFEFD5.
/// </summary>
public static readonly Color PapayaWhip = NamedColors<Color>.PapayaWhip;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFDAB9.
/// </summary>
public static readonly Color PeachPuff = NamedColors<Color>.PeachPuff;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #CD853F.
/// </summary>
public static readonly Color Peru = NamedColors<Color>.Peru;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFC0CB.
/// </summary>
public static readonly Color Pink = NamedColors<Color>.Pink;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DDA0DD.
/// </summary>
public static readonly Color Plum = NamedColors<Color>.Plum;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B0E0E6.
/// </summary>
public static readonly Color PowderBlue = NamedColors<Color>.PowderBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #800080.
/// </summary>
public static readonly Color Purple = NamedColors<Color>.Purple;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #663399.
/// </summary>
public static readonly Color RebeccaPurple = NamedColors<Color>.RebeccaPurple;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF0000.
/// </summary>
public static readonly Color Red = NamedColors<Color>.Red;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #BC8F8F.
/// </summary>
public static readonly Color RosyBrown = NamedColors<Color>.RosyBrown;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #4169E1.
/// </summary>
public static readonly Color RoyalBlue = NamedColors<Color>.RoyalBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8B4513.
/// </summary>
public static readonly Color SaddleBrown = NamedColors<Color>.SaddleBrown;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FA8072.
/// </summary>
public static readonly Color Salmon = NamedColors<Color>.Salmon;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F4A460.
/// </summary>
public static readonly Color SandyBrown = NamedColors<Color>.SandyBrown;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #2E8B57.
/// </summary>
public static readonly Color SeaGreen = NamedColors<Color>.SeaGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFF5EE.
/// </summary>
public static readonly Color SeaShell = NamedColors<Color>.SeaShell;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #A0522D.
/// </summary>
public static readonly Color Sienna = NamedColors<Color>.Sienna;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #C0C0C0.
/// </summary>
public static readonly Color Silver = NamedColors<Color>.Silver;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #87CEEB.
/// </summary>
public static readonly Color SkyBlue = NamedColors<Color>.SkyBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #6A5ACD.
/// </summary>
public static readonly Color SlateBlue = NamedColors<Color>.SlateBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #708090.
/// </summary>
public static readonly Color SlateGray = NamedColors<Color>.SlateGray;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFAFA.
/// </summary>
public static readonly Color Snow = NamedColors<Color>.Snow;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FF7F.
/// </summary>
public static readonly Color SpringGreen = NamedColors<Color>.SpringGreen;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #4682B4.
/// </summary>
public static readonly Color SteelBlue = NamedColors<Color>.SteelBlue;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D2B48C.
/// </summary>
public static readonly Color Tan = NamedColors<Color>.Tan;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #008080.
/// </summary>
public static readonly Color Teal = NamedColors<Color>.Teal;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D8BFD8.
/// </summary>
public static readonly Color Thistle = NamedColors<Color>.Thistle;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF6347.
/// </summary>
public static readonly Color Tomato = NamedColors<Color>.Tomato;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFFF.
/// </summary>
public static readonly Color Transparent = NamedColors<Color>.Transparent;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #40E0D0.
/// </summary>
public static readonly Color Turquoise = NamedColors<Color>.Turquoise;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #EE82EE.
/// </summary>
public static readonly Color Violet = NamedColors<Color>.Violet;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5DEB3.
/// </summary>
public static readonly Color Wheat = NamedColors<Color>.Wheat;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFFF.
/// </summary>
public static readonly Color White = NamedColors<Color>.White;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5F5F5.
/// </summary>
public static readonly Color WhiteSmoke = NamedColors<Color>.WhiteSmoke;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFF00.
/// </summary>
public static readonly Color Yellow = NamedColors<Color>.Yellow;
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9ACD32.
/// </summary>
public static readonly Color YellowGreen = NamedColors<Color>.YellowGreen;
}
}

255
src/ImageSharp/Colors/ColorTransforms.cs

@ -1,255 +0,0 @@
// <copyright file="ColorTransforms.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.Numerics;
/// <summary>
/// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255.
/// The color components are stored in red, green, blue, and alpha order.
/// </summary>
/// <remarks>
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
/// </remarks>
public partial struct Color
{
/// <summary>
/// Adds the second color to the first.
/// </summary>
/// <param name="left">The first source color.</param>
/// <param name="right">The second source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color operator +(Color left, Color right)
{
Vector4 add = left.ToVector4() + right.ToVector4();
return new Color(Pack(ref add));
}
/// <summary>
/// Subtracts the second color from the first.
/// </summary>
/// <param name="left">The first source color.</param>
/// <param name="right">The second source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color operator -(Color left, Color right)
{
Vector4 sub = left.ToVector4() - right.ToVector4();
return new Color(Pack(ref sub));
}
/// <summary>
/// The blending formula simply selects the source color.
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color Normal(Color backdrop, Color source)
{
Vector4 normal = Vector4BlendTransforms.Normal(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref normal));
}
/// <summary>
/// Blends two colors by multiplication.
/// <remarks>
/// The source color is multiplied by the destination color and replaces the destination.
/// The resultant color is always at least as dark as either the source or destination color.
/// Multiplying any color with black results in black. Multiplying any color with white preserves the
/// original color.
/// </remarks>
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color Multiply(Color backdrop, Color source)
{
Vector4 multiply = Vector4BlendTransforms.Multiply(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref multiply));
}
/// <summary>
/// Multiplies the complements of the backdrop and source color values, then complements the result.
/// <remarks>
/// The result color is always at least as light as either of the two constituent colors. Screening any
/// color with white produces white; screening with black leaves the original color unchanged.
/// The effect is similar to projecting multiple photographic slides simultaneously onto a single screen.
/// </remarks>
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color Screen(Color backdrop, Color source)
{
Vector4 subtract = Vector4BlendTransforms.Screen(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref subtract));
}
/// <summary>
/// Multiplies or screens the colors, depending on the source color value. The effect is similar to
/// shining a harsh spotlight on the backdrop.
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color HardLight(Color backdrop, Color source)
{
Vector4 hardlight = Vector4BlendTransforms.HardLight(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref hardlight));
}
/// <summary>
/// Multiplies or screens the colors, depending on the backdrop color value.
/// <remarks>
/// Source colors overlay the backdrop while preserving its highlights and shadows.
/// The backdrop color is not replaced but is mixed with the source color to reflect the lightness or darkness
/// of the backdrop.
/// </remarks>
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color Overlay(Color backdrop, Color source)
{
Vector4 overlay = Vector4BlendTransforms.Overlay(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref overlay));
}
/// <summary>
/// Selects the darker of the backdrop and source colors.
/// The backdrop is replaced with the source where the source is darker; otherwise, it is left unchanged.
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color Darken(Color backdrop, Color source)
{
Vector4 darken = Vector4BlendTransforms.Darken(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref darken));
}
/// <summary>
/// Selects the lighter of the backdrop and source colors.
/// The backdrop is replaced with the source where the source is lighter; otherwise, it is left unchanged.
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color Lighten(Color backdrop, Color source)
{
Vector4 lighten = Vector4BlendTransforms.Lighten(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref lighten));
}
/// <summary>
/// Darkens or lightens the colors, depending on the source color value. The effect is similar to shining
/// a diffused spotlight on the backdrop.
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color SoftLight(Color backdrop, Color source)
{
Vector4 softlight = Vector4BlendTransforms.SoftLight(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref softlight));
}
/// <summary>
/// Brightens the backdrop color to reflect the source color. Painting with black produces no changes.
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color ColorDodge(Color backdrop, Color source)
{
Vector4 dodge = Vector4BlendTransforms.Dodge(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref dodge));
}
/// <summary>
/// Darkens the backdrop color to reflect the source color. Painting with white produces no change.
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color ColorBurn(Color backdrop, Color source)
{
Vector4 burn = Vector4BlendTransforms.Burn(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref burn));
}
/// <summary>
/// Subtracts the darker of the two constituent colors from the lighter color.
/// Painting with white inverts the backdrop color; painting with black produces no change.
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color Difference(Color backdrop, Color source)
{
Vector4 difference = Vector4BlendTransforms.Difference(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref difference));
}
/// <summary>
/// Produces an effect similar to that of the <see cref="Difference"/> mode but lower in contrast. Painting with white
/// inverts the backdrop color; painting with black produces no change
/// </summary>
/// <param name="backdrop">The backdrop color.</param>
/// <param name="source">The source color.</param>
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
public static Color Exclusion(Color backdrop, Color source)
{
Vector4 exclusion = Vector4BlendTransforms.Exclusion(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref exclusion));
}
/// <summary>
/// Linearly interpolates from one color to another based on the given weighting.
/// </summary>
/// <param name="from">The first color value.</param>
/// <param name="to">The second color value.</param>
/// <param name="amount">
/// A value between 0 and 1 indicating the weight of the second source vector.
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
/// </param>
/// <returns>
/// The <see cref="Color"/>
/// </returns>
public static Color Lerp(Color from, Color to, float amount)
{
return new Color(Vector4.Lerp(from.ToVector4(), to.ToVector4(), amount));
}
}
}

727
src/ImageSharp/Colors/NamedColors{TColor}.cs

@ -1,727 +0,0 @@
// <copyright file="NamedColors{TColor}.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;
/// <summary>
/// A set of named colors mapped to the provided Color space.
/// </summary>
/// <typeparam name="TColor">The type of the color.</typeparam>
public static class NamedColors<TColor>
where TColor : struct, IPixel<TColor>
{
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0F8FF.
/// </summary>
public static readonly TColor AliceBlue = ColorBuilder<TColor>.FromRGBA(240, 248, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FAEBD7.
/// </summary>
public static readonly TColor AntiqueWhite = ColorBuilder<TColor>.FromRGBA(250, 235, 215, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FFFF.
/// </summary>
public static readonly TColor Aqua = ColorBuilder<TColor>.FromRGBA(0, 255, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7FFFD4.
/// </summary>
public static readonly TColor Aquamarine = ColorBuilder<TColor>.FromRGBA(127, 255, 212, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0FFFF.
/// </summary>
public static readonly TColor Azure = ColorBuilder<TColor>.FromRGBA(240, 255, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5F5DC.
/// </summary>
public static readonly TColor Beige = ColorBuilder<TColor>.FromRGBA(245, 245, 220, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFE4C4.
/// </summary>
public static readonly TColor Bisque = ColorBuilder<TColor>.FromRGBA(255, 228, 196, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #000000.
/// </summary>
public static readonly TColor Black = ColorBuilder<TColor>.FromRGBA(0, 0, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFEBCD.
/// </summary>
public static readonly TColor BlanchedAlmond = ColorBuilder<TColor>.FromRGBA(255, 235, 205, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #0000FF.
/// </summary>
public static readonly TColor Blue = ColorBuilder<TColor>.FromRGBA(0, 0, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8A2BE2.
/// </summary>
public static readonly TColor BlueViolet = ColorBuilder<TColor>.FromRGBA(138, 43, 226, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #A52A2A.
/// </summary>
public static readonly TColor Brown = ColorBuilder<TColor>.FromRGBA(165, 42, 42, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DEB887.
/// </summary>
public static readonly TColor BurlyWood = ColorBuilder<TColor>.FromRGBA(222, 184, 135, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #5F9EA0.
/// </summary>
public static readonly TColor CadetBlue = ColorBuilder<TColor>.FromRGBA(95, 158, 160, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7FFF00.
/// </summary>
public static readonly TColor Chartreuse = ColorBuilder<TColor>.FromRGBA(127, 255, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D2691E.
/// </summary>
public static readonly TColor Chocolate = ColorBuilder<TColor>.FromRGBA(210, 105, 30, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF7F50.
/// </summary>
public static readonly TColor Coral = ColorBuilder<TColor>.FromRGBA(255, 127, 80, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #6495ED.
/// </summary>
public static readonly TColor CornflowerBlue = ColorBuilder<TColor>.FromRGBA(100, 149, 237, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFF8DC.
/// </summary>
public static readonly TColor Cornsilk = ColorBuilder<TColor>.FromRGBA(255, 248, 220, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DC143C.
/// </summary>
public static readonly TColor Crimson = ColorBuilder<TColor>.FromRGBA(220, 20, 60, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FFFF.
/// </summary>
public static readonly TColor Cyan = ColorBuilder<TColor>.FromRGBA(0, 255, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00008B.
/// </summary>
public static readonly TColor DarkBlue = ColorBuilder<TColor>.FromRGBA(0, 0, 139, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #008B8B.
/// </summary>
public static readonly TColor DarkCyan = ColorBuilder<TColor>.FromRGBA(0, 139, 139, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B8860B.
/// </summary>
public static readonly TColor DarkGoldenrod = ColorBuilder<TColor>.FromRGBA(184, 134, 11, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #A9A9A9.
/// </summary>
public static readonly TColor DarkGray = ColorBuilder<TColor>.FromRGBA(169, 169, 169, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #006400.
/// </summary>
public static readonly TColor DarkGreen = ColorBuilder<TColor>.FromRGBA(0, 100, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #BDB76B.
/// </summary>
public static readonly TColor DarkKhaki = ColorBuilder<TColor>.FromRGBA(189, 183, 107, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8B008B.
/// </summary>
public static readonly TColor DarkMagenta = ColorBuilder<TColor>.FromRGBA(139, 0, 139, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #556B2F.
/// </summary>
public static readonly TColor DarkOliveGreen = ColorBuilder<TColor>.FromRGBA(85, 107, 47, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF8C00.
/// </summary>
public static readonly TColor DarkOrange = ColorBuilder<TColor>.FromRGBA(255, 140, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9932CC.
/// </summary>
public static readonly TColor DarkOrchid = ColorBuilder<TColor>.FromRGBA(153, 50, 204, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8B0000.
/// </summary>
public static readonly TColor DarkRed = ColorBuilder<TColor>.FromRGBA(139, 0, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #E9967A.
/// </summary>
public static readonly TColor DarkSalmon = ColorBuilder<TColor>.FromRGBA(233, 150, 122, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8FBC8B.
/// </summary>
public static readonly TColor DarkSeaGreen = ColorBuilder<TColor>.FromRGBA(143, 188, 139, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #483D8B.
/// </summary>
public static readonly TColor DarkSlateBlue = ColorBuilder<TColor>.FromRGBA(72, 61, 139, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #2F4F4F.
/// </summary>
public static readonly TColor DarkSlateGray = ColorBuilder<TColor>.FromRGBA(47, 79, 79, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00CED1.
/// </summary>
public static readonly TColor DarkTurquoise = ColorBuilder<TColor>.FromRGBA(0, 206, 209, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9400D3.
/// </summary>
public static readonly TColor DarkViolet = ColorBuilder<TColor>.FromRGBA(148, 0, 211, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF1493.
/// </summary>
public static readonly TColor DeepPink = ColorBuilder<TColor>.FromRGBA(255, 20, 147, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00BFFF.
/// </summary>
public static readonly TColor DeepSkyBlue = ColorBuilder<TColor>.FromRGBA(0, 191, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #696969.
/// </summary>
public static readonly TColor DimGray = ColorBuilder<TColor>.FromRGBA(105, 105, 105, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #1E90FF.
/// </summary>
public static readonly TColor DodgerBlue = ColorBuilder<TColor>.FromRGBA(30, 144, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B22222.
/// </summary>
public static readonly TColor Firebrick = ColorBuilder<TColor>.FromRGBA(178, 34, 34, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFAF0.
/// </summary>
public static readonly TColor FloralWhite = ColorBuilder<TColor>.FromRGBA(255, 250, 240, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #228B22.
/// </summary>
public static readonly TColor ForestGreen = ColorBuilder<TColor>.FromRGBA(34, 139, 34, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF00FF.
/// </summary>
public static readonly TColor Fuchsia = ColorBuilder<TColor>.FromRGBA(255, 0, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DCDCDC.
/// </summary>
public static readonly TColor Gainsboro = ColorBuilder<TColor>.FromRGBA(220, 220, 220, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F8F8FF.
/// </summary>
public static readonly TColor GhostWhite = ColorBuilder<TColor>.FromRGBA(248, 248, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFD700.
/// </summary>
public static readonly TColor Gold = ColorBuilder<TColor>.FromRGBA(255, 215, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DAA520.
/// </summary>
public static readonly TColor Goldenrod = ColorBuilder<TColor>.FromRGBA(218, 165, 32, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #808080.
/// </summary>
public static readonly TColor Gray = ColorBuilder<TColor>.FromRGBA(128, 128, 128, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #008000.
/// </summary>
public static readonly TColor Green = ColorBuilder<TColor>.FromRGBA(0, 128, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #ADFF2F.
/// </summary>
public static readonly TColor GreenYellow = ColorBuilder<TColor>.FromRGBA(173, 255, 47, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0FFF0.
/// </summary>
public static readonly TColor Honeydew = ColorBuilder<TColor>.FromRGBA(240, 255, 240, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF69B4.
/// </summary>
public static readonly TColor HotPink = ColorBuilder<TColor>.FromRGBA(255, 105, 180, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #CD5C5C.
/// </summary>
public static readonly TColor IndianRed = ColorBuilder<TColor>.FromRGBA(205, 92, 92, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #4B0082.
/// </summary>
public static readonly TColor Indigo = ColorBuilder<TColor>.FromRGBA(75, 0, 130, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFF0.
/// </summary>
public static readonly TColor Ivory = ColorBuilder<TColor>.FromRGBA(255, 255, 240, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0E68C.
/// </summary>
public static readonly TColor Khaki = ColorBuilder<TColor>.FromRGBA(240, 230, 140, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #E6E6FA.
/// </summary>
public static readonly TColor Lavender = ColorBuilder<TColor>.FromRGBA(230, 230, 250, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFF0F5.
/// </summary>
public static readonly TColor LavenderBlush = ColorBuilder<TColor>.FromRGBA(255, 240, 245, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7CFC00.
/// </summary>
public static readonly TColor LawnGreen = ColorBuilder<TColor>.FromRGBA(124, 252, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFACD.
/// </summary>
public static readonly TColor LemonChiffon = ColorBuilder<TColor>.FromRGBA(255, 250, 205, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #ADD8E6.
/// </summary>
public static readonly TColor LightBlue = ColorBuilder<TColor>.FromRGBA(173, 216, 230, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F08080.
/// </summary>
public static readonly TColor LightCoral = ColorBuilder<TColor>.FromRGBA(240, 128, 128, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #E0FFFF.
/// </summary>
public static readonly TColor LightCyan = ColorBuilder<TColor>.FromRGBA(224, 255, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FAFAD2.
/// </summary>
public static readonly TColor LightGoldenrodYellow = ColorBuilder<TColor>.FromRGBA(250, 250, 210, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D3D3D3.
/// </summary>
public static readonly TColor LightGray = ColorBuilder<TColor>.FromRGBA(211, 211, 211, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #90EE90.
/// </summary>
public static readonly TColor LightGreen = ColorBuilder<TColor>.FromRGBA(144, 238, 144, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFB6C1.
/// </summary>
public static readonly TColor LightPink = ColorBuilder<TColor>.FromRGBA(255, 182, 193, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFA07A.
/// </summary>
public static readonly TColor LightSalmon = ColorBuilder<TColor>.FromRGBA(255, 160, 122, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #20B2AA.
/// </summary>
public static readonly TColor LightSeaGreen = ColorBuilder<TColor>.FromRGBA(32, 178, 170, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #87CEFA.
/// </summary>
public static readonly TColor LightSkyBlue = ColorBuilder<TColor>.FromRGBA(135, 206, 250, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #778899.
/// </summary>
public static readonly TColor LightSlateGray = ColorBuilder<TColor>.FromRGBA(119, 136, 153, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B0C4DE.
/// </summary>
public static readonly TColor LightSteelBlue = ColorBuilder<TColor>.FromRGBA(176, 196, 222, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFE0.
/// </summary>
public static readonly TColor LightYellow = ColorBuilder<TColor>.FromRGBA(255, 255, 224, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FF00.
/// </summary>
public static readonly TColor Lime = ColorBuilder<TColor>.FromRGBA(0, 255, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #32CD32.
/// </summary>
public static readonly TColor LimeGreen = ColorBuilder<TColor>.FromRGBA(50, 205, 50, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FAF0E6.
/// </summary>
public static readonly TColor Linen = ColorBuilder<TColor>.FromRGBA(250, 240, 230, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF00FF.
/// </summary>
public static readonly TColor Magenta = ColorBuilder<TColor>.FromRGBA(255, 0, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #800000.
/// </summary>
public static readonly TColor Maroon = ColorBuilder<TColor>.FromRGBA(128, 0, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #66CDAA.
/// </summary>
public static readonly TColor MediumAquamarine = ColorBuilder<TColor>.FromRGBA(102, 205, 170, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #0000CD.
/// </summary>
public static readonly TColor MediumBlue = ColorBuilder<TColor>.FromRGBA(0, 0, 205, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #BA55D3.
/// </summary>
public static readonly TColor MediumOrchid = ColorBuilder<TColor>.FromRGBA(186, 85, 211, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9370DB.
/// </summary>
public static readonly TColor MediumPurple = ColorBuilder<TColor>.FromRGBA(147, 112, 219, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #3CB371.
/// </summary>
public static readonly TColor MediumSeaGreen = ColorBuilder<TColor>.FromRGBA(60, 179, 113, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7B68EE.
/// </summary>
public static readonly TColor MediumSlateBlue = ColorBuilder<TColor>.FromRGBA(123, 104, 238, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FA9A.
/// </summary>
public static readonly TColor MediumSpringGreen = ColorBuilder<TColor>.FromRGBA(0, 250, 154, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #48D1CC.
/// </summary>
public static readonly TColor MediumTurquoise = ColorBuilder<TColor>.FromRGBA(72, 209, 204, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #C71585.
/// </summary>
public static readonly TColor MediumVioletRed = ColorBuilder<TColor>.FromRGBA(199, 21, 133, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #191970.
/// </summary>
public static readonly TColor MidnightBlue = ColorBuilder<TColor>.FromRGBA(25, 25, 112, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5FFFA.
/// </summary>
public static readonly TColor MintCream = ColorBuilder<TColor>.FromRGBA(245, 255, 250, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFE4E1.
/// </summary>
public static readonly TColor MistyRose = ColorBuilder<TColor>.FromRGBA(255, 228, 225, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFE4B5.
/// </summary>
public static readonly TColor Moccasin = ColorBuilder<TColor>.FromRGBA(255, 228, 181, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFDEAD.
/// </summary>
public static readonly TColor NavajoWhite = ColorBuilder<TColor>.FromRGBA(255, 222, 173, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #000080.
/// </summary>
public static readonly TColor Navy = ColorBuilder<TColor>.FromRGBA(0, 0, 128, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FDF5E6.
/// </summary>
public static readonly TColor OldLace = ColorBuilder<TColor>.FromRGBA(253, 245, 230, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #808000.
/// </summary>
public static readonly TColor Olive = ColorBuilder<TColor>.FromRGBA(128, 128, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #6B8E23.
/// </summary>
public static readonly TColor OliveDrab = ColorBuilder<TColor>.FromRGBA(107, 142, 35, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFA500.
/// </summary>
public static readonly TColor Orange = ColorBuilder<TColor>.FromRGBA(255, 165, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF4500.
/// </summary>
public static readonly TColor OrangeRed = ColorBuilder<TColor>.FromRGBA(255, 69, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DA70D6.
/// </summary>
public static readonly TColor Orchid = ColorBuilder<TColor>.FromRGBA(218, 112, 214, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #EEE8AA.
/// </summary>
public static readonly TColor PaleGoldenrod = ColorBuilder<TColor>.FromRGBA(238, 232, 170, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #98FB98.
/// </summary>
public static readonly TColor PaleGreen = ColorBuilder<TColor>.FromRGBA(152, 251, 152, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #AFEEEE.
/// </summary>
public static readonly TColor PaleTurquoise = ColorBuilder<TColor>.FromRGBA(175, 238, 238, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DB7093.
/// </summary>
public static readonly TColor PaleVioletRed = ColorBuilder<TColor>.FromRGBA(219, 112, 147, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFEFD5.
/// </summary>
public static readonly TColor PapayaWhip = ColorBuilder<TColor>.FromRGBA(255, 239, 213, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFDAB9.
/// </summary>
public static readonly TColor PeachPuff = ColorBuilder<TColor>.FromRGBA(255, 218, 185, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #CD853F.
/// </summary>
public static readonly TColor Peru = ColorBuilder<TColor>.FromRGBA(205, 133, 63, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFC0CB.
/// </summary>
public static readonly TColor Pink = ColorBuilder<TColor>.FromRGBA(255, 192, 203, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DDA0DD.
/// </summary>
public static readonly TColor Plum = ColorBuilder<TColor>.FromRGBA(221, 160, 221, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B0E0E6.
/// </summary>
public static readonly TColor PowderBlue = ColorBuilder<TColor>.FromRGBA(176, 224, 230, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #800080.
/// </summary>
public static readonly TColor Purple = ColorBuilder<TColor>.FromRGBA(128, 0, 128, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #663399.
/// </summary>
public static readonly TColor RebeccaPurple = ColorBuilder<TColor>.FromRGBA(102, 51, 153, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF0000.
/// </summary>
public static readonly TColor Red = ColorBuilder<TColor>.FromRGBA(255, 0, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #BC8F8F.
/// </summary>
public static readonly TColor RosyBrown = ColorBuilder<TColor>.FromRGBA(188, 143, 143, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #4169E1.
/// </summary>
public static readonly TColor RoyalBlue = ColorBuilder<TColor>.FromRGBA(65, 105, 225, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8B4513.
/// </summary>
public static readonly TColor SaddleBrown = ColorBuilder<TColor>.FromRGBA(139, 69, 19, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FA8072.
/// </summary>
public static readonly TColor Salmon = ColorBuilder<TColor>.FromRGBA(250, 128, 114, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F4A460.
/// </summary>
public static readonly TColor SandyBrown = ColorBuilder<TColor>.FromRGBA(244, 164, 96, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #2E8B57.
/// </summary>
public static readonly TColor SeaGreen = ColorBuilder<TColor>.FromRGBA(46, 139, 87, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFF5EE.
/// </summary>
public static readonly TColor SeaShell = ColorBuilder<TColor>.FromRGBA(255, 245, 238, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #A0522D.
/// </summary>
public static readonly TColor Sienna = ColorBuilder<TColor>.FromRGBA(160, 82, 45, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #C0C0C0.
/// </summary>
public static readonly TColor Silver = ColorBuilder<TColor>.FromRGBA(192, 192, 192, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #87CEEB.
/// </summary>
public static readonly TColor SkyBlue = ColorBuilder<TColor>.FromRGBA(135, 206, 235, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #6A5ACD.
/// </summary>
public static readonly TColor SlateBlue = ColorBuilder<TColor>.FromRGBA(106, 90, 205, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #708090.
/// </summary>
public static readonly TColor SlateGray = ColorBuilder<TColor>.FromRGBA(112, 128, 144, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFAFA.
/// </summary>
public static readonly TColor Snow = ColorBuilder<TColor>.FromRGBA(255, 250, 250, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FF7F.
/// </summary>
public static readonly TColor SpringGreen = ColorBuilder<TColor>.FromRGBA(0, 255, 127, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #4682B4.
/// </summary>
public static readonly TColor SteelBlue = ColorBuilder<TColor>.FromRGBA(70, 130, 180, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D2B48C.
/// </summary>
public static readonly TColor Tan = ColorBuilder<TColor>.FromRGBA(210, 180, 140, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #008080.
/// </summary>
public static readonly TColor Teal = ColorBuilder<TColor>.FromRGBA(0, 128, 128, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D8BFD8.
/// </summary>
public static readonly TColor Thistle = ColorBuilder<TColor>.FromRGBA(216, 191, 216, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF6347.
/// </summary>
public static readonly TColor Tomato = ColorBuilder<TColor>.FromRGBA(255, 99, 71, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFFF.
/// </summary>
public static readonly TColor Transparent = ColorBuilder<TColor>.FromRGBA(255, 255, 255, 0);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #40E0D0.
/// </summary>
public static readonly TColor Turquoise = ColorBuilder<TColor>.FromRGBA(64, 224, 208, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #EE82EE.
/// </summary>
public static readonly TColor Violet = ColorBuilder<TColor>.FromRGBA(238, 130, 238, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5DEB3.
/// </summary>
public static readonly TColor Wheat = ColorBuilder<TColor>.FromRGBA(245, 222, 179, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFFF.
/// </summary>
public static readonly TColor White = ColorBuilder<TColor>.FromRGBA(255, 255, 255, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5F5F5.
/// </summary>
public static readonly TColor WhiteSmoke = ColorBuilder<TColor>.FromRGBA(245, 245, 245, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFF00.
/// </summary>
public static readonly TColor Yellow = ColorBuilder<TColor>.FromRGBA(255, 255, 0, 255);
/// <summary>
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9ACD32.
/// </summary>
public static readonly TColor YellowGreen = ColorBuilder<TColor>.FromRGBA(154, 205, 50, 255);
}
}

256
src/ImageSharp/Colors/PackedPixel/BulkPixelOperations{TColor}.cs

@ -1,256 +0,0 @@
// <copyright file="BulkPixelOperations{TColor}.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.Numerics;
using System.Runtime.CompilerServices;
/// <summary>
/// A stateless class implementing Strategy Pattern for batched pixel-data conversion operations
/// for pixel buffers of type <typeparamref name="TColor"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
public unsafe class BulkPixelOperations<TColor>
where TColor : struct, IPixel<TColor>
{
/// <summary>
/// The size of <typeparamref name="TColor"/> in bytes
/// </summary>
private static readonly int ColorSize = Unsafe.SizeOf<TColor>();
/// <summary>
/// Gets the global <see cref="BulkPixelOperations{TColor}"/> instance for the pixel type <typeparamref name="TColor"/>
/// </summary>
public static BulkPixelOperations<TColor> Instance { get; } = default(TColor).CreateBulkOperations();
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromVector4(Vector4)"/>
/// </summary>
/// <param name="sourceVectors">The <see cref="BufferSpan{T}"/> to the source vectors.</param>
/// <param name="destColors">The <see cref="BufferSpan{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromVector4(
BufferSpan<Vector4> sourceVectors,
BufferSpan<TColor> destColors,
int count)
{
Vector4* sp = (Vector4*)sourceVectors.PointerAtOffset;
byte* dp = (byte*)destColors;
for (int i = 0; i < count; i++)
{
Vector4 v = Unsafe.Read<Vector4>(sp);
TColor c = default(TColor);
c.PackFromVector4(v);
Unsafe.Write(dp, c);
sp++;
dp += ColorSize;
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.ToVector4()"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="BufferSpan{T}"/> to the source colors.</param>
/// <param name="destVectors">The <see cref="BufferSpan{T}"/> to the destination vectors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToVector4(
BufferSpan<TColor> sourceColors,
BufferSpan<Vector4> destVectors,
int count)
{
byte* sp = (byte*)sourceColors;
Vector4* dp = (Vector4*)destVectors.PointerAtOffset;
for (int i = 0; i < count; i++)
{
TColor c = Unsafe.Read<TColor>(sp);
*dp = c.ToVector4();
sp += ColorSize;
dp++;
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Xyz"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="BufferSpan{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="BufferSpan{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromXyzBytes(
BufferSpan<byte> sourceBytes,
BufferSpan<TColor> destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
byte* dp = (byte*)destColors.PointerAtOffset;
for (int i = 0; i < count; i++)
{
TColor c = default(TColor);
c.PackFromBytes(sp[0], sp[1], sp[2], 255);
Unsafe.Write(dp, c);
sp += 3;
dp += ColorSize;
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.ToXyzBytes(byte[], int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="BufferSpan{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="BufferSpan{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToXyzBytes(BufferSpan<TColor> sourceColors, BufferSpan<byte> destBytes, int count)
{
byte* sp = (byte*)sourceColors;
byte[] dest = destBytes.Array;
for (int i = destBytes.Start; i < destBytes.Start + (count * 3); i += 3)
{
TColor c = Unsafe.Read<TColor>(sp);
c.ToXyzBytes(dest, i);
sp += ColorSize;
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Xyzw"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="BufferSpan{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="BufferSpan{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromXyzwBytes(
BufferSpan<byte> sourceBytes,
BufferSpan<TColor> destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
byte* dp = (byte*)destColors.PointerAtOffset;
for (int i = 0; i < count; i++)
{
TColor c = default(TColor);
c.PackFromBytes(sp[0], sp[1], sp[2], sp[3]);
Unsafe.Write(dp, c);
sp += 4;
dp += ColorSize;
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.ToXyzwBytes(byte[], int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="BufferSpan{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="BufferSpan{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToXyzwBytes(
BufferSpan<TColor> sourceColors,
BufferSpan<byte> destBytes,
int count)
{
byte* sp = (byte*)sourceColors;
byte[] dest = destBytes.Array;
for (int i = destBytes.Start; i < destBytes.Start + (count * 4); i += 4)
{
TColor c = Unsafe.Read<TColor>(sp);
c.ToXyzwBytes(dest, i);
sp += ColorSize;
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Zyx"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="BufferSpan{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="BufferSpan{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromZyxBytes(
BufferSpan<byte> sourceBytes,
BufferSpan<TColor> destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
byte* dp = (byte*)destColors.PointerAtOffset;
for (int i = 0; i < count; i++)
{
TColor c = default(TColor);
c.PackFromBytes(sp[2], sp[1], sp[0], 255);
Unsafe.Write(dp, c);
sp += 3;
dp += ColorSize;
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.ToZyxBytes(byte[], int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="BufferSpan{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="BufferSpan{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToZyxBytes(BufferSpan<TColor> sourceColors, BufferSpan<byte> destBytes, int count)
{
byte* sp = (byte*)sourceColors;
byte[] dest = destBytes.Array;
for (int i = destBytes.Start; i < destBytes.Start + (count * 3); i += 3)
{
TColor c = Unsafe.Read<TColor>(sp);
c.ToZyxBytes(dest, i);
sp += ColorSize;
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Zyxw"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="BufferSpan{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="BufferSpan{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromZyxwBytes(
BufferSpan<byte> sourceBytes,
BufferSpan<TColor> destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
byte* dp = (byte*)destColors.PointerAtOffset;
for (int i = 0; i < count; i++)
{
TColor c = default(TColor);
c.PackFromBytes(sp[2], sp[1], sp[0], sp[3]);
Unsafe.Write(dp, c);
sp += 4;
dp += ColorSize;
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.ToZyxwBytes(byte[], int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="BufferSpan{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="BufferSpan{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToZyxwBytes(
BufferSpan<TColor> sourceColors,
BufferSpan<byte> destBytes,
int count)
{
byte* sp = (byte*)sourceColors;
byte[] dest = destBytes.Array;
for (int i = destBytes.Start; i < destBytes.Start + (count * 4); i += 4)
{
TColor c = Unsafe.Read<TColor>(sp);
c.ToZyxwBytes(dest, i);
sp += ColorSize;
}
}
}
}

3
src/ImageSharp/Colors/PackedPixel/README.md

@ -1,3 +0,0 @@
Pixel formats adapted and extended from:
https://github.com/MonoGame/MonoGame

7
src/ImageSharp/Colors/Spaces/Bgra32.cs

@ -8,6 +8,7 @@ namespace ImageSharp.Colors.Spaces
using System;
using System.ComponentModel;
using System.Numerics;
using ImageSharp.PixelFormats;
/// <summary>
/// Represents an BGRA (blue, green, red, alpha) color.
@ -79,16 +80,16 @@ namespace ImageSharp.Colors.Spaces
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
/// Allows the implicit conversion of an instance of <see cref="Rgba32"/> to a
/// <see cref="Bgra32"/>.
/// </summary>
/// <param name="color">
/// The instance of <see cref="Color"/> to convert.
/// The instance of <see cref="Rgba32"/> to convert.
/// </param>
/// <returns>
/// An instance of <see cref="Bgra32"/>.
/// </returns>
public static implicit operator Bgra32(Color color)
public static implicit operator Bgra32(Rgba32 color)
{
return new Bgra32(color.B, color.G, color.R, color.A);
}

7
src/ImageSharp/Colors/Spaces/CieLab.cs

@ -8,6 +8,7 @@ namespace ImageSharp.Colors.Spaces
using System;
using System.ComponentModel;
using System.Numerics;
using ImageSharp.PixelFormats;
/// <summary>
/// Represents an CIE LAB 1976 color.
@ -72,16 +73,16 @@ namespace ImageSharp.Colors.Spaces
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
/// Allows the implicit conversion of an instance of <see cref="Rgba32"/> to a
/// <see cref="CieLab"/>.
/// </summary>
/// <param name="color">
/// The instance of <see cref="Color"/> to convert.
/// The instance of <see cref="Rgba32"/> to convert.
/// </param>
/// <returns>
/// An instance of <see cref="CieLab"/>.
/// </returns>
public static implicit operator CieLab(Color color)
public static implicit operator CieLab(Rgba32 color)
{
// First convert to CIE XYZ
Vector4 vector = color.ToVector4().Expand();

7
src/ImageSharp/Colors/Spaces/CieXyz.cs

@ -8,6 +8,7 @@ namespace ImageSharp.Colors.Spaces
using System;
using System.ComponentModel;
using System.Numerics;
using ImageSharp.PixelFormats;
/// <summary>
/// Represents an CIE 1931 color
@ -63,16 +64,16 @@ namespace ImageSharp.Colors.Spaces
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
/// Allows the implicit conversion of an instance of <see cref="Rgba32"/> to a
/// <see cref="CieXyz"/>.
/// </summary>
/// <param name="color">
/// The instance of <see cref="Color"/> to convert.
/// The instance of <see cref="Rgba32"/> to convert.
/// </param>
/// <returns>
/// An instance of <see cref="CieXyz"/>.
/// </returns>
public static implicit operator CieXyz(Color color)
public static implicit operator CieXyz(Rgba32 color)
{
Vector4 vector = color.ToVector4().Expand();

5
src/ImageSharp/Colors/Spaces/Cmyk.cs

@ -8,6 +8,7 @@ namespace ImageSharp.Colors.Spaces
using System;
using System.ComponentModel;
using System.Numerics;
using ImageSharp.PixelFormats;
/// <summary>
/// Represents an CMYK (cyan, magenta, yellow, keyline) color.
@ -78,7 +79,7 @@ namespace ImageSharp.Colors.Spaces
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
/// Allows the implicit conversion of an instance of <see cref="Rgba32"/> to a
/// <see cref="Cmyk"/>.
/// </summary>
/// <param name="color">
@ -87,7 +88,7 @@ namespace ImageSharp.Colors.Spaces
/// <returns>
/// An instance of <see cref="Cmyk"/>.
/// </returns>
public static implicit operator Cmyk(Color color)
public static implicit operator Cmyk(Rgba32 color)
{
float c = 1f - (color.R / 255F);
float m = 1f - (color.G / 255F);

7
src/ImageSharp/Colors/Spaces/Hsl.cs

@ -8,6 +8,7 @@ namespace ImageSharp.Colors.Spaces
using System;
using System.ComponentModel;
using System.Numerics;
using ImageSharp.PixelFormats;
/// <summary>
/// Represents a Hsl (hue, saturation, lightness) color.
@ -70,14 +71,14 @@ namespace ImageSharp.Colors.Spaces
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
/// Allows the implicit conversion of an instance of <see cref="Rgba32"/> to a
/// <see cref="Hsl"/>.
/// </summary>
/// <param name="color">The instance of <see cref="Color"/> to convert.</param>
/// <param name="color">The instance of <see cref="Rgba32"/> to convert.</param>
/// <returns>
/// An instance of <see cref="Hsl"/>.
/// </returns>
public static implicit operator Hsl(Color color)
public static implicit operator Hsl(Rgba32 color)
{
float r = color.R / 255F;
float g = color.G / 255F;

7
src/ImageSharp/Colors/Spaces/Hsv.cs

@ -8,6 +8,7 @@ namespace ImageSharp.Colors.Spaces
using System;
using System.ComponentModel;
using System.Numerics;
using ImageSharp.PixelFormats;
/// <summary>
/// Represents a HSV (hue, saturation, value) color. Also known as HSB (hue, saturation, brightness).
@ -70,14 +71,14 @@ namespace ImageSharp.Colors.Spaces
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
/// Allows the implicit conversion of an instance of <see cref="Rgba32"/> to a
/// <see cref="Hsv"/>.
/// </summary>
/// <param name="color">The instance of <see cref="Color"/> to convert.</param>
/// <param name="color">The instance of <see cref="Rgba32"/> to convert.</param>
/// <returns>
/// An instance of <see cref="Hsv"/>.
/// </returns>
public static implicit operator Hsv(Color color)
public static implicit operator Hsv(Rgba32 color)
{
float r = color.R / 255F;
float g = color.G / 255F;

6
src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs

@ -11,9 +11,9 @@ namespace ImageSharp.Colors.Spaces
/// Defines a generalized method that a value type or class implements to create
/// a type-specific method for determining approximate equality of instances.
/// </summary>
/// <typeparam name="TColor">The type of objects to compare.</typeparam>
/// <typeparam name="TPixel">The type of objects to compare.</typeparam>
/// <typeparam name="TPrecision">The object specifying the type to specify precision with.</typeparam>
public interface IAlmostEquatable<in TColor, in TPrecision>
public interface IAlmostEquatable<in TPixel, in TPrecision>
where TPrecision : struct, IComparable<TPrecision>
{
/// <summary>
@ -25,6 +25,6 @@ namespace ImageSharp.Colors.Spaces
/// <returns>
/// true if the current object is equal to the other parameter; otherwise, false.
/// </returns>
bool AlmostEquals(TColor other, TPrecision precision);
bool AlmostEquals(TPixel other, TPrecision precision);
}
}

7
src/ImageSharp/Colors/Spaces/YCbCr.cs

@ -8,6 +8,7 @@ namespace ImageSharp.Colors.Spaces
using System;
using System.ComponentModel;
using System.Numerics;
using ImageSharp.PixelFormats;
/// <summary>
/// Represents an YCbCr (luminance, blue chroma, red chroma) color conforming to the full range standard used in digital imaging systems.
@ -72,16 +73,16 @@ namespace ImageSharp.Colors.Spaces
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
/// Allows the implicit conversion of an instance of <see cref="Rgba32"/> to a
/// <see cref="YCbCr"/>.
/// </summary>
/// <param name="color">
/// The instance of <see cref="Color"/> to convert.
/// The instance of <see cref="Rgba32"/> to convert.
/// </param>
/// <returns>
/// An instance of <see cref="YCbCr"/>.
/// </returns>
public static implicit operator YCbCr(Color color)
public static implicit operator YCbCr(Rgba32 color)
{
byte r = color.R;
byte g = color.G;

292
src/ImageSharp/Colors/Vector4BlendTransforms.cs

@ -1,292 +0,0 @@
// <copyright file="Vector4BlendTransforms.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.Numerics;
/// <summary>
/// Transform algorithms that match the equations defined in the W3C Compositing and Blending Level 1 specification.
/// <see href="https://www.w3.org/TR/compositing-1/"/>
/// </summary>
public class Vector4BlendTransforms
{
/// <summary>
/// The blending formula simply selects the source vector.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 Normal(Vector4 backdrop, Vector4 source)
{
return new Vector4(source.X, source.Y, source.Z, source.W);
}
/// <summary>
/// Blends two vectors by multiplication.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 Multiply(Vector4 backdrop, Vector4 source)
{
Vector4 multiply = backdrop * source;
multiply.W = backdrop.W;
return multiply;
}
/// <summary>
/// Multiplies the complements of the backdrop and source vector values, then complements the result.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 Screen(Vector4 backdrop, Vector4 source)
{
Vector4 subtract = backdrop + source - (backdrop * source);
subtract.W = backdrop.W;
return subtract;
}
/// <summary>
/// Multiplies or screens the colors, depending on the source vector value.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 HardLight(Vector4 backdrop, Vector4 source)
{
return new Vector4(BlendOverlay(source.X, backdrop.X), BlendOverlay(source.Y, backdrop.Y), BlendOverlay(source.Z, backdrop.Z), backdrop.W);
}
/// <summary>
/// Multiplies or screens the vectors, depending on the backdrop vector value.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 Overlay(Vector4 backdrop, Vector4 source)
{
return new Vector4(BlendOverlay(backdrop.X, source.X), BlendOverlay(backdrop.Y, source.Y), BlendOverlay(backdrop.Z, source.Z), backdrop.W);
}
/// <summary>
/// Selects the minimum of the backdrop and source vectors.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 Darken(Vector4 backdrop, Vector4 source)
{
Vector4 result = Vector4.Min(backdrop, source);
result.W = backdrop.W;
return result;
}
/// <summary>
/// Selects the max of the backdrop and source vector.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 Lighten(Vector4 backdrop, Vector4 source)
{
Vector4 result = Vector4.Max(backdrop, source);
result.W = backdrop.W;
return result;
}
/// <summary>
/// Selects the maximum or minimum of the vectors, depending on the source vector value.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 SoftLight(Vector4 backdrop, Vector4 source)
{
return new Vector4(BlendSoftLight(backdrop.X, source.X), BlendSoftLight(backdrop.Y, source.Y), BlendSoftLight(backdrop.Z, source.Z), backdrop.W);
}
/// <summary>
/// Increases the backdrop vector to reflect the source vector.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 Dodge(Vector4 backdrop, Vector4 source)
{
return new Vector4(BlendDodge(backdrop.X, source.X), BlendDodge(backdrop.Y, source.Y), BlendDodge(backdrop.Z, source.Z), backdrop.W);
}
/// <summary>
/// Decreases the backdrop vector to reflect the source vector.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 Burn(Vector4 backdrop, Vector4 source)
{
return new Vector4(BlendBurn(backdrop.X, source.X), BlendBurn(backdrop.Y, source.Y), BlendBurn(backdrop.Z, source.Z), backdrop.W);
}
/// <summary>
/// Subtracts the minimum of the two constituent vectors from the maximum vector.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 Difference(Vector4 backdrop, Vector4 source)
{
Vector4 result = Vector4.Abs(backdrop - source);
result.W = backdrop.W;
return result;
}
/// <summary>
/// Produces an effect similar to that of the <see cref="Difference"/> mode but lower in magnitude.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <returns>
/// The <see cref="Vector4"/>.
/// </returns>
public static Vector4 Exclusion(Vector4 backdrop, Vector4 source)
{
return new Vector4(BlendExclusion(backdrop.X, source.X), BlendExclusion(backdrop.Y, source.Y), BlendExclusion(backdrop.Z, source.Z), backdrop.W);
}
/// <summary>
/// Linearly interpolates from one vector to another based on the given weighting.
/// The two vectors are premultiplied before operating.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
/// <param name="source">The source vector.</param>
/// <param name="amount">
/// A value between 0 and 1 indicating the weight of the second source vector.
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
/// </param>
/// <returns>
/// The <see cref="Vector4"/>
/// </returns>
public static Vector4 PremultipliedLerp(Vector4 backdrop, Vector4 source, float amount)
{
amount = amount.Clamp(0, 1);
// Santize on zero alpha
if (MathF.Abs(backdrop.W) < Constants.Epsilon)
{
source.W *= amount;
return source;
}
if (MathF.Abs(source.W) < Constants.Epsilon)
{
return backdrop;
}
// Premultiply the source vector.
// Oddly premultiplying the background vector creates dark outlines when pixels
// Have low alpha values.
source = new Vector4(source.X, source.Y, source.Z, 1) * (source.W * amount);
// This should be implementing the following formula
// https://en.wikipedia.org/wiki/Alpha_compositing
// Vout = Vs + Vb (1 - Vsa)
// Aout = Vsa + Vsb (1 - Vsa)
Vector3 inverseW = new Vector3(1 - source.W);
Vector3 xyzB = new Vector3(backdrop.X, backdrop.Y, backdrop.Z);
Vector3 xyzS = new Vector3(source.X, source.Y, source.Z);
return new Vector4(xyzS + (xyzB * inverseW), source.W + (backdrop.W * (1 - source.W)));
}
/// <summary>
/// Multiplies or screens the backdrop component, depending on the component value.
/// </summary>
/// <param name="b">The backdrop component.</param>
/// <param name="s">The source component.</param>
/// <returns>
/// The <see cref="float"/>.
/// </returns>
private static float BlendOverlay(float b, float s)
{
return b <= .5F ? (2F * b * s) : (1F - (2F * (1F - b) * (1F - s)));
}
/// <summary>
/// Darkens or lightens the backdrop component, depending on the source component value.
/// </summary>
/// <param name="b">The backdrop component.</param>
/// <param name="s">The source component.</param>
/// <returns>
/// The <see cref="float"/>.
/// </returns>
private static float BlendSoftLight(float b, float s)
{
return s <= .5F ? ((2F * b * s) + (b * b * (1F - (2F * s)))) : (MathF.Sqrt(b) * ((2F * s) - 1F)) + (2F * b * (1F - s));
}
/// <summary>
/// Brightens the backdrop component to reflect the source component.
/// </summary>
/// <param name="b">The backdrop component.</param>
/// <param name="s">The source component.</param>
/// <returns>
/// The <see cref="float"/>.
/// </returns>
private static float BlendDodge(float b, float s)
{
return MathF.Abs(s - 1F) < Constants.Epsilon ? s : MathF.Min(b / (1F - s), 1F);
}
/// <summary>
/// Darkens the backdrop component to reflect the source component.
/// </summary>
/// <param name="b">The backdrop component.</param>
/// <param name="s">The source component.</param>
/// <returns>
/// The <see cref="float"/>.
/// </returns>
private static float BlendBurn(float b, float s)
{
return MathF.Abs(s) < Constants.Epsilon ? s : MathF.Max(1F - ((1F - b) / s), 0F);
}
/// <summary>
/// Darkens the backdrop component to reflect the source component.
/// </summary>
/// <param name="b">The backdrop component.</param>
/// <param name="s">The source component.</param>
/// <returns>
/// The <see cref="float"/>.
/// </returns>
private static float BlendExclusion(float b, float s)
{
return b + s - (2F * b * s);
}
}
}

8
src/ImageSharp/Common/Extensions/Vector4Extensions.cs

@ -5,14 +5,14 @@
namespace ImageSharp
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using ImageSharp.PixelFormats;
/// <summary>
/// Extension methods for the <see cref="Vector4"/> struct.
/// </summary>
public static class Vector4Extensions
internal static class Vector4Extensions
{
/// <summary>
/// Compresses a linear color signal to its sRGB equivalent.
@ -21,6 +21,7 @@ namespace ImageSharp
/// </summary>
/// <param name="linear">The <see cref="Vector4"/> whose signal to compress.</param>
/// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Compress(this Vector4 linear)
{
// TODO: Is there a faster way to do this?
@ -32,8 +33,9 @@ namespace ImageSharp
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/>
/// <see href="http://entropymine.com/imageworsener/srgbformula/"/>
/// </summary>
/// <param name="gamma">The <see cref="Color"/> whose signal to expand.</param>
/// <param name="gamma">The <see cref="Rgba32"/> whose signal to expand.</param>
/// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Expand(this Vector4 gamma)
{
// TODO: Is there a faster way to do this?

40
src/ImageSharp/Common/Helpers/DebugGuard.cs

@ -159,5 +159,45 @@ namespace ImageSharp
throw new ArgumentException(message, parameterName);
}
}
/// <summary>
/// Verifies, that the target span is of same size than the 'other' span.
/// </summary>
/// <typeparam name="T">The element type of the spans</typeparam>
/// <param name="target">The target span.</param>
/// <param name="other">The 'other' span to compare 'target' to.</param>
/// <param name="parameterName">The name of the parameter that is to be checked.</param>
/// <exception cref="ArgumentException">
/// <paramref name="target"/> is true
/// </exception>
[Conditional("DEBUG")]
public static void MustBeSameSized<T>(Span<T> target, Span<T> other, string parameterName)
where T : struct
{
if (target.Length != other.Length)
{
throw new ArgumentException("Span-s must be the same size!", parameterName);
}
}
/// <summary>
/// Verifies, that the `target` span has the length of 'minSpan', or longer.
/// </summary>
/// <typeparam name="T">The element type of the spans</typeparam>
/// <param name="target">The target span.</param>
/// <param name="minSpan">The 'minSpan' span to compare 'target' to.</param>
/// <param name="parameterName">The name of the parameter that is to be checked.</param>
/// <exception cref="ArgumentException">
/// <paramref name="target"/> is true
/// </exception>
[Conditional("DEBUG")]
public static void MustBeSizedAtLeast<T>(Span<T> target, Span<T> minSpan, string parameterName)
where T : struct
{
if (target.Length < minSpan.Length)
{
throw new ArgumentException($"Span-s must be at least of length {minSpan.Length}!", parameterName);
}
}
}
}

19
src/ImageSharp/Common/Helpers/Guard.cs

@ -230,5 +230,24 @@ namespace ImageSharp
throw new ArgumentException(message, parameterName);
}
}
/// <summary>
/// Verifies, that the `target` span has the length of 'minSpan', or longer.
/// </summary>
/// <typeparam name="T">The element type of the spans</typeparam>
/// <param name="target">The target span.</param>
/// <param name="minLength">The minimum length.</param>
/// <param name="parameterName">The name of the parameter that is to be checked.</param>
/// <exception cref="ArgumentException">
/// <paramref name="target"/> is true
/// </exception>
public static void MustBeSizedAtLeast<T>(Span<T> target, int minLength, string parameterName)
where T : struct
{
if (target.Length < minLength)
{
throw new ArgumentException($"Span-s must be at least of length {minLength}!", parameterName);
}
}
}
}

77
src/ImageSharp/Common/Helpers/ImageMaths.cs

@ -10,6 +10,8 @@ namespace ImageSharp
using System.Numerics;
using System.Runtime.CompilerServices;
using ImageSharp.PixelFormats;
/// <summary>
/// Provides common mathematical methods.
/// </summary>
@ -100,25 +102,6 @@ namespace ImageSharp
return 0F;
}
/// <summary>
/// Gets the result of a sine cardinal function for the given value.
/// </summary>
/// <param name="x">The value to calculate the result for.</param>
/// <returns>
/// The <see cref="float"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float SinC(float x)
{
if (MathF.Abs(x) > Constants.Epsilon)
{
x *= MathF.PI;
return Clean(MathF.Sin(x) / x);
}
return 1.0f;
}
/// <summary>
/// Returns the given degrees converted to radians.
/// </summary>
@ -175,22 +158,22 @@ namespace ImageSharp
/// Finds the bounding rectangle based on the first instance of any color component other
/// than the given one.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="bitmap">The <see cref="Image"/> to search within.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="bitmap">The <see cref="Image{TPixel}"/> to search within.</param>
/// <param name="componentValue">The color component value to remove.</param>
/// <param name="channel">The <see cref="RgbaComponent"/> channel to test against.</param>
/// <returns>
/// The <see cref="Rectangle"/>.
/// </returns>
public static Rectangle GetFilteredBoundingRectangle<TColor>(ImageBase<TColor> bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B)
where TColor : struct, IPixel<TColor>
public static Rectangle GetFilteredBoundingRectangle<TPixel>(ImageBase<TPixel> bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B)
where TPixel : struct, IPixel<TPixel>
{
int width = bitmap.Width;
int height = bitmap.Height;
Point topLeft = default(Point);
Point bottomRight = default(Point);
Func<PixelAccessor<TColor>, int, int, float, bool> delegateFunc;
Func<PixelAccessor<TPixel>, int, int, float, bool> delegateFunc;
// Determine which channel to check against
switch (channel)
@ -212,7 +195,7 @@ namespace ImageSharp
break;
}
Func<PixelAccessor<TColor>, int> getMinY = pixels =>
int GetMinY(PixelAccessor<TPixel> pixels)
{
for (int y = 0; y < height; y++)
{
@ -226,9 +209,9 @@ namespace ImageSharp
}
return 0;
};
}
Func<PixelAccessor<TColor>, int> getMaxY = pixels =>
int GetMaxY(PixelAccessor<TPixel> pixels)
{
for (int y = height - 1; y > -1; y--)
{
@ -242,9 +225,9 @@ namespace ImageSharp
}
return height;
};
}
Func<PixelAccessor<TColor>, int> getMinX = pixels =>
int GetMinX(PixelAccessor<TPixel> pixels)
{
for (int x = 0; x < width; x++)
{
@ -258,9 +241,9 @@ namespace ImageSharp
}
return 0;
};
}
Func<PixelAccessor<TColor>, int> getMaxX = pixels =>
int GetMaxX(PixelAccessor<TPixel> pixels)
{
for (int x = width - 1; x > -1; x--)
{
@ -274,35 +257,17 @@ namespace ImageSharp
}
return height;
};
using (PixelAccessor<TColor> bitmapPixels = bitmap.Lock())
{
topLeft.Y = getMinY(bitmapPixels);
topLeft.X = getMinX(bitmapPixels);
bottomRight.Y = (getMaxY(bitmapPixels) + 1).Clamp(0, height);
bottomRight.X = (getMaxX(bitmapPixels) + 1).Clamp(0, width);
}
return GetBoundingRectangle(topLeft, bottomRight);
}
/// <summary>
/// Ensures that any passed double is correctly rounded to zero
/// </summary>
/// <param name="x">The value to clean.</param>
/// <returns>
/// The <see cref="float"/>
/// </returns>.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float Clean(float x)
{
if (MathF.Abs(x) < Constants.Epsilon)
using (PixelAccessor<TPixel> bitmapPixels = bitmap.Lock())
{
return 0F;
topLeft.Y = GetMinY(bitmapPixels);
topLeft.X = GetMinX(bitmapPixels);
bottomRight.Y = (GetMaxY(bitmapPixels) + 1).Clamp(0, height);
bottomRight.X = (GetMaxX(bitmapPixels) + 1).Clamp(0, width);
}
return x;
return GetBoundingRectangle(topLeft, bottomRight);
}
}
}
}

38
src/ImageSharp/Common/Helpers/MathF.cs

@ -126,6 +126,26 @@ namespace ImageSharp
return (float)Math.Sin(f);
}
/// <summary>
/// Returns the result of a normalized sine cardinal function for the given value.
/// SinC(x) = sin(pi*x)/(pi*x).
/// </summary>
/// <param name="f">A single-precision floating-point number to calculate the result for.</param>
/// <returns>
/// The sine cardinal of <paramref name="f" />.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float SinC(float f)
{
if (Abs(f) > Constants.Epsilon)
{
f *= PI;
return Clean(Sin(f) / f);
}
return 1F;
}
/// <summary>Returns the square root of a specified number.</summary>
/// <param name="f">The number whose square root is to be found. </param>
/// <returns>
@ -140,5 +160,23 @@ namespace ImageSharp
{
return (float)Math.Sqrt(f);
}
/// <summary>
/// Ensures that any passed float is correctly rounded to zero
/// </summary>
/// <param name="x">The value to clean.</param>
/// <returns>
/// The <see cref="float"/>
/// </returns>.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float Clean(float x)
{
if (Abs(x) < Constants.Epsilon)
{
return 0F;
}
return x;
}
}
}

129
src/ImageSharp/Common/Memory/BufferSpan.cs

@ -1,129 +0,0 @@
// <copyright file="BufferSpan.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 System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <summary>
/// Utility methods for <see cref="BufferSpan{T}"/>
/// </summary>
internal static class BufferSpan
{
/// <summary>
/// It's worth to use Marshal.Copy() or Buffer.BlockCopy() over this size.
/// </summary>
private const int ByteCountThreshold = 1024;
/// <summary>
/// Copy 'count' number of elements of the same type from 'source' to 'dest'
/// </summary>
/// <typeparam name="T">The element type.</typeparam>
/// <param name="source">The input <see cref="BufferSpan{T}"/></param>
/// <param name="destination">The destination <see cref="BufferSpan{T}"/>.</param>
/// <param name="count">The number of elements to copy</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Copy<T>(BufferSpan<T> source, BufferSpan<T> destination, int count)
where T : struct
{
CopyImpl(source, destination, count);
}
/// <summary>
/// Copy 'countInSource' elements of <typeparamref name="T"/> from 'source' into the raw byte buffer 'destination'.
/// </summary>
/// <typeparam name="T">The element type.</typeparam>
/// <param name="source">The source buffer of <typeparamref name="T"/> elements to copy from.</param>
/// <param name="destination">The destination buffer.</param>
/// <param name="countInSource">The number of elements to copy from 'source'</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Copy<T>(BufferSpan<T> source, BufferSpan<byte> destination, int countInSource)
where T : struct
{
CopyImpl(source, destination, countInSource);
}
/// <summary>
/// Copy 'countInDest' number of <typeparamref name="T"/> elements into 'dest' from a raw byte buffer defined by 'source'.
/// </summary>
/// <typeparam name="T">The element type.</typeparam>
/// <param name="source">The raw source buffer to copy from"/></param>
/// <param name="destination">The destination buffer"/></param>
/// <param name="countInDest">The number of <typeparamref name="T"/> elements to copy.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Copy<T>(BufferSpan<byte> source, BufferSpan<T> destination, int countInDest)
where T : struct
{
int byteCount = SizeOf<T>(countInDest);
if (byteCount > (int)ByteCountThreshold)
{
Marshal.Copy(source.Array, source.Start, destination.PointerAtOffset, byteCount);
}
else
{
Unsafe.CopyBlock((void*)destination.PointerAtOffset, (void*)source.PointerAtOffset, (uint)byteCount);
}
}
/// <summary>
/// Gets the size of `count` elements in bytes.
/// </summary>
/// <typeparam name="T">The element type.</typeparam>
/// <param name="count">The count of the elements</param>
/// <returns>The size in bytes as int</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SizeOf<T>(int count)
where T : struct => Unsafe.SizeOf<T>() * count;
/// <summary>
/// Gets the size of `count` elements in bytes as UInt32
/// </summary>
/// <typeparam name="T">The element type.</typeparam>
/// <param name="count">The count of the elements</param>
/// <returns>The size in bytes as UInt32</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint USizeOf<T>(int count)
where T : struct
=> (uint)SizeOf<T>(count);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe void CopyImpl<T, TDest>(BufferSpan<T> source, BufferSpan<TDest> destination, int count)
where T : struct
where TDest : struct
{
int byteCount = SizeOf<T>(count);
if (byteCount > ByteCountThreshold)
{
if (Unsafe.SizeOf<T>() == sizeof(long))
{
Marshal.Copy(Unsafe.As<long[]>(source.Array), source.Start, destination.PointerAtOffset, count);
return;
}
else if (Unsafe.SizeOf<T>() == sizeof(int))
{
Marshal.Copy(Unsafe.As<int[]>(source.Array), source.Start, destination.PointerAtOffset, count);
return;
}
else if (Unsafe.SizeOf<T>() == sizeof(short))
{
Marshal.Copy(Unsafe.As<short[]>(source.Array), source.Start, destination.PointerAtOffset, count);
return;
}
else if (Unsafe.SizeOf<T>() == sizeof(byte))
{
Marshal.Copy(Unsafe.As<byte[]>(source.Array), source.Start, destination.PointerAtOffset, count);
return;
}
}
Unsafe.CopyBlock((void*)destination.PointerAtOffset, (void*)source.PointerAtOffset, (uint)byteCount);
}
}
}

237
src/ImageSharp/Common/Memory/BufferSpan{T}.cs

@ -1,237 +0,0 @@
// <copyright file="BufferSpan{T}.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.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <summary>
/// Represents a contiguous region of a pinned managed array.
/// The array is usually owned by a <see cref="PinnedBuffer{T}"/> instance.
/// </summary>
/// <remarks>
/// <see cref="BufferSpan{T}"/> is very similar to corefx System.Span&lt;T&gt;, and we try to maintain a compatible API.
/// There are several differences though:
/// - It's not possible to use it with stack objects or pointers to unmanaged memory, only with managed arrays.
/// - It's possible to retrieve a reference to the array (<see cref="Array"/>) so we can pass it to API-s like <see cref="Marshal.Copy(byte[], int, IntPtr, int)"/>
/// - It's possible to retrieve the pinned pointer. This enables optimized (unchecked) unsafe operations.
/// - There is no bounds checking for performance reasons, only in debug mode. This makes <see cref="BufferSpan{T}"/> an unsafe type!
/// </remarks>
/// <typeparam name="T">The type of elements of the array</typeparam>
internal unsafe struct BufferSpan<T>
where T : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="BufferSpan{T}"/> struct from a pinned array and an start.
/// </summary>
/// <param name="array">The pinned array</param>
/// <param name="pointerToArray">Pointer to the beginning of the array</param>
/// <param name="start">The index at which to begin the span.</param>
/// <param name="length">The length</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public BufferSpan(T[] array, void* pointerToArray, int start, int length)
{
GuardArrayAndPointer(array, pointerToArray);
DebugGuard.MustBeLessThanOrEqualTo(start, array.Length, nameof(start));
DebugGuard.MustBeLessThanOrEqualTo(length, array.Length - start, nameof(length));
this.Array = array;
this.Length = length;
this.Start = start;
this.PointerAtOffset = (IntPtr)pointerToArray + (Unsafe.SizeOf<T>() * start);
}
/// <summary>
/// Initializes a new instance of the <see cref="BufferSpan{T}"/> struct from a pinned array and an start.
/// </summary>
/// <param name="array">The pinned array</param>
/// <param name="pointerToArray">Pointer to the beginning of the array</param>
/// <param name="start">The index at which to begin the span.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public BufferSpan(T[] array, void* pointerToArray, int start)
{
GuardArrayAndPointer(array, pointerToArray);
DebugGuard.MustBeLessThanOrEqualTo(start, array.Length, nameof(start));
this.Array = array;
this.Length = array.Length - start;
this.Start = start;
this.PointerAtOffset = (IntPtr)pointerToArray + (Unsafe.SizeOf<T>() * start);
}
/// <summary>
/// Initializes a new instance of the <see cref="BufferSpan{T}"/> struct from a pinned array.
/// </summary>
/// <param name="array">The pinned array</param>
/// <param name="pointerToArray">Pointer to the start of 'array'</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public BufferSpan(T[] array, void* pointerToArray)
{
GuardArrayAndPointer(array, pointerToArray);
this.Array = array;
this.Start = 0;
this.Length = array.Length;
this.PointerAtOffset = (IntPtr)pointerToArray;
}
/// <summary>
/// Gets the backing array
/// </summary>
public T[] Array { get; private set; }
/// <summary>
/// Gets the length of the <see cref="BufferSpan{T}"/>
/// </summary>
public int Length { get; private set; }
/// <summary>
/// Gets the start inside <see cref="Array"/>
/// </summary>
public int Start { get; private set; }
/// <summary>
/// Gets the start inside <see cref="Array"/> in bytes.
/// </summary>
public int ByteOffset => this.Start * Unsafe.SizeOf<T>();
/// <summary>
/// Gets the pointer to the offseted array position
/// </summary>
public IntPtr PointerAtOffset { get; private set; }
/// <summary>
/// Returns a reference to specified element of the span.
/// </summary>
/// <param name="index">The index</param>
/// <returns>The reference to the specified element</returns>
public ref T this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
DebugGuard.MustBeLessThan(index, this.Length, nameof(index));
byte* ptr = (byte*)this.PointerAtOffset + BufferSpan.SizeOf<T>(index);
return ref Unsafe.AsRef<T>(ptr);
}
}
/// <summary>
/// Convertes <see cref="BufferSpan{T}"/> instance to a raw 'void*' pointer
/// </summary>
/// <param name="bufferSpan">The <see cref="BufferSpan{T}"/> to convert</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator void*(BufferSpan<T> bufferSpan)
{
return (void*)bufferSpan.PointerAtOffset;
}
/// <summary>
/// Converts <see cref="BufferSpan{T}"/> instance to a raw 'byte*' pointer
/// </summary>
/// <param name="bufferSpan">The <see cref="BufferSpan{T}"/> to convert</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator byte*(BufferSpan<T> bufferSpan)
{
return (byte*)bufferSpan.PointerAtOffset;
}
/// <summary>
/// Converts generic <see cref="BufferSpan{T}"/> to a <see cref="BufferSpan{T}"/> of bytes
/// setting it's <see cref="Start"/> and <see cref="PointerAtOffset"/> to correct values.
/// </summary>
/// <param name="source">The <see cref="BufferSpan{T}"/> to convert</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator BufferSpan<byte>(BufferSpan<T> source)
{
BufferSpan<byte> result = default(BufferSpan<byte>);
result.Array = Unsafe.As<byte[]>(source.Array);
result.Start = source.Start * Unsafe.SizeOf<T>();
result.PointerAtOffset = source.PointerAtOffset;
return result;
}
/// <summary>
/// Forms a slice out of the given BufferSpan, beginning at 'start'.
/// </summary>
/// <param name="start">TThe index at which to begin this slice.</param>
/// <returns>The offseted (sliced) BufferSpan</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public BufferSpan<T> Slice(int start)
{
DebugGuard.MustBeLessThan(start, this.Length, nameof(start));
BufferSpan<T> result = default(BufferSpan<T>);
result.Array = this.Array;
result.Start = this.Start + start;
result.PointerAtOffset = this.PointerAtOffset + (Unsafe.SizeOf<T>() * start);
result.Length = this.Length - start;
return result;
}
/// <summary>
/// Forms a slice out of the given BufferSpan, beginning at 'start'.
/// </summary>
/// <param name="start">The index at which to begin this slice.</param>
/// <param name="length">The desired length for the slice (exclusive).</param>
/// <returns>The sliced BufferSpan</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public BufferSpan<T> Slice(int start, int length)
{
DebugGuard.MustBeLessThanOrEqualTo(start, this.Length, nameof(start));
DebugGuard.MustBeLessThanOrEqualTo(length, this.Length - start, nameof(length));
BufferSpan<T> result = default(BufferSpan<T>);
result.Array = this.Array;
result.Start = this.Start + start;
result.PointerAtOffset = this.PointerAtOffset + (Unsafe.SizeOf<T>() * start);
result.Length = length;
return result;
}
/// <summary>
/// Clears `count` elements from the beginning of the span.
/// </summary>
/// <param name="count">The number of elements to clear</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear(int count)
{
DebugGuard.MustBeLessThanOrEqualTo(count, this.Length, nameof(count));
if (count < 256)
{
Unsafe.InitBlock((void*)this.PointerAtOffset, 0, BufferSpan.USizeOf<T>(count));
}
else
{
System.Array.Clear(this.Array, this.Start, count);
}
}
/// <summary>
/// Clears the the span
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear()
{
this.Clear(this.Length);
}
[Conditional("DEBUG")]
private static void GuardArrayAndPointer(T[] array, void* pointerToArray)
{
DebugGuard.NotNull(array, nameof(array));
DebugGuard.IsFalse(
pointerToArray == (void*)0,
nameof(pointerToArray),
"pointerToArray should not be null pointer!");
}
}
}

2
src/ImageSharp/Dithering/ErrorDiffusion/Atkinson.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering
{
using ImageSharp.Memory;
/// <summary>
/// Applies error diffusion based dithering using the Atkinson image dithering algorithm.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>

2
src/ImageSharp/Dithering/ErrorDiffusion/Burks.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering
{
using ImageSharp.Memory;
/// <summary>
/// Applies error diffusion based dithering using the Burks image dithering algorithm.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>

24
src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs

@ -8,6 +8,9 @@ namespace ImageSharp.Dithering
using System.Numerics;
using System.Runtime.CompilerServices;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
/// <summary>
/// The base class for performing error diffusion based dithering.
/// </summary>
@ -68,11 +71,22 @@ namespace ImageSharp.Dithering
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dither<TColor>(PixelAccessor<TColor> pixels, TColor source, TColor transformed, int x, int y, int width, int height)
where TColor : struct, IPixel<TColor>
public void Dither<TPixel>(PixelAccessor<TPixel> pixels, TPixel source, TPixel transformed, int x, int y, int width, int height)
where TPixel : struct, IPixel<TPixel>
{
this.Dither(pixels, source, transformed, x, y, width, height, true);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dither<TPixel>(PixelAccessor<TPixel> pixels, TPixel source, TPixel transformed, int x, int y, int width, int height, bool replacePixel)
where TPixel : struct, IPixel<TPixel>
{
// Assign the transformed pixel to the array.
pixels[x, y] = transformed;
if (replacePixel)
{
// Assign the transformed pixel to the array.
pixels[x, y] = transformed;
}
// Calculate the error
Vector4 error = source.ToVector4() - transformed.ToVector4();
@ -102,7 +116,7 @@ namespace ImageSharp.Dithering
Vector4 result = ((error * coefficientVector) / this.divisorVector) + offsetColor;
result.W = offsetColor.W;
TColor packed = default(TColor);
TPixel packed = default(TPixel);
packed.PackFromVector4(result);
pixels[matrixX, matrixY] = packed;
}

2
src/ImageSharp/Dithering/ErrorDiffusion/FloydSteinberg.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering
{
using ImageSharp.Memory;
/// <summary>
/// Applies error diffusion based dithering using the Floyd–Steinberg image dithering algorithm.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>

26
src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs

@ -5,7 +5,7 @@
namespace ImageSharp.Dithering
{
using System;
using ImageSharp.PixelFormats;
/// <summary>
/// Encapsulates properties and methods required to perfom diffused error dithering on an image.
@ -22,8 +22,26 @@ namespace ImageSharp.Dithering
/// <param name="y">The row index.</param>
/// <param name="width">The image width.</param>
/// <param name="height">The image height.</param>
/// <typeparam name="TColor">The pixel format.</typeparam>
void Dither<TColor>(PixelAccessor<TColor> pixels, TColor source, TColor transformed, int x, int y, int width, int height)
where TColor : struct, IPixel<TColor>;
/// <typeparam name="TPixel">The pixel format.</typeparam>
void Dither<TPixel>(PixelAccessor<TPixel> pixels, TPixel source, TPixel transformed, int x, int y, int width, int height)
where TPixel : struct, IPixel<TPixel>;
/// <summary>
/// Transforms the image applying the dither matrix. This method alters the input pixels array
/// </summary>
/// <param name="pixels">The pixel accessor </param>
/// <param name="source">The source pixel</param>
/// <param name="transformed">The transformed pixel</param>
/// <param name="x">The column index.</param>
/// <param name="y">The row index.</param>
/// <param name="width">The image width.</param>
/// <param name="height">The image height.</param>
/// <param name="replacePixel">
/// Whether to replace the pixel at the given coordinates with the transformed value.
/// Generally this would be true for standard two-color dithering but when used in conjunction with color quantization this should be false.
/// </param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
void Dither<TPixel>(PixelAccessor<TPixel> pixels, TPixel source, TPixel transformed, int x, int y, int width, int height, bool replacePixel)
where TPixel : struct, IPixel<TPixel>;
}
}

2
src/ImageSharp/Dithering/ErrorDiffusion/JarvisJudiceNinke.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering
{
using ImageSharp.Memory;
/// <summary>
/// Applies error diffusion based dithering using the JarvisJudiceNinke image dithering algorithm.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>

2
src/ImageSharp/Dithering/ErrorDiffusion/Sierra2.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering
{
using ImageSharp.Memory;
/// <summary>
/// Applies error diffusion based dithering using the Sierra2 image dithering algorithm.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>

2
src/ImageSharp/Dithering/ErrorDiffusion/Sierra3.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering
{
using ImageSharp.Memory;
/// <summary>
/// Applies error diffusion based dithering using the Sierra3 image dithering algorithm.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>

2
src/ImageSharp/Dithering/ErrorDiffusion/SierraLite.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering
{
using ImageSharp.Memory;
/// <summary>
/// Applies error diffusion based dithering using the SierraLite image dithering algorithm.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>

2
src/ImageSharp/Dithering/ErrorDiffusion/Stucki.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering
{
using ImageSharp.Memory;
/// <summary>
/// Applies error diffusion based dithering using the Stucki image dithering algorithm.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>

2
src/ImageSharp/Dithering/Ordered/Bayer.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering.Ordered
{
using ImageSharp.Memory;
/// <summary>
/// Applies error diffusion based dithering using the 4x4 Bayer dithering matrix.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>

8
src/ImageSharp/Dithering/Ordered/IOrderedDither.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering
{
using ImageSharp.PixelFormats;
/// <summary>
/// Encapsulates properties and methods required to perfom ordered dithering on an image.
/// </summary>
@ -23,8 +25,8 @@ namespace ImageSharp.Dithering
/// <param name="y">The row index.</param>
/// <param name="width">The image width.</param>
/// <param name="height">The image height.</param>
/// <typeparam name="TColor">The pixel format.</typeparam>
void Dither<TColor>(PixelAccessor<TColor> pixels, TColor source, TColor upper, TColor lower, byte[] bytes, int index, int x, int y, int width, int height)
where TColor : struct, IPixel<TColor>;
/// <typeparam name="TPixel">The pixel format.</typeparam>
void Dither<TPixel>(PixelAccessor<TPixel> pixels, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y, int width, int height)
where TPixel : struct, IPixel<TPixel>;
}
}

2
src/ImageSharp/Dithering/Ordered/Ordered.cs

@ -5,6 +5,8 @@
namespace ImageSharp.Dithering.Ordered
{
using ImageSharp.Memory;
/// <summary>
/// Applies error diffusion based dithering using the 4x4 ordered dithering matrix.
/// <see href="https://en.wikipedia.org/wiki/Ordered_dithering"/>

7
src/ImageSharp/Dithering/Ordered/OrderedDither4x4.cs

@ -5,6 +5,9 @@
namespace ImageSharp.Dithering.Ordered
{
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
/// <summary>
/// The base class for performing ordered ditheroing using a 4x4 matrix.
/// </summary>
@ -25,8 +28,8 @@ namespace ImageSharp.Dithering.Ordered
}
/// <inheritdoc />
public void Dither<TColor>(PixelAccessor<TColor> pixels, TColor source, TColor upper, TColor lower, byte[] bytes, int index, int x, int y, int width, int height)
where TColor : struct, IPixel<TColor>
public void Dither<TPixel>(PixelAccessor<TPixel> pixels, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y, int width, int height)
where TPixel : struct, IPixel<TPixel>
{
// TODO: This doesn't really cut it for me.
// I'd rather be using float but we need to add some sort of movalization vector methods to all IPixel implementations

8
src/ImageSharp/Formats/Bmp/BmpDecoder.cs

@ -8,6 +8,8 @@ namespace ImageSharp.Formats
using System;
using System.IO;
using ImageSharp.PixelFormats;
/// <summary>
/// Image decoder for generating an image out of a Windows bitmap stream.
/// </summary>
@ -26,13 +28,13 @@ namespace ImageSharp.Formats
public class BmpDecoder : IImageDecoder
{
/// <inheritdoc/>
public Image<TColor> Decode<TColor>(Configuration configuration, Stream stream, IDecoderOptions options)
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, IDecoderOptions options)
where TColor : struct, IPixel<TColor>
where TPixel : struct, IPixel<TPixel>
{
Guard.NotNull(stream, "stream");
return new BmpDecoderCore(configuration).Decode<TColor>(stream);
return new BmpDecoderCore(configuration).Decode<TPixel>(stream);
}
}
}

58
src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

@ -7,6 +7,8 @@ namespace ImageSharp.Formats
using System;
using System.IO;
using ImageSharp.PixelFormats;
/// <summary>
/// Performs the bmp decoding operation.
/// </summary>
@ -58,15 +60,15 @@ namespace ImageSharp.Formats
/// Decodes the image from the specified this._stream and sets
/// the data to image.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="stream">The stream, where the image should be
/// decoded from. Cannot be null (Nothing in Visual Basic).</param>
/// <exception cref="System.ArgumentNullException">
/// <para><paramref name="stream"/> is null.</para>
/// </exception>
/// <returns>The decoded image.</returns>
public Image<TColor> Decode<TColor>(Stream stream)
where TColor : struct, IPixel<TColor>
public Image<TPixel> Decode<TPixel>(Stream stream)
where TPixel : struct, IPixel<TPixel>
{
this.currentStream = stream;
@ -118,15 +120,15 @@ namespace ImageSharp.Formats
this.currentStream.Read(palette, 0, colorMapSize);
}
if (this.infoHeader.Width > Image<TColor>.MaxWidth || this.infoHeader.Height > Image<TColor>.MaxHeight)
if (this.infoHeader.Width > Image<TPixel>.MaxWidth || this.infoHeader.Height > Image<TPixel>.MaxHeight)
{
throw new ArgumentOutOfRangeException(
$"The input bitmap '{this.infoHeader.Width}x{this.infoHeader.Height}' is "
+ $"bigger then the max allowed size '{Image<TColor>.MaxWidth}x{Image<TColor>.MaxHeight}'");
+ $"bigger then the max allowed size '{Image<TPixel>.MaxWidth}x{Image<TPixel>.MaxHeight}'");
}
Image<TColor> image = Image.Create<TColor>(this.infoHeader.Width, this.infoHeader.Height, this.configuration);
using (PixelAccessor<TColor> pixels = image.Lock())
Image<TPixel> image = new Image<TPixel>(this.configuration, this.infoHeader.Width, this.infoHeader.Height);
using (PixelAccessor<TPixel> pixels = image.Lock())
{
switch (this.infoHeader.Compression)
{
@ -213,15 +215,15 @@ namespace ImageSharp.Formats
/// <summary>
/// Reads the color palette from the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="pixels">The <see cref="PixelAccessor{TColor}"/> to assign the palette to.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> to assign the palette to.</param>
/// <param name="colors">The <see cref="T:byte[]"/> containing the colors.</param>
/// <param name="width">The width of the bitmap.</param>
/// <param name="height">The height of the bitmap.</param>
/// <param name="bits">The number of bits per pixel.</param>
/// <param name="inverted">Whether the bitmap is inverted.</param>
private void ReadRgbPalette<TColor>(PixelAccessor<TColor> pixels, byte[] colors, int width, int height, int bits, bool inverted)
where TColor : struct, IPixel<TColor>
private void ReadRgbPalette<TPixel>(PixelAccessor<TPixel> pixels, byte[] colors, int width, int height, int bits, bool inverted)
where TPixel : struct, IPixel<TPixel>
{
// Pixels per byte (bits per pixel)
int ppb = 8 / bits;
@ -239,7 +241,7 @@ namespace ImageSharp.Formats
}
byte[] row = new byte[arrayWidth + padding];
TColor color = default(TColor);
TPixel color = default(TPixel);
for (int y = 0; y < height; y++)
{
@ -270,21 +272,21 @@ namespace ImageSharp.Formats
/// <summary>
/// Reads the 16 bit color palette from the stream
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="pixels">The <see cref="PixelAccessor{TColor}"/> to assign the palette to.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> to assign the palette to.</param>
/// <param name="width">The width of the bitmap.</param>
/// <param name="height">The height of the bitmap.</param>
/// <param name="inverted">Whether the bitmap is inverted.</param>
private void ReadRgb16<TColor>(PixelAccessor<TColor> pixels, int width, int height, bool inverted)
where TColor : struct, IPixel<TColor>
private void ReadRgb16<TPixel>(PixelAccessor<TPixel> pixels, int width, int height, bool inverted)
where TPixel : struct, IPixel<TPixel>
{
// We divide here as we will store the colors in our floating point format.
const int ScaleR = 8; // 256/32
const int ScaleG = 4; // 256/64
const int ComponentCount = 2;
TColor color = default(TColor);
using (PixelArea<TColor> row = new PixelArea<TColor>(width, ComponentOrder.Xyz))
TPixel color = default(TPixel);
using (PixelArea<TPixel> row = new PixelArea<TPixel>(width, ComponentOrder.Xyz))
{
for (int y = 0; y < height; y++)
{
@ -312,16 +314,16 @@ namespace ImageSharp.Formats
/// <summary>
/// Reads the 24 bit color palette from the stream
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="pixels">The <see cref="PixelAccessor{TColor}"/> to assign the palette to.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> to assign the palette to.</param>
/// <param name="width">The width of the bitmap.</param>
/// <param name="height">The height of the bitmap.</param>
/// <param name="inverted">Whether the bitmap is inverted.</param>
private void ReadRgb24<TColor>(PixelAccessor<TColor> pixels, int width, int height, bool inverted)
where TColor : struct, IPixel<TColor>
private void ReadRgb24<TPixel>(PixelAccessor<TPixel> pixels, int width, int height, bool inverted)
where TPixel : struct, IPixel<TPixel>
{
int padding = CalculatePadding(width, 3);
using (PixelArea<TColor> row = new PixelArea<TColor>(width, ComponentOrder.Zyx, padding))
using (PixelArea<TPixel> row = new PixelArea<TPixel>(width, ComponentOrder.Zyx, padding))
{
for (int y = 0; y < height; y++)
{
@ -336,16 +338,16 @@ namespace ImageSharp.Formats
/// <summary>
/// Reads the 32 bit color palette from the stream
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="pixels">The <see cref="PixelAccessor{TColor}"/> to assign the palette to.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> to assign the palette to.</param>
/// <param name="width">The width of the bitmap.</param>
/// <param name="height">The height of the bitmap.</param>
/// <param name="inverted">Whether the bitmap is inverted.</param>
private void ReadRgb32<TColor>(PixelAccessor<TColor> pixels, int width, int height, bool inverted)
where TColor : struct, IPixel<TColor>
private void ReadRgb32<TPixel>(PixelAccessor<TPixel> pixels, int width, int height, bool inverted)
where TPixel : struct, IPixel<TPixel>
{
int padding = CalculatePadding(width, 4);
using (PixelArea<TColor> row = new PixelArea<TColor>(width, ComponentOrder.Zyxw, padding))
using (PixelArea<TPixel> row = new PixelArea<TPixel>(width, ComponentOrder.Zyxw, padding))
{
for (int y = 0; y < height; y++)
{

16
src/ImageSharp/Formats/Bmp/BmpEncoder.cs

@ -8,6 +8,8 @@ namespace ImageSharp.Formats
using System;
using System.IO;
using ImageSharp.PixelFormats;
/// <summary>
/// Image encoder for writing an image to a stream as a Windows bitmap.
/// </summary>
@ -15,8 +17,8 @@ namespace ImageSharp.Formats
public class BmpEncoder : IImageEncoder
{
/// <inheritdoc/>
public void Encode<TColor>(Image<TColor> image, Stream stream, IEncoderOptions options)
where TColor : struct, IPixel<TColor>
public void Encode<TPixel>(Image<TPixel> image, Stream stream, IEncoderOptions options)
where TPixel : struct, IPixel<TPixel>
{
IBmpEncoderOptions bmpOptions = BmpEncoderOptions.Create(options);
@ -24,14 +26,14 @@ namespace ImageSharp.Formats
}
/// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TColor}"/>.
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TColor}"/> to encode from.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
/// <param name="options">The options for the encoder.</param>
public void Encode<TColor>(Image<TColor> image, Stream stream, IBmpEncoderOptions options)
where TColor : struct, IPixel<TColor>
public void Encode<TPixel>(Image<TPixel> image, Stream stream, IBmpEncoderOptions options)
where TPixel : struct, IPixel<TPixel>
{
BmpEncoderCore encoder = new BmpEncoderCore(options);
encoder.Encode(image, stream);

42
src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

@ -8,6 +8,8 @@ namespace ImageSharp.Formats
using System;
using System.IO;
using ImageSharp.PixelFormats;
using IO;
/// <summary>
@ -35,13 +37,13 @@ namespace ImageSharp.Formats
}
/// <summary>
/// Encodes the image to the specified stream from the <see cref="ImageBase{TColor}"/>.
/// Encodes the image to the specified stream from the <see cref="ImageBase{TPixel}"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TColor}"/> to encode from.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public void Encode<TColor>(ImageBase<TColor> image, Stream stream)
where TColor : struct, IPixel<TColor>
public void Encode<TPixel>(ImageBase<TPixel> image, Stream stream)
where TPixel : struct, IPixel<TPixel>
{
Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream));
@ -124,15 +126,15 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the pixel data to the binary stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param>
/// <param name="image">
/// The <see cref="ImageBase{TColor}"/> containing pixel data.
/// The <see cref="ImageBase{TPixel}"/> containing pixel data.
/// </param>
private void WriteImage<TColor>(EndianBinaryWriter writer, ImageBase<TColor> image)
where TColor : struct, IPixel<TColor>
private void WriteImage<TPixel>(EndianBinaryWriter writer, ImageBase<TPixel> image)
where TPixel : struct, IPixel<TPixel>
{
using (PixelAccessor<TColor> pixels = image.Lock())
using (PixelAccessor<TPixel> pixels = image.Lock())
{
switch (this.options.BitsPerPixel)
{
@ -150,13 +152,13 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the 32bit color palette to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param>
/// <param name="pixels">The <see cref="PixelAccessor{TColor}"/> containing pixel data.</param>
private void Write32Bit<TColor>(EndianBinaryWriter writer, PixelAccessor<TColor> pixels)
where TColor : struct, IPixel<TColor>
/// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> containing pixel data.</param>
private void Write32Bit<TPixel>(EndianBinaryWriter writer, PixelAccessor<TPixel> pixels)
where TPixel : struct, IPixel<TPixel>
{
using (PixelArea<TColor> row = new PixelArea<TColor>(pixels.Width, ComponentOrder.Zyxw, this.padding))
using (PixelArea<TPixel> row = new PixelArea<TPixel>(pixels.Width, ComponentOrder.Zyxw, this.padding))
{
for (int y = pixels.Height - 1; y >= 0; y--)
{
@ -169,13 +171,13 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the 24bit color palette to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="writer">The <see cref="EndianBinaryWriter"/> containing the stream to write to.</param>
/// <param name="pixels">The <see cref="PixelAccessor{TColor}"/> containing pixel data.</param>
private void Write24Bit<TColor>(EndianBinaryWriter writer, PixelAccessor<TColor> pixels)
where TColor : struct, IPixel<TColor>
/// <param name="pixels">The <see cref="PixelAccessor{TPixel}"/> containing pixel data.</param>
private void Write24Bit<TPixel>(EndianBinaryWriter writer, PixelAccessor<TPixel> pixels)
where TPixel : struct, IPixel<TPixel>
{
using (PixelArea<TColor> row = new PixelArea<TColor>(pixels.Width, ComponentOrder.Zyx, this.padding))
using (PixelArea<TPixel> row = new PixelArea<TPixel>(pixels.Width, ComponentOrder.Zyx, this.padding))
{
for (int y = pixels.Height - 1; y >= 0; y--)
{

12
src/ImageSharp/Formats/Bmp/ImageExtensions.cs

@ -10,23 +10,25 @@ namespace ImageSharp
using Formats;
using ImageSharp.PixelFormats;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Saves the image to the given stream with the bmp format.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="stream">The stream to save the image to.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
/// <returns>
/// The <see cref="Image{TColoR}"/>.
/// The <see cref="Image{TPixel}"/>.
/// </returns>
public static Image<TColor> SaveAsBmp<TColor>(this Image<TColor> source, Stream stream)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> SaveAsBmp<TPixel>(this Image<TPixel> source, Stream stream)
where TPixel : struct, IPixel<TPixel>
=> source.Save(stream, new BmpEncoder());
}
}

18
src/ImageSharp/Formats/Gif/GifDecoder.cs

@ -8,33 +8,35 @@ namespace ImageSharp.Formats
using System;
using System.IO;
using ImageSharp.PixelFormats;
/// <summary>
/// Decoder for generating an image out of a gif encoded stream.
/// </summary>
public class GifDecoder : IImageDecoder
{
/// <inheritdoc/>
public Image<TColor> Decode<TColor>(Configuration configuration, Stream stream, IDecoderOptions options)
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, IDecoderOptions options)
where TColor : struct, IPixel<TColor>
where TPixel : struct, IPixel<TPixel>
{
IGifDecoderOptions gifOptions = GifDecoderOptions.Create(options);
return this.Decode<TColor>(configuration, stream, gifOptions);
return this.Decode<TPixel>(configuration, stream, gifOptions);
}
/// <summary>
/// Decodes the image from the specified stream to the <see cref="ImageBase{TColor}"/>.
/// Decodes the image from the specified stream to the <see cref="ImageBase{TPixel}"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="configuration">The configuration.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <param name="options">The options for the decoder.</param>
/// <returns>The image thats been decoded.</returns>
public Image<TColor> Decode<TColor>(Configuration configuration, Stream stream, IGifDecoderOptions options)
where TColor : struct, IPixel<TColor>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, IGifDecoderOptions options)
where TPixel : struct, IPixel<TPixel>
{
return new GifDecoderCore<TColor>(options, configuration).Decode(stream);
return new GifDecoderCore<TPixel>(options, configuration).Decode(stream);
}
}
}

60
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -8,14 +8,17 @@ namespace ImageSharp.Formats
using System;
using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using ImageSharp.PixelFormats;
/// <summary>
/// Performs the gif decoding operation.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
internal class GifDecoderCore<TColor>
where TColor : struct, IPixel<TColor>
/// <typeparam name="TPixel">The pixel format.</typeparam>
internal class GifDecoderCore<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// The temp buffer used to reduce allocations.
@ -50,7 +53,7 @@ namespace ImageSharp.Formats
/// <summary>
/// The previous frame.
/// </summary>
private ImageFrame<TColor> previousFrame;
private ImageFrame<TPixel> previousFrame;
/// <summary>
/// The area to restore.
@ -75,10 +78,10 @@ namespace ImageSharp.Formats
/// <summary>
/// The image to decode the information to.
/// </summary>
private Image<TColor> image;
private Image<TPixel> image;
/// <summary>
/// Initializes a new instance of the <see cref="GifDecoderCore{TColor}"/> class.
/// Initializes a new instance of the <see cref="GifDecoderCore{TPixel}"/> class.
/// </summary>
/// <param name="options">The decoder options.</param>
/// <param name="configuration">The configuration.</param>
@ -93,7 +96,7 @@ namespace ImageSharp.Formats
/// </summary>
/// <param name="stream">The stream containing image data. </param>
/// <returns>The decoded image</returns>
public Image<TColor> Decode(Stream stream)
public Image<TPixel> Decode(Stream stream)
{
try
{
@ -227,10 +230,10 @@ namespace ImageSharp.Formats
}
/* // No point doing this as the max width/height is always int.Max and that always bigger than the max size of a gif which is stored in a short.
if (this.logicalScreenDescriptor.Width > Image<TColor>.MaxWidth || this.logicalScreenDescriptor.Height > Image<TColor>.MaxHeight)
if (this.logicalScreenDescriptor.Width > Image<TPixel>.MaxWidth || this.logicalScreenDescriptor.Height > Image<TPixel>.MaxHeight)
{
throw new ArgumentOutOfRangeException(
$"The input gif '{this.logicalScreenDescriptor.Width}x{this.logicalScreenDescriptor.Height}' is bigger then the max allowed size '{Image<TColor>.MaxWidth}x{Image<TColor>.MaxHeight}'");
$"The input gif '{this.logicalScreenDescriptor.Width}x{this.logicalScreenDescriptor.Height}' is bigger then the max allowed size '{Image<TPixel>.MaxWidth}x{Image<TPixel>.MaxHeight}'");
}
*/
}
@ -330,6 +333,7 @@ namespace ImageSharp.Formats
/// </summary>
/// <param name="imageDescriptor">The <see cref="GifImageDescriptor"/>.</param>
/// <param name="indices">The pixel array to write to.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadFrameIndices(GifImageDescriptor imageDescriptor, byte[] indices)
{
int dataSize = this.currentStream.ReadByte();
@ -351,20 +355,20 @@ namespace ImageSharp.Formats
int imageWidth = this.logicalScreenDescriptor.Width;
int imageHeight = this.logicalScreenDescriptor.Height;
ImageFrame<TColor> previousFrame = null;
ImageFrame<TPixel> previousFrame = null;
ImageFrame<TColor> currentFrame = null;
ImageFrame<TPixel> currentFrame = null;
ImageBase<TColor> image;
ImageBase<TPixel> image;
if (this.previousFrame == null)
{
this.metaData.Quality = colorTableLength / 3;
// This initializes the image to become fully transparent because the alpha channel is zero.
this.image = Image.Create<TColor>(imageWidth, imageHeight, this.metaData, this.configuration);
this.image = new Image<TPixel>(this.configuration, imageWidth, imageHeight, this.metaData);
this.SetFrameDelay(this.metaData);
this.SetFrameMetaData(this.metaData);
image = this.image;
}
@ -378,7 +382,7 @@ namespace ImageSharp.Formats
currentFrame = this.previousFrame.Clone();
this.SetFrameDelay(currentFrame.MetaData);
this.SetFrameMetaData(currentFrame.MetaData);
image = currentFrame;
@ -392,7 +396,7 @@ namespace ImageSharp.Formats
int interlaceIncrement = 8; // The interlacing line increment
int interlaceY = 0; // The current interlaced line
using (PixelAccessor<TColor> pixelAccessor = image.Lock())
using (PixelAccessor<TPixel> pixelAccessor = image.Lock())
{
for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
{
@ -441,7 +445,7 @@ namespace ImageSharp.Formats
{
int indexOffset = index * 3;
TColor pixel = default(TColor);
TPixel pixel = default(TPixel);
pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255);
pixelAccessor[x, writeY] = pixel;
}
@ -470,7 +474,7 @@ namespace ImageSharp.Formats
/// Restores the current frame area to the background.
/// </summary>
/// <param name="frame">The frame.</param>
private void RestoreToBackground(ImageBase<TColor> frame)
private void RestoreToBackground(ImageBase<TPixel> frame)
{
if (this.restoreArea == null)
{
@ -481,16 +485,16 @@ namespace ImageSharp.Formats
if (this.restoreArea.Value.Width == this.image.Width &&
this.restoreArea.Value.Height == this.image.Height)
{
using (PixelAccessor<TColor> pixelAccessor = frame.Lock())
using (PixelAccessor<TPixel> pixelAccessor = frame.Lock())
{
pixelAccessor.Reset();
}
}
else
{
using (PixelArea<TColor> emptyRow = new PixelArea<TColor>(this.restoreArea.Value.Width, ComponentOrder.Xyzw))
using (PixelArea<TPixel> emptyRow = new PixelArea<TPixel>(this.restoreArea.Value.Width, ComponentOrder.Xyzw))
{
using (PixelAccessor<TColor> pixelAccessor = frame.Lock())
using (PixelAccessor<TPixel> pixelAccessor = frame.Lock())
{
for (int y = this.restoreArea.Value.Top; y < this.restoreArea.Value.Top + this.restoreArea.Value.Height; y++)
{
@ -504,14 +508,20 @@ namespace ImageSharp.Formats
}
/// <summary>
/// Sets the frame delay in the metadata.
/// Sets the frames metadata.
/// </summary>
/// <param name="metaData">The meta data.</param>
private void SetFrameDelay(IMetaData metaData)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void SetFrameMetaData(IMetaData metaData)
{
if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0)
if (this.graphicsControlExtension != null)
{
metaData.FrameDelay = this.graphicsControlExtension.DelayTime;
if (this.graphicsControlExtension.DelayTime > 0)
{
metaData.FrameDelay = this.graphicsControlExtension.DelayTime;
}
metaData.DisposalMethod = this.graphicsControlExtension.DisposalMethod;
}
}
}

16
src/ImageSharp/Formats/Gif/GifEncoder.cs

@ -8,14 +8,16 @@ namespace ImageSharp.Formats
using System;
using System.IO;
using ImageSharp.PixelFormats;
/// <summary>
/// Image encoder for writing image data to a stream in gif format.
/// </summary>
public class GifEncoder : IImageEncoder
{
/// <inheritdoc/>
public void Encode<TColor>(Image<TColor> image, Stream stream, IEncoderOptions options)
where TColor : struct, IPixel<TColor>
public void Encode<TPixel>(Image<TPixel> image, Stream stream, IEncoderOptions options)
where TPixel : struct, IPixel<TPixel>
{
IGifEncoderOptions gifOptions = GifEncoderOptions.Create(options);
@ -23,14 +25,14 @@ namespace ImageSharp.Formats
}
/// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TColor}"/>.
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TColor}"/> to encode from.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
/// <param name="options">The options for the encoder.</param>
public void Encode<TColor>(Image<TColor> image, Stream stream, IGifEncoderOptions options)
where TColor : struct, IPixel<TColor>
public void Encode<TPixel>(Image<TPixel> image, Stream stream, IGifEncoderOptions options)
where TPixel : struct, IPixel<TPixel>
{
GifEncoderCore encoder = new GifEncoderCore(options);
encoder.Encode(image, stream);

116
src/ImageSharp/Formats/Gif/GifEncoderCore.cs

@ -10,6 +10,8 @@ namespace ImageSharp.Formats
using System.IO;
using System.Linq;
using ImageSharp.PixelFormats;
using IO;
using Quantizers;
@ -33,6 +35,11 @@ namespace ImageSharp.Formats
/// </summary>
private int bitDepth;
/// <summary>
/// Whether the current image has multiple frames.
/// </summary>
private bool hasFrames;
/// <summary>
/// Initializes a new instance of the <see cref="GifEncoderCore"/> class.
/// </summary>
@ -48,18 +55,18 @@ namespace ImageSharp.Formats
public IQuantizer Quantizer { get; set; }
/// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TColor}"/>.
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TColor}"/> to encode from.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public void Encode<TColor>(Image<TColor> image, Stream stream)
where TColor : struct, IPixel<TColor>
public void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : struct, IPixel<TPixel>
{
Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream));
this.Quantizer = this.options.Quantizer ?? new OctreeQuantizer<TColor>();
this.Quantizer = this.options.Quantizer ?? new OctreeQuantizer<TPixel>();
// Do not use IDisposable pattern here as we want to preserve the stream.
EndianBinaryWriter writer = new EndianBinaryWriter(Endianness.LittleEndian, stream);
@ -72,7 +79,13 @@ namespace ImageSharp.Formats
this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quality);
// Quantize the image returning a palette.
QuantizedImage<TColor> quantized = ((IQuantizer<TColor>)this.Quantizer).Quantize(image, quality);
this.hasFrames = image.Frames.Any();
// Dithering when animating gifs is a bad idea as we introduce pixel tearing across frames.
IQuantizer<TPixel> ditheredQuantizer = (IQuantizer<TPixel>)this.Quantizer;
ditheredQuantizer.Dither = !this.hasFrames;
QuantizedImage<TPixel> quantized = ditheredQuantizer.Quantize(image, quality);
int index = this.GetTransparentIndex(quantized);
@ -90,15 +103,15 @@ namespace ImageSharp.Formats
this.WriteImageData(quantized, writer);
// Write additional frames.
if (image.Frames.Any())
if (this.hasFrames)
{
this.WriteApplicationExtension(writer, image.MetaData.RepeatCount, image.Frames.Count);
// ReSharper disable once ForCanBeConvertedToForeach
for (int i = 0; i < image.Frames.Count; i++)
{
ImageFrame<TColor> frame = image.Frames[i];
QuantizedImage<TColor> quantizedFrame = ((IQuantizer<TColor>)this.Quantizer).Quantize(frame, quality);
ImageFrame<TPixel> frame = image.Frames[i];
QuantizedImage<TPixel> quantizedFrame = ditheredQuantizer.Quantize(frame, quality);
this.WriteGraphicalControlExtension(frame, writer, this.GetTransparentIndex(quantizedFrame));
this.WriteImageDescriptor(frame, writer);
@ -117,12 +130,12 @@ namespace ImageSharp.Formats
/// <param name="quantized">
/// The quantized.
/// </param>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>
/// The <see cref="int"/>.
/// </returns>
private int GetTransparentIndex<TColor>(QuantizedImage<TColor> quantized)
where TColor : struct, IPixel<TColor>
private int GetTransparentIndex<TPixel>(QuantizedImage<TPixel> quantized)
where TPixel : struct, IPixel<TPixel>
{
// Find the lowest alpha value and make it the transparent index.
int index = 255;
@ -167,18 +180,18 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the logical screen descriptor to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The image to encode.</param>
/// <param name="writer">The writer to write to the stream with.</param>
/// <param name="tranparencyIndex">The transparency index to set the default background index to.</param>
private void WriteLogicalScreenDescriptor<TColor>(Image<TColor> image, EndianBinaryWriter writer, int tranparencyIndex)
where TColor : struct, IPixel<TColor>
private void WriteLogicalScreenDescriptor<TPixel>(Image<TPixel> image, EndianBinaryWriter writer, int tranparencyIndex)
where TPixel : struct, IPixel<TPixel>
{
GifLogicalScreenDescriptor descriptor = new GifLogicalScreenDescriptor
{
Width = (short)image.Width,
Height = (short)image.Height,
GlobalColorTableFlag = false, // Always false for now.
GlobalColorTableFlag = false, // TODO: Always false for now.
GlobalColorTableSize = this.bitDepth - 1,
BackgroundColorIndex = (byte)tranparencyIndex
};
@ -222,8 +235,7 @@ namespace ImageSharp.Formats
writer.Write((byte)1); // Data sub-block index (always 1)
// 0 means loop indefinitely. Count is set as play n + 1 times.
repeatCount = (ushort)(Math.Max((ushort)0, repeatCount) - 1);
repeatCount = (ushort)Math.Max(0, repeatCount - 1);
writer.Write(repeatCount); // Repeat count for images.
writer.Write(GifConstants.Terminator); // Terminator
@ -233,11 +245,11 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the image comments to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TColor}"/> to be encoded.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TPixel}"/> to be encoded.</param>
/// <param name="writer">The stream to write to.</param>
private void WriteComments<TColor>(Image<TColor> image, EndianBinaryWriter writer)
where TColor : struct, IPixel<TColor>
private void WriteComments<TPixel>(Image<TPixel> image, EndianBinaryWriter writer)
where TPixel : struct, IPixel<TPixel>
{
if (this.options.IgnoreMetadata == true)
{
@ -266,12 +278,12 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the graphics control extension to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TColor}"/> to encode.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode.</param>
/// <param name="writer">The stream to write to.</param>
/// <param name="transparencyIndex">The index of the color in the color palette to make transparent.</param>
private void WriteGraphicalControlExtension<TColor>(Image<TColor> image, EndianBinaryWriter writer, int transparencyIndex)
where TColor : struct, IPixel<TColor>
private void WriteGraphicalControlExtension<TPixel>(Image<TPixel> image, EndianBinaryWriter writer, int transparencyIndex)
where TPixel : struct, IPixel<TPixel>
{
this.WriteGraphicalControlExtension(image, image.MetaData, writer, transparencyIndex);
}
@ -279,12 +291,12 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the graphics control extension to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="imageFrame">The <see cref="ImageFrame{TColor}"/> to encode.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="imageFrame">The <see cref="ImageFrame{TPixel}"/> to encode.</param>
/// <param name="writer">The stream to write to.</param>
/// <param name="transparencyIndex">The index of the color in the color palette to make transparent.</param>
private void WriteGraphicalControlExtension<TColor>(ImageFrame<TColor> imageFrame, EndianBinaryWriter writer, int transparencyIndex)
where TColor : struct, IPixel<TColor>
private void WriteGraphicalControlExtension<TPixel>(ImageFrame<TPixel> imageFrame, EndianBinaryWriter writer, int transparencyIndex)
where TPixel : struct, IPixel<TPixel>
{
this.WriteGraphicalControlExtension(imageFrame, imageFrame.MetaData, writer, transparencyIndex);
}
@ -292,24 +304,18 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the graphics control extension to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TColor}"/> to encode.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TPixel}"/> to encode.</param>
/// <param name="metaData">The metadata of the image or frame.</param>
/// <param name="writer">The stream to write to.</param>
/// <param name="transparencyIndex">The index of the color in the color palette to make transparent.</param>
private void WriteGraphicalControlExtension<TColor>(ImageBase<TColor> image, IMetaData metaData, EndianBinaryWriter writer, int transparencyIndex)
where TColor : struct, IPixel<TColor>
private void WriteGraphicalControlExtension<TPixel>(ImageBase<TPixel> image, IMetaData metaData, EndianBinaryWriter writer, int transparencyIndex)
where TPixel : struct, IPixel<TPixel>
{
// TODO: Check transparency logic.
bool hasTransparent = transparencyIndex < 255;
DisposalMethod disposalMethod = hasTransparent
? DisposalMethod.RestoreToBackground
: DisposalMethod.Unspecified;
GifGraphicsControlExtension extension = new GifGraphicsControlExtension()
{
DisposalMethod = disposalMethod,
TransparencyFlag = hasTransparent,
DisposalMethod = metaData.DisposalMethod,
TransparencyFlag = transparencyIndex < 255,
TransparencyIndex = transparencyIndex,
DelayTime = metaData.FrameDelay
};
@ -336,11 +342,11 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the image descriptor to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TColor}"/> to be encoded.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TPixel}"/> to be encoded.</param>
/// <param name="writer">The stream to write to.</param>
private void WriteImageDescriptor<TColor>(ImageBase<TColor> image, EndianBinaryWriter writer)
where TColor : struct, IPixel<TColor>
private void WriteImageDescriptor<TPixel>(ImageBase<TPixel> image, EndianBinaryWriter writer)
where TPixel : struct, IPixel<TPixel>
{
writer.Write(GifConstants.ImageDescriptorLabel); // 2c
@ -362,11 +368,11 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the color table to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TColor}"/> to encode.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TPixel}"/> to encode.</param>
/// <param name="writer">The writer to write to the stream with.</param>
private void WriteColorTable<TColor>(QuantizedImage<TColor> image, EndianBinaryWriter writer)
where TColor : struct, IPixel<TColor>
private void WriteColorTable<TPixel>(QuantizedImage<TPixel> image, EndianBinaryWriter writer)
where TPixel : struct, IPixel<TPixel>
{
// Grab the palette and write it to the stream.
int pixelCount = image.Palette.Length;
@ -397,11 +403,11 @@ namespace ImageSharp.Formats
/// <summary>
/// Writes the image pixel data to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="QuantizedImage{TColor}"/> containing indexed pixels.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="QuantizedImage{TPixel}"/> containing indexed pixels.</param>
/// <param name="writer">The stream to write to.</param>
private void WriteImageData<TColor>(QuantizedImage<TColor> image, EndianBinaryWriter writer)
where TColor : struct, IPixel<TColor>
private void WriteImageData<TPixel>(QuantizedImage<TPixel> image, EndianBinaryWriter writer)
where TPixel : struct, IPixel<TPixel>
{
using (LzwEncoder encoder = new LzwEncoder(image.Pixels, (byte)this.bitDepth))
{

20
src/ImageSharp/Formats/Gif/ImageExtensions.cs

@ -10,23 +10,25 @@ namespace ImageSharp
using Formats;
using ImageSharp.PixelFormats;
/// <summary>
/// Extension methods for the <see cref="Image{TColor}"/> type.
/// Extension methods for the <see cref="Image{TPixel}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Saves the image to the given stream with the gif format.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="stream">The stream to save the image to.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
/// <returns>
/// The <see cref="Image{TColor}"/>.
/// The <see cref="Image{TPixel}"/>.
/// </returns>
public static Image<TColor> SaveAsGif<TColor>(this Image<TColor> source, Stream stream)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> SaveAsGif<TPixel>(this Image<TPixel> source, Stream stream)
where TPixel : struct, IPixel<TPixel>
{
return SaveAsGif(source, stream, null);
}
@ -34,16 +36,16 @@ namespace ImageSharp
/// <summary>
/// Saves the image to the given stream with the gif format.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="stream">The stream to save the image to.</param>
/// <param name="options">The options for the encoder.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
/// <returns>
/// The <see cref="Image{TColor}"/>.
/// The <see cref="Image{TPixel}"/>.
/// </returns>
public static Image<TColor> SaveAsGif<TColor>(this Image<TColor> source, Stream stream, IGifEncoderOptions options)
where TColor : struct, IPixel<TColor>
public static Image<TPixel> SaveAsGif<TPixel>(this Image<TPixel> source, Stream stream, IGifEncoderOptions options)
where TPixel : struct, IPixel<TPixel>
{
GifEncoder encoder = new GifEncoder();
encoder.Encode(source, stream, options);

2476
src/ImageSharp/Formats/Gif/spec-gif89a.txt

File diff suppressed because it is too large

10
src/ImageSharp/Formats/IImageDecoder.cs

@ -8,20 +8,22 @@ namespace ImageSharp.Formats
using System;
using System.IO;
using ImageSharp.PixelFormats;
/// <summary>
/// Encapsulates properties and methods required for decoding an image from a stream.
/// </summary>
public interface IImageDecoder
{
/// <summary>
/// Decodes the image from the specified stream to the <see cref="ImageBase{TColor}"/>.
/// Decodes the image from the specified stream to the <see cref="ImageBase{TPixel}"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="configuration">The configuration for the image.</param>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <param name="options">The options for the decoder.</param>
/// <returns>The decoded image</returns>
Image<TColor> Decode<TColor>(Configuration configuration, Stream stream, IDecoderOptions options)
where TColor : struct, IPixel<TColor>;
Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream, IDecoderOptions options)
where TPixel : struct, IPixel<TPixel>;
}
}

12
src/ImageSharp/Formats/IImageEncoder.cs

@ -8,19 +8,21 @@ namespace ImageSharp.Formats
using System;
using System.IO;
using ImageSharp.PixelFormats;
/// <summary>
/// Encapsulates properties and methods required for encoding an image to a stream.
/// </summary>
public interface IImageEncoder
{
/// <summary>
/// Encodes the image to the specified stream from the <see cref="Image{TColor}"/>.
/// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TColor}"/> to encode from.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
/// <param name="options">The options for the encoder.</param>
void Encode<TColor>(Image<TColor> image, Stream stream, IEncoderOptions options)
where TColor : struct, IPixel<TColor>;
void Encode<TPixel>(Image<TPixel> image, Stream stream, IEncoderOptions options)
where TPixel : struct, IPixel<TPixel>;
}
}

2
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs

@ -235,7 +235,7 @@ namespace ImageSharp.Formats.Jpg
/// </summary>
/// <param name="scaleVec">Vector to multiply by</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MultiplyAllInplace(Vector4 scaleVec)
public void MultiplyAllInplace(float scaleVec)
{
this.V0L *= scaleVec;
this.V0R *= scaleVec;

52
src/ImageSharp/Formats/Jpeg/Components/DCT.cs

@ -15,31 +15,31 @@ namespace ImageSharp.Formats.Jpg
internal static class DCT
{
#pragma warning disable SA1310 // FieldNamesMustNotContainUnderscore
private static readonly Vector4 C_1_175876 = new Vector4(1.175876f);
private static readonly float C_1_175876 = 1.175876f;
private static readonly Vector4 C_1_961571 = new Vector4(-1.961571f);
private static readonly float C_1_961571 = -1.961571f;
private static readonly Vector4 C_0_390181 = new Vector4(-0.390181f);
private static readonly float C_0_390181 = -0.390181f;
private static readonly Vector4 C_0_899976 = new Vector4(-0.899976f);
private static readonly float C_0_899976 = -0.899976f;
private static readonly Vector4 C_2_562915 = new Vector4(-2.562915f);
private static readonly float C_2_562915 = -2.562915f;
private static readonly Vector4 C_0_298631 = new Vector4(0.298631f);
private static readonly float C_0_298631 = 0.298631f;
private static readonly Vector4 C_2_053120 = new Vector4(2.053120f);
private static readonly float C_2_053120 = 2.053120f;
private static readonly Vector4 C_3_072711 = new Vector4(3.072711f);
private static readonly float C_3_072711 = 3.072711f;
private static readonly Vector4 C_1_501321 = new Vector4(1.501321f);
private static readonly float C_1_501321 = 1.501321f;
private static readonly Vector4 C_0_541196 = new Vector4(0.541196f);
private static readonly float C_0_541196 = 0.541196f;
private static readonly Vector4 C_1_847759 = new Vector4(-1.847759f);
private static readonly float C_1_847759 = -1.847759f;
private static readonly Vector4 C_0_765367 = new Vector4(0.765367f);
private static readonly float C_0_765367 = 0.765367f;
private static readonly Vector4 C_0_125 = new Vector4(0.1250f);
private static readonly float C_0_125 = 0.1250f;
#pragma warning restore SA1310 // FieldNamesMustNotContainUnderscore
private static readonly Vector4 InvSqrt2 = new Vector4(0.707107f);
@ -216,26 +216,26 @@ namespace ImageSharp.Formats.Jpg
d.V0L = c0 + c1;
d.V4L = c0 - c1;
Vector4 w0 = new Vector4(0.541196f);
Vector4 w1 = new Vector4(1.306563f);
float w0 = 0.541196f;
float w1 = 1.306563f;
d.V2L = (w0 * c2) + (w1 * c3);
d.V6L = (w0 * c3) - (w1 * c2);
w0 = new Vector4(1.175876f);
w1 = new Vector4(0.785695f);
w0 = 1.175876f;
w1 = 0.785695f;
c3 = (w0 * t4) + (w1 * t7);
c0 = (w0 * t7) - (w1 * t4);
w0 = new Vector4(1.387040f);
w1 = new Vector4(0.275899f);
w0 = 1.387040f;
w1 = 0.275899f;
c2 = (w0 * t5) + (w1 * t6);
c1 = (w0 * t6) - (w1 * t5);
d.V3L = c0 - c2;
d.V5L = c3 - c1;
Vector4 invsqrt2 = new Vector4(0.707107f);
float invsqrt2 = 0.707107f;
c0 = (c0 + c2) * invsqrt2;
c3 = (c3 + c1) * invsqrt2;
@ -281,19 +281,19 @@ namespace ImageSharp.Formats.Jpg
d.V0R = c0 + c1;
d.V4R = c0 - c1;
Vector4 w0 = new Vector4(0.541196f);
Vector4 w1 = new Vector4(1.306563f);
float w0 = 0.541196f;
float w1 = 1.306563f;
d.V2R = (w0 * c2) + (w1 * c3);
d.V6R = (w0 * c3) - (w1 * c2);
w0 = new Vector4(1.175876f);
w1 = new Vector4(0.785695f);
w0 = 1.175876f;
w1 = 0.785695f;
c3 = (w0 * t4) + (w1 * t7);
c0 = (w0 * t7) - (w1 * t4);
w0 = new Vector4(1.387040f);
w1 = new Vector4(0.275899f);
w0 = 1.387040f;
w1 = 0.275899f;
c2 = (w0 * t5) + (w1 * t6);
c1 = (w0 * t6) - (w1 * t5);

55
src/ImageSharp/Formats/Jpeg/Components/Decoder/DecodedBlockArray.cs

@ -1,55 +0,0 @@
// <copyright file="DecodedBlockArray.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Formats.Jpg
{
using System;
using System.Buffers;
/// <summary>
/// Because <see cref="System.Array.Length"/> has no information for rented arrays,
/// we need to store the count and the buffer separately when storing pooled <see cref="DecodedBlock"/> arrays.
/// </summary>
internal struct DecodedBlockArray : IDisposable
{
/// <summary>
/// The <see cref="ArrayPool{T}"/> used to pool data in <see cref="JpegDecoderCore.DecodedBlocks"/>.
/// Should always clean arrays when returning!
/// </summary>
private static readonly ArrayPool<DecodedBlock> ArrayPool = ArrayPool<DecodedBlock>.Create();
/// <summary>
/// Initializes a new instance of the <see cref="DecodedBlockArray"/> struct. Rents a buffer.
/// </summary>
/// <param name="count">The number of valid <see cref="DecodedBlock"/>-s</param>
public DecodedBlockArray(int count)
{
this.Count = count;
this.Buffer = ArrayPool.Rent(count);
}
/// <summary>
/// Gets the number of actual <see cref="DecodedBlock"/>-s inside <see cref="Buffer"/>
/// </summary>
public int Count { get; }
/// <summary>
/// Gets the rented buffer.
/// </summary>
public DecodedBlock[] Buffer { get; private set; }
/// <summary>
/// Returns the rented buffer to the pool.
/// </summary>
public void Dispose()
{
if (this.Buffer != null)
{
ArrayPool.Return(this.Buffer, true);
this.Buffer = null;
}
}
}
}

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

Loading…
Cancel
Save