diff --git a/ImageSharp.sln.DotSettings b/ImageSharp.sln.DotSettings
index 435aad73b..432f4524a 100644
--- a/ImageSharp.sln.DotSettings
+++ b/ImageSharp.sln.DotSettings
@@ -343,8 +343,11 @@
<Entry DisplayName="All other members" />
</TypePattern>
</Patterns>
- True
+ False
True
+ // Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
AC
DC
DCT
diff --git a/appveyor.yml b/appveyor.yml
index 3e6b79bfc..5d84e6cea 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,5 +1,5 @@
version: 1.0.0.{build}
-image: Visual Studio 2017
+image: Previous Visual Studio 2017
# prevent the double build when a branch has an active PR
skip_branch_with_pr: true
diff --git a/build.ps1 b/build.ps1
index 4c5a36cae..35b8344dc 100644
--- a/build.ps1
+++ b/build.ps1
@@ -8,7 +8,7 @@ $tagRegex = '^v?(\d+\.\d+\.\d+)(-([a-zA-Z]+)\.?(\d*))?$'
# we are running on the build server
$isVersionTag = $env:APPVEYOR_REPO_TAG_NAME -match $tagRegex
- if($isVersionTag){
+ if($isVersionTag) {
Write-Debug "Building commit tagged with a compatable version number"
@@ -26,7 +26,8 @@ $isVersionTag = $env:APPVEYOR_REPO_TAG_NAME -match $tagRegex
$version = "${version}${padded}"
}
- }else {
+ }
+ else {
Write-Debug "Untagged"
$lastTag = (git tag --list --sort=-taggerdate) | Out-String
diff --git a/src/ImageSharp.Drawing/Primitives/ShapePath.cs b/src/ImageSharp.Drawing/Primitives/ShapePath.cs
index 7a8c9e895..a4fef66a6 100644
--- a/src/ImageSharp.Drawing/Primitives/ShapePath.cs
+++ b/src/ImageSharp.Drawing/Primitives/ShapePath.cs
@@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using SixLabors.ImageSharp.Processing.Drawing.Pens;
+using SixLabors.ImageSharp.Processing;
using SixLabors.Shapes;
namespace SixLabors.ImageSharp.Primitives
diff --git a/src/ImageSharp.Drawing/Primitives/ShapeRegion.cs b/src/ImageSharp.Drawing/Primitives/ShapeRegion.cs
index 9f5611dc0..fddd283e0 100644
--- a/src/ImageSharp.Drawing/Primitives/ShapeRegion.cs
+++ b/src/ImageSharp.Drawing/Primitives/ShapeRegion.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using SixLabors.Memory;
using SixLabors.Primitives;
using SixLabors.Shapes;
@@ -45,7 +46,7 @@ namespace SixLabors.ImageSharp.Primitives
var start = new PointF(this.Bounds.Left - 1, y);
var end = new PointF(this.Bounds.Right + 1, y);
- using (IBuffer tempBuffer = configuration.MemoryAllocator.Allocate(buffer.Length))
+ using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(buffer.Length))
{
Span innerBuffer = tempBuffer.GetSpan();
int count = this.Shape.FindIntersections(start, end, innerBuffer);
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/BrushApplicator.cs b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs
similarity index 93%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/BrushApplicator.cs
rename to src/ImageSharp.Drawing/Processing/BrushApplicator.cs
index 7672681da..64f37eeab 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/BrushApplicator.cs
+++ b/src/ImageSharp.Drawing/Processing/BrushApplicator.cs
@@ -2,11 +2,13 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
+
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// primitive that converts a point in to a color for discovering the fill color based on an implementation
@@ -24,9 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
internal BrushApplicator(ImageFrame target, GraphicsOptions options)
{
this.Target = target;
-
this.Options = options;
-
this.Blender = PixelOperations.Instance.GetPixelBlender(options.BlenderMode);
}
@@ -67,8 +67,8 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
{
MemoryAllocator memoryAllocator = this.Target.MemoryAllocator;
- using (IBuffer amountBuffer = memoryAllocator.Allocate(scanline.Length))
- using (IBuffer overlay = memoryAllocator.Allocate(scanline.Length))
+ using (IMemoryOwner amountBuffer = memoryAllocator.Allocate(scanline.Length))
+ using (IMemoryOwner overlay = memoryAllocator.Allocate(scanline.Length))
{
Span amountSpan = amountBuffer.GetSpan();
Span overlaySpan = overlay.GetSpan();
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/Brushes.cs b/src/ImageSharp.Drawing/Processing/Brushes.cs
similarity index 99%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/Brushes.cs
rename to src/ImageSharp.Drawing/Processing/Brushes.cs
index 141ca403b..c5e7a3e9f 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/Brushes.cs
+++ b/src/ImageSharp.Drawing/Processing/Brushes.cs
@@ -3,7 +3,7 @@
using SixLabors.ImageSharp.PixelFormats;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// A collection of methods for creating generic brushes.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/ColorStop{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs
similarity index 86%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/ColorStop{TPixel}.cs
rename to src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs
index 298af5cb5..7fd0ba7cd 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/ColorStop{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/ColorStop{TPixel}.cs
@@ -1,8 +1,11 @@
-using System.Diagnostics;
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.Diagnostics;
using SixLabors.ImageSharp.PixelFormats;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes.GradientBrushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// A struct that defines a single color stop.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/DrawBezierExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/DrawBezierExtensions.cs
rename to src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs
index 72bd76fa6..782f5d4d7 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/DrawBezierExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/DrawBezierExtensions.cs
@@ -2,12 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Drawing.Pens;
using SixLabors.Primitives;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the drawing of Bezier paths to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/DrawImageExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs
similarity index 98%
rename from src/ImageSharp.Drawing/Processing/Drawing/DrawImageExtensions.cs
rename to src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs
index 83e1b90f5..7c9d7c280 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/DrawImageExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/DrawImageExtensions.cs
@@ -2,10 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Processors;
+using SixLabors.ImageSharp.Processing.Processors.Drawing;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the drawing of images to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/DrawLineExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/DrawLineExtensions.cs
rename to src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs
index 981a07e13..9084b30ef 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/DrawLineExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/DrawLineExtensions.cs
@@ -2,12 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Drawing.Pens;
using SixLabors.Primitives;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the drawing of lines to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/DrawPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/DrawPathCollectionExtensions.cs
rename to src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs
index eca3805bd..0d3abf297 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/DrawPathCollectionExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/DrawPathCollectionExtensions.cs
@@ -2,11 +2,9 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Drawing.Pens;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the drawing of collections of polygon outlines to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/DrawPathExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/DrawPathExtensions.cs
rename to src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs
index a15412a45..4dbe942f2 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/DrawPathExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/DrawPathExtensions.cs
@@ -3,11 +3,9 @@
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Drawing.Pens;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the drawing of polygon outlines to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/DrawPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/DrawPolygonExtensions.cs
rename to src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs
index 9f8d74f00..4dcfe00aa 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/DrawPolygonExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/DrawPolygonExtensions.cs
@@ -2,12 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Drawing.Pens;
using SixLabors.Primitives;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the drawing of closed linear polygons to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/DrawRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/DrawRectangleExtensions.cs
rename to src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs
index 1f4a38a27..918fb1e73 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/DrawRectangleExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/DrawRectangleExtensions.cs
@@ -2,12 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Drawing.Pens;
using SixLabors.Primitives;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the drawing of rectangles to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Text/DrawTextExtensions.cs b/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs
similarity index 96%
rename from src/ImageSharp.Drawing/Processing/Text/DrawTextExtensions.cs
rename to src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs
index a20d7f730..46061ce9b 100644
--- a/src/ImageSharp.Drawing/Processing/Text/DrawTextExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/DrawTextExtensions.cs
@@ -3,17 +3,15 @@
using SixLabors.Fonts;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Drawing.Pens;
-using SixLabors.ImageSharp.Processing.Text.Processors;
+using SixLabors.ImageSharp.Processing.Processors.Text;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Text
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the drawing of text to the type.
///
- public static partial class DrawTextExtensions
+ public static class DrawTextExtensions
{
///
/// Draws the text onto the the image filled via the brush.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/EllipticGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/EllipticGradientBrush{TPixel}.cs
rename to src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs
index 43f7fe04e..8af01564c 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/EllipticGradientBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/EllipticGradientBrush{TPixel}.cs
@@ -1,9 +1,12 @@
-using System;
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes.GradientBrushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// Gradient Brush with elliptic shape.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/FillPathBuilderExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/FillPathBuilderExtensions.cs
rename to src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs
index 921209d2e..ff4de3ff8 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/FillPathBuilderExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/FillPathBuilderExtensions.cs
@@ -3,10 +3,9 @@
using System;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the filling of polygons with various brushes to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/FillPathCollectionExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/FillPathCollectionExtensions.cs
rename to src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs
index 71474dceb..da2dd35b6 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/FillPathCollectionExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/FillPathCollectionExtensions.cs
@@ -2,10 +2,9 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the filling of collections of polygon outlines to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/FillPathExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/FillPathExtensions.cs
rename to src/ImageSharp.Drawing/Processing/FillPathExtensions.cs
index 4273fd8be..da1062111 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/FillPathExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/FillPathExtensions.cs
@@ -3,10 +3,9 @@
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the filling of polygon outlines to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/FillPolygonExtensions.cs b/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/FillPolygonExtensions.cs
rename to src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs
index 3b80dd0f4..970ca2264 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/FillPolygonExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/FillPolygonExtensions.cs
@@ -2,11 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
using SixLabors.Primitives;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the filling of closed linear polygons to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/FillRectangleExtensions.cs b/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/FillRectangleExtensions.cs
rename to src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs
index ae0afc5d5..26bf214f7 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/FillRectangleExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/FillRectangleExtensions.cs
@@ -2,11 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
using SixLabors.Primitives;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the filling of rectangles to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/FillRegionExtensions.cs b/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/FillRegionExtensions.cs
rename to src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs
index 997dba22e..e566d0323 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/FillRegionExtensions.cs
+++ b/src/ImageSharp.Drawing/Processing/FillRegionExtensions.cs
@@ -3,10 +3,9 @@
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Drawing.Processors;
+using SixLabors.ImageSharp.Processing.Processors.Drawing;
-namespace SixLabors.ImageSharp.Processing.Drawing
+namespace SixLabors.ImageSharp.Processing
{
///
/// Adds extensions that allow the filling of regions with various brushes to the type.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/GradientBrushBase{TPixel}.cs b/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/GradientBrushBase{TPixel}.cs
rename to src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs
index 061023428..fe997ed7f 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/GradientBrushBase{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/GradientBrushBase{TPixel}.cs
@@ -1,11 +1,14 @@
-using System;
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.PixelFormats.PixelBlenders;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes.GradientBrushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// Base class for Gradient brushes
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/GradientRepetitionMode.cs b/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs
similarity index 89%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/GradientRepetitionMode.cs
rename to src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs
index adbc26ed4..c156153be 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/GradientRepetitionMode.cs
+++ b/src/ImageSharp.Drawing/Processing/GradientRepetitionMode.cs
@@ -1,4 +1,7 @@
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes.GradientBrushes
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Processing
{
///
/// Modes to repeat a gradient.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/IBrush.cs b/src/ImageSharp.Drawing/Processing/IBrush.cs
similarity index 96%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/IBrush.cs
rename to src/ImageSharp.Drawing/Processing/IBrush.cs
index 93ecb7788..a3c94a1b5 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/IBrush.cs
+++ b/src/ImageSharp.Drawing/Processing/IBrush.cs
@@ -4,7 +4,7 @@
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// Brush represents a logical configuration of a brush which can be used to source pixel colors
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Pens/IPen.cs b/src/ImageSharp.Drawing/Processing/IPen.cs
similarity index 89%
rename from src/ImageSharp.Drawing/Processing/Drawing/Pens/IPen.cs
rename to src/ImageSharp.Drawing/Processing/IPen.cs
index 387165e20..6f63dcfd0 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Pens/IPen.cs
+++ b/src/ImageSharp.Drawing/Processing/IPen.cs
@@ -3,9 +3,8 @@
using System;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-namespace SixLabors.ImageSharp.Processing.Drawing.Pens
+namespace SixLabors.ImageSharp.Processing
{
///
/// Interface representing a Pen
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/ImageBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs
similarity index 94%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/ImageBrush{TPixel}.cs
rename to src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs
index 779848856..5ebad0f32 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/ImageBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs
@@ -2,12 +2,13 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// Provides an implementation of an image brush for painting images within areas.
@@ -118,8 +119,8 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
internal override void Apply(Span scanline, int x, int y)
{
// Create a span for colors
- using (IBuffer amountBuffer = this.Target.MemoryAllocator.Allocate(scanline.Length))
- using (IBuffer overlay = this.Target.MemoryAllocator.Allocate(scanline.Length))
+ using (IMemoryOwner amountBuffer = this.Target.MemoryAllocator.Allocate(scanline.Length))
+ using (IMemoryOwner overlay = this.Target.MemoryAllocator.Allocate(scanline.Length))
{
Span amountSpan = amountBuffer.GetSpan();
Span overlaySpan = overlay.GetSpan();
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/LinearGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/LinearGradientBrush{TPixel}.cs
rename to src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs
index 09f816dd9..765bf5499 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/LinearGradientBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/LinearGradientBrush{TPixel}.cs
@@ -1,9 +1,12 @@
-using System;
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes.GradientBrushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// Provides an implementation of a brush for painting linear gradients within areas.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs
similarity index 95%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/PatternBrush{TPixel}.cs
rename to src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs
index 21f2066fb..ab48a185b 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/PatternBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@@ -9,7 +10,7 @@ using SixLabors.ImageSharp.Primitives;
using SixLabors.Memory;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// Provides an implementation of a pattern brush for painting patterns.
@@ -153,8 +154,8 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
int patternY = y % this.pattern.Rows;
MemoryAllocator memoryAllocator = this.Target.MemoryAllocator;
- using (IBuffer amountBuffer = memoryAllocator.Allocate(scanline.Length))
- using (IBuffer overlay = memoryAllocator.Allocate(scanline.Length))
+ using (IMemoryOwner amountBuffer = memoryAllocator.Allocate(scanline.Length))
+ using (IMemoryOwner overlay = memoryAllocator.Allocate(scanline.Length))
{
Span amountSpan = amountBuffer.GetSpan();
Span overlaySpan = overlay.GetSpan();
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Pens/Pens.cs b/src/ImageSharp.Drawing/Processing/Pens.cs
similarity index 98%
rename from src/ImageSharp.Drawing/Processing/Drawing/Pens/Pens.cs
rename to src/ImageSharp.Drawing/Processing/Pens.cs
index b1883e322..90253a3cb 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Pens/Pens.cs
+++ b/src/ImageSharp.Drawing/Processing/Pens.cs
@@ -2,9 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-namespace SixLabors.ImageSharp.Processing.Drawing.Pens
+namespace SixLabors.ImageSharp.Processing
{
///
/// Contains a collection of common Pen styles
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Pens/Pen{TPixel}.cs b/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs
similarity index 84%
rename from src/ImageSharp.Drawing/Processing/Drawing/Pens/Pen{TPixel}.cs
rename to src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs
index 1dd6b6616..26c21a0e5 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Pens/Pen{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/Pen{TPixel}.cs
@@ -3,9 +3,8 @@
using System;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-namespace SixLabors.ImageSharp.Processing.Drawing.Pens
+namespace SixLabors.ImageSharp.Processing
{
///
/// Provides a pen that can apply a pattern to a line with a set brush and thickness
@@ -25,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Pens
private readonly float[] pattern;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The color.
/// The width.
@@ -36,7 +35,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Pens
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The brush.
/// The width.
@@ -49,7 +48,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Pens
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The color.
/// The width.
@@ -59,7 +58,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Pens
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The brush.
/// The width.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Processors/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Drawing/Processors/DrawImageProcessor.cs
rename to src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
index 506df3886..4a59dfe3e 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Processors/DrawImageProcessor.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
@@ -2,14 +2,14 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Processors;
using SixLabors.Memory;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Processors
+namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
///
/// Combines two images together by blending the pixels.
@@ -135,7 +135,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Processors
MemoryAllocator memoryAllocator = this.Image.GetConfiguration().MemoryAllocator;
- using (IBuffer amount = memoryAllocator.Allocate(width))
+ using (IMemoryOwner amount = memoryAllocator.Allocate(width))
{
amount.GetSpan().Fill(this.Opacity);
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Processors/FillProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs
similarity index 93%
rename from src/ImageSharp.Drawing/Processing/Drawing/Processors/FillProcessor.cs
rename to src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs
index 4214041a7..e40ba5316 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Processors/FillProcessor.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs
@@ -2,15 +2,14 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Processors;
using SixLabors.Memory;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Processors
+namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
///
/// Using the brush as a source of pixels colors blends the brush color with source.
@@ -77,7 +76,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Processors
startY = 0;
}
- using (IBuffer amount = source.MemoryAllocator.Allocate(width))
+ using (IMemoryOwner amount = source.MemoryAllocator.Allocate(width))
using (BrushApplicator applicator = this.brush.CreateApplicator(
source,
sourceRectangle,
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Processors/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs
similarity index 95%
rename from src/ImageSharp.Drawing/Processing/Drawing/Processors/FillRegionProcessor.cs
rename to src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs
index 1e968b97e..b9db3f067 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Processors/FillRegionProcessor.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs
@@ -2,15 +2,15 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
+
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Processors;
using SixLabors.ImageSharp.Utils;
using SixLabors.Memory;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Processors
+namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
///
/// Using a brush and a shape fills shape with contents of brush the
@@ -96,8 +96,8 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Processors
using (BrushApplicator applicator = this.Brush.CreateApplicator(source, rect, this.Options))
{
int scanlineWidth = maxX - minX;
- using (IBuffer bBuffer = source.MemoryAllocator.Allocate(maxIntersections))
- using (IBuffer bScanline = source.MemoryAllocator.Allocate(scanlineWidth))
+ using (IMemoryOwner bBuffer = source.MemoryAllocator.Allocate(maxIntersections))
+ using (IMemoryOwner bScanline = source.MemoryAllocator.Allocate(scanlineWidth))
{
bool scanlineDirty = true;
float subpixelFraction = 1f / subpixelCount;
diff --git a/src/ImageSharp.Drawing/Processing/Text/Processors/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs
similarity index 97%
rename from src/ImageSharp.Drawing/Processing/Text/Processors/DrawTextProcessor.cs
rename to src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs
index 9327f9449..048c4440d 100644
--- a/src/ImageSharp.Drawing/Processing/Text/Processors/DrawTextProcessor.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs
@@ -2,19 +2,17 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Collections.Generic;
using SixLabors.Fonts;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-using SixLabors.ImageSharp.Processing.Drawing.Pens;
-using SixLabors.ImageSharp.Processing.Processors;
using SixLabors.ImageSharp.Utils;
using SixLabors.Memory;
using SixLabors.Primitives;
using SixLabors.Shapes;
-namespace SixLabors.ImageSharp.Processing.Text.Processors
+namespace SixLabors.ImageSharp.Processing.Processors.Text
{
///
/// Using the brush as a source of pixels colors blends the brush color with source.
@@ -337,10 +335,10 @@ namespace SixLabors.ImageSharp.Processing.Text.Processors
}
// take the path inside the path builder, scan thing and generate a Buffer2d representing the glyph and cache it.
- Buffer2D fullBuffer = this.MemoryAllocator.Allocate2D(size.Width + 1, size.Height + 1, true);
+ Buffer2D fullBuffer = this.MemoryAllocator.Allocate2D(size.Width + 1, size.Height + 1, AllocationOptions.Clean);
- using (IBuffer bufferBacking = this.MemoryAllocator.Allocate(path.MaxIntersections))
- using (IBuffer rowIntersectionBuffer = this.MemoryAllocator.Allocate(size.Width))
+ using (IMemoryOwner bufferBacking = this.MemoryAllocator.Allocate(path.MaxIntersections))
+ using (IMemoryOwner rowIntersectionBuffer = this.MemoryAllocator.Allocate(size.Width))
{
float subpixelFraction = 1f / subpixelCount;
float subpixelFractionPoint = subpixelFraction / subpixelCount;
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/RadialGradientBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs
similarity index 96%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/RadialGradientBrush{TPixel}.cs
rename to src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs
index 5c0d8051c..16380fc34 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/GradientBrushes/RadialGradientBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/RadialGradientBrush{TPixel}.cs
@@ -1,9 +1,12 @@
-using System;
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes.GradientBrushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// A Circular Gradient Brush, defined by center point and radius.
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/RecolorBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs
similarity index 95%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/RecolorBrush{TPixel}.cs
rename to src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs
index a7da2cc5b..e1b11637d 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/RecolorBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs
@@ -2,20 +2,21 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// Provides an implementation of a brush that can recolor an image
///
/// The pixel format.
public class RecolorBrush : IBrush
- where TPixel : struct, IPixel
+ where TPixel : struct, IPixel
{
///
/// Initializes a new instance of the class.
@@ -138,8 +139,8 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
{
MemoryAllocator memoryAllocator = this.Target.MemoryAllocator;
- using (IBuffer amountBuffer = memoryAllocator.Allocate(scanline.Length))
- using (IBuffer overlay = memoryAllocator.Allocate(scanline.Length))
+ using (IMemoryOwner amountBuffer = memoryAllocator.Allocate(scanline.Length))
+ using (IMemoryOwner overlay = memoryAllocator.Allocate(scanline.Length))
{
Span amountSpan = amountBuffer.GetSpan();
Span overlaySpan = overlay.GetSpan();
diff --git a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/SolidBrush{TPixel}.cs b/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs
similarity index 94%
rename from src/ImageSharp.Drawing/Processing/Drawing/Brushes/SolidBrush{TPixel}.cs
rename to src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs
index 791c307bf..3904f3d9b 100644
--- a/src/ImageSharp.Drawing/Processing/Drawing/Brushes/SolidBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs
@@ -2,12 +2,14 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
+
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
+namespace SixLabors.ImageSharp.Processing
{
///
/// Provides an implementation of a solid brush for painting solid color areas.
@@ -65,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
///
/// Gets the colors.
///
- protected IBuffer Colors { get; }
+ protected IMemoryOwner Colors { get; }
///
/// Gets the color for a single pixel.
@@ -96,7 +98,7 @@ namespace SixLabors.ImageSharp.Processing.Drawing.Brushes
}
else
{
- using (IBuffer amountBuffer = memoryAllocator.Allocate(scanline.Length))
+ using (IMemoryOwner amountBuffer = memoryAllocator.Allocate(scanline.Length))
{
Span amountSpan = amountBuffer.GetSpan();
diff --git a/src/ImageSharp.Drawing/Processing/Text/TextGraphicsOptions.cs b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs
similarity index 99%
rename from src/ImageSharp.Drawing/Processing/Text/TextGraphicsOptions.cs
rename to src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs
index aaa6dea56..dfad06768 100644
--- a/src/ImageSharp.Drawing/Processing/Text/TextGraphicsOptions.cs
+++ b/src/ImageSharp.Drawing/Processing/TextGraphicsOptions.cs
@@ -4,7 +4,7 @@
using SixLabors.Fonts;
using SixLabors.ImageSharp.PixelFormats;
-namespace SixLabors.ImageSharp.Processing.Text
+namespace SixLabors.ImageSharp.Processing
{
///
/// Options for influencing the drawing functions.
diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
index 18b1d994b..1c73b5ed1 100644
--- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
+++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
@@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Advanced
internal static Memory GetPixelMemory(this ImageFrame source)
where TPixel : struct, IPixel
{
- return source.PixelBuffer.Buffer.Memory;
+ return source.PixelBuffer.MemorySource.Memory;
}
///
diff --git a/src/ImageSharp/ColorSpaces/CieLab.cs b/src/ImageSharp/ColorSpaces/CieLab.cs
index 66900079f..82975d933 100644
--- a/src/ImageSharp/ColorSpaces/CieLab.cs
+++ b/src/ImageSharp/ColorSpaces/CieLab.cs
@@ -20,11 +20,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public static readonly CieXyz DefaultWhitePoint = Illuminants.D50;
- ///
- /// Represents a that has L, A, B values set to zero.
- ///
- public static readonly CieLab Empty = default;
-
///
/// The backing vector for SIMD support.
///
@@ -83,11 +78,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Gets the reference white point of this color
///
- public CieXyz WhitePoint
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
+ public CieXyz WhitePoint { get; }
///
/// Gets the lightness dimension.
@@ -119,18 +110,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -171,27 +152,18 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override int GetHashCode()
{
- unchecked
- {
- int hashCode = this.WhitePoint.GetHashCode();
- hashCode = (hashCode * 397) ^ this.backingVector.GetHashCode();
- return hashCode;
- }
+ return HashHelpers.Combine(this.WhitePoint.GetHashCode(), this.backingVector.GetHashCode());
}
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "CieLab [Empty]";
- }
-
- return $"CieLab [ L={this.L:#0.##}, A={this.A:#0.##}, B={this.B:#0.##}]";
+ return this.Equals(default)
+ ? "CieLab [Empty]"
+ : $"CieLab [ L={this.L:#0.##}, A={this.A:#0.##}, B={this.B:#0.##}]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is CieLab other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/CieLch.cs b/src/ImageSharp/ColorSpaces/CieLch.cs
index 57ed5f48d..67a9956bd 100644
--- a/src/ImageSharp/ColorSpaces/CieLch.cs
+++ b/src/ImageSharp/ColorSpaces/CieLch.cs
@@ -20,11 +20,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public static readonly CieXyz DefaultWhitePoint = Illuminants.D50;
- ///
- /// Represents a that has L, C, H values set to zero.
- ///
- public static readonly CieLch Empty = default;
-
///
/// The backing vector for SIMD support.
///
@@ -83,11 +78,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Gets the reference white point of this color
///
- public CieXyz WhitePoint
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
+ public CieXyz WhitePoint { get; }
///
/// Gets the lightness dimension.
@@ -119,18 +110,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -171,23 +152,15 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override int GetHashCode()
{
- unchecked
- {
- int hashCode = this.WhitePoint.GetHashCode();
- hashCode = (hashCode * 397) ^ this.backingVector.GetHashCode();
- return hashCode;
- }
+ return HashHelpers.Combine(this.WhitePoint.GetHashCode(), this.backingVector.GetHashCode());
}
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "CieLch [Empty]";
- }
-
- return $"CieLch [ L={this.L:#0.##}, C={this.C:#0.##}, H={this.H:#0.##}]";
+ return this.Equals(default)
+ ? "CieLch [Empty]"
+ : $"CieLch [ L={this.L:#0.##}, C={this.C:#0.##}, H={this.H:#0.##}]";
}
///
diff --git a/src/ImageSharp/ColorSpaces/CieLchuv.cs b/src/ImageSharp/ColorSpaces/CieLchuv.cs
index a378aae86..0b4c7a903 100644
--- a/src/ImageSharp/ColorSpaces/CieLchuv.cs
+++ b/src/ImageSharp/ColorSpaces/CieLchuv.cs
@@ -20,11 +20,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public static readonly CieXyz DefaultWhitePoint = Illuminants.D65;
- ///
- /// Represents a that has L, C, H values set to zero.
- ///
- public static readonly CieLchuv Empty = default;
-
///
/// The backing vector for SIMD support.
///
@@ -83,11 +78,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Gets the reference white point of this color
///
- public CieXyz WhitePoint
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
+ public CieXyz WhitePoint { get; }
///
/// Gets the lightness dimension.
@@ -119,18 +110,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -144,7 +125,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// True if the current left is equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(CieLchuv left, CieLchuv right)
{
return left.Equals(right);
@@ -162,36 +142,27 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// True if the current left is unequal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(CieLchuv left, CieLchuv right)
{
return !left.Equals(right);
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
- unchecked
- {
- int hashCode = this.WhitePoint.GetHashCode();
- hashCode = (hashCode * 397) ^ this.backingVector.GetHashCode();
- return hashCode;
- }
+ return HashHelpers.Combine(this.WhitePoint.GetHashCode(), this.backingVector.GetHashCode());
}
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "CieLchuv [Empty]";
- }
-
- return $"CieLchuv [ L={this.L:#0.##}, C={this.C:#0.##}, H={this.H:#0.##}]";
+ return this.Equals(default)
+ ? "CieLchuv [Empty]"
+ : $"CieLchuv [ L={this.L:#0.##}, C={this.C:#0.##}, H={this.H:#0.##}";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is CieLchuv other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/CieLuv.cs b/src/ImageSharp/ColorSpaces/CieLuv.cs
index f93e1fd46..dbc3b6dee 100644
--- a/src/ImageSharp/ColorSpaces/CieLuv.cs
+++ b/src/ImageSharp/ColorSpaces/CieLuv.cs
@@ -22,11 +22,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public static readonly CieXyz DefaultWhitePoint = Illuminants.D65;
- ///
- /// Represents a that has L, U, and V values set to zero.
- ///
- public static readonly CieLuv Empty = default;
-
///
/// The backing vector for SIMD support.
///
@@ -85,11 +80,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Gets the reference white point of this color
///
- public CieXyz WhitePoint
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
+ public CieXyz WhitePoint { get; }
///
/// Gets the lightness dimension
@@ -121,18 +112,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -173,27 +154,18 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override int GetHashCode()
{
- unchecked
- {
- int hashCode = this.WhitePoint.GetHashCode();
- hashCode = (hashCode * 397) ^ this.backingVector.GetHashCode();
- return hashCode;
- }
+ return HashHelpers.Combine(this.WhitePoint.GetHashCode(), this.backingVector.GetHashCode());
}
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "CieLuv [ Empty ]";
- }
-
- return $"CieLuv [ L={this.L:#0.##}, U={this.U:#0.##}, V={this.V:#0.##} ]";
+ return this.Equals(default)
+ ? "CieLuv [ Empty ]"
+ : $"CieLuv [ L={this.L:#0.##}, U={this.U:#0.##}, V={this.V:#0.##} ]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is CieLuv other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
index 6716b1bad..4f4f95147 100644
--- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
@@ -14,11 +14,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
internal readonly struct CieXyChromaticityCoordinates : IEquatable, IAlmostEquatable
{
- ///
- /// Represents a that has X, Y values set to zero.
- ///
- public static readonly CieXyChromaticityCoordinates Empty = default;
-
///
/// The backing vector for SIMD support.
///
@@ -69,12 +64,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Y;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
/// Compares two objects for equality.
///
@@ -112,6 +101,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
@@ -120,16 +110,12 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "CieXyChromaticityCoordinates [Empty]";
- }
-
- return $"CieXyChromaticityCoordinates [ X={this.X:#0.##}, Y={this.Y:#0.##}]";
+ return this.Equals(default)
+ ? "CieXyChromaticityCoordinates [Empty]"
+ : $"CieXyChromaticityCoordinates [ X={this.X:#0.##}, Y={this.Y:#0.##}]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is CieXyChromaticityCoordinates other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/CieXyy.cs b/src/ImageSharp/ColorSpaces/CieXyy.cs
index 71ad4701a..ac1a4532c 100644
--- a/src/ImageSharp/ColorSpaces/CieXyy.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyy.cs
@@ -14,11 +14,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
internal readonly struct CieXyy : IColorVector, IEquatable, IAlmostEquatable
{
- ///
- /// Represents a that has X, Y, and Y values set to zero.
- ///
- public static readonly CieXyy Empty = default;
-
///
/// The backing vector for SIMD support.
///
@@ -78,18 +73,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -128,6 +113,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
@@ -136,16 +122,12 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "CieXyy [ Empty ]";
- }
-
- return $"CieXyy [ X={this.X:#0.##}, Y={this.Y:#0.##}, Yl={this.Yl:#0.##} ]";
+ return this.Equals(default)
+ ? "CieXyy [ Empty ]"
+ : $"CieXyy [ X={this.X:#0.##}, Y={this.Y:#0.##}, Yl={this.Yl:#0.##} ]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is CieXyy other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/CieXyz.cs b/src/ImageSharp/ColorSpaces/CieXyz.cs
index 79676bb08..fa4261b46 100644
--- a/src/ImageSharp/ColorSpaces/CieXyz.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyz.cs
@@ -14,11 +14,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
internal readonly struct CieXyz : IColorVector, IEquatable, IAlmostEquatable
{
- ///
- /// Represents a that has X, Y, and Z values set to zero.
- ///
- public static readonly CieXyz Empty = default;
-
///
/// The backing vector for SIMD support.
///
@@ -40,7 +35,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Initializes a new instance of the struct.
///
/// The vector representing the x, y, z components.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieXyz(Vector3 vector)
: this()
{
@@ -78,18 +72,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -128,6 +112,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
@@ -136,16 +121,12 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "CieXyz [ Empty ]";
- }
-
- return $"CieXyz [ X={this.X:#0.##}, Y={this.Y:#0.##}, Z={this.Z:#0.##} ]";
+ return this.Equals(default)
+ ? "CieXyz [ Empty ]"
+ : $"CieXyz [ X={this.X:#0.##}, Y={this.Y:#0.##}, Z={this.Z:#0.##} ]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is CieXyz other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs
index 989d512bb..2702d4ba3 100644
--- a/src/ImageSharp/ColorSpaces/Cmyk.cs
+++ b/src/ImageSharp/ColorSpaces/Cmyk.cs
@@ -13,11 +13,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
internal readonly struct Cmyk : IEquatable, IAlmostEquatable
{
- ///
- /// Represents a that has C, M, Y, and K values set to zero.
- ///
- public static readonly Cmyk Empty = default;
-
///
/// The backing vector for SIMD support.
///
@@ -87,12 +82,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.W;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
/// Compares two objects for equality.
///
@@ -130,6 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
@@ -138,16 +128,12 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "Cmyk [Empty]";
- }
-
- return $"Cmyk [ C={this.C:#0.##}, M={this.M:#0.##}, Y={this.Y:#0.##}, K={this.K:#0.##}]";
+ return this.Equals(default)
+ ? "Cmyk [Empty]"
+ : $"Cmyk [ C={this.C:#0.##}, M={this.M:#0.##}, Y={this.Y:#0.##}, K={this.K:#0.##}]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is Cmyk other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs
index 4bb537aeb..e2c1308fa 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs
@@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The color to adapt
/// The white point to adapt for
/// The adapted color
- public CieXyz Adapt(CieXyz color, CieXyz sourceWhitePoint)
+ public CieXyz Adapt(in CieXyz color, in CieXyz sourceWhitePoint)
{
if (!this.IsChromaticAdaptationPerformed)
{
@@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to adapt
/// The adapted color
- public CieLab Adapt(CieLab color)
+ public CieLab Adapt(in CieLab color)
{
if (!this.IsChromaticAdaptationPerformed)
{
@@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to adapt
/// The adapted color
- public CieLch Adapt(CieLch color)
+ public CieLch Adapt(in CieLch color)
{
if (!this.IsChromaticAdaptationPerformed)
{
@@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to adapt
/// The adapted color
- public CieLchuv Adapt(CieLchuv color)
+ public CieLchuv Adapt(in CieLchuv color)
{
if (!this.IsChromaticAdaptationPerformed)
{
@@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to adapt
/// The adapted color
- public CieLuv Adapt(CieLuv color)
+ public CieLuv Adapt(in CieLuv color)
{
if (!this.IsChromaticAdaptationPerformed)
{
@@ -117,7 +117,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to adapt
/// The adapted color
- public HunterLab Adapt(HunterLab color)
+ public HunterLab Adapt(in HunterLab color)
{
if (!this.IsChromaticAdaptationPerformed)
{
@@ -138,7 +138,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to adapt
/// The adapted color
- public LinearRgb Adapt(LinearRgb color)
+ public LinearRgb Adapt(in LinearRgb color)
{
if (!this.IsChromaticAdaptationPerformed)
{
@@ -167,7 +167,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to adapt
/// The adapted color
- public Rgb Adapt(Rgb color)
+ public Rgb Adapt(in Rgb color)
{
LinearRgb linearInput = this.ToLinearRgb(color);
LinearRgb linearOutput = this.Adapt(linearInput);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
index 16e3ec707..1cead3001 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
@@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(CieLch color)
+ public CieLab ToCieLab(in CieLch color)
{
// Conversion (perserving white point)
CieLab unadapted = CieLchToCieLabConverter.Convert(color);
@@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(CieLchuv color)
+ public CieLab ToCieLab(in CieLchuv color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
@@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(CieLuv color)
+ public CieLab ToCieLab(in CieLuv color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
@@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(CieXyy color)
+ public CieLab ToCieLab(in CieXyy color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
@@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(CieXyz color)
+ public CieLab ToCieLab(in CieXyz color)
{
// Adaptation
CieXyz adapted = !this.WhitePoint.Equals(this.TargetLabWhitePoint) && this.IsChromaticAdaptationPerformed
@@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(Cmyk color)
+ public CieLab ToCieLab(in Cmyk color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
@@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(Hsl color)
+ public CieLab ToCieLab(in Hsl color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
@@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(Hsv color)
+ public CieLab ToCieLab(in Hsv color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
@@ -123,7 +123,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(HunterLab color)
+ public CieLab ToCieLab(in HunterLab color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
@@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(Lms color)
+ public CieLab ToCieLab(in Lms color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
@@ -145,7 +145,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(LinearRgb color)
+ public CieLab ToCieLab(in LinearRgb color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
@@ -156,7 +156,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(Rgb color)
+ public CieLab ToCieLab(in Rgb color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
@@ -167,7 +167,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLab ToCieLab(YCbCr color)
+ public CieLab ToCieLab(in YCbCr color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
index b13580209..cbefc5ac5 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
@@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(CieLab color)
+ public CieLch ToCieLch(in CieLab color)
{
// Adaptation
CieLab adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color;
@@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(CieLchuv color)
+ public CieLch ToCieLch(in CieLchuv color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
@@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(CieLuv color)
+ public CieLch ToCieLch(in CieLuv color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
@@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(CieXyy color)
+ public CieLch ToCieLch(in CieXyy color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
@@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(CieXyz color)
+ public CieLch ToCieLch(in CieXyz color)
{
CieLab labColor = this.ToCieLab(color);
return this.ToCieLch(labColor);
@@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(Cmyk color)
+ public CieLch ToCieLch(in Cmyk color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
@@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(Hsl color)
+ public CieLch ToCieLch(in Hsl color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
@@ -100,7 +100,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(Hsv color)
+ public CieLch ToCieLch(in Hsv color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
@@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(HunterLab color)
+ public CieLch ToCieLch(in HunterLab color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
@@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(LinearRgb color)
+ public CieLch ToCieLch(in LinearRgb color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
@@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(Lms color)
+ public CieLch ToCieLch(in Lms color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
@@ -144,7 +144,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(Rgb color)
+ public CieLch ToCieLch(in Rgb color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
@@ -155,7 +155,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLch ToCieLch(YCbCr color)
+ public CieLch ToCieLch(in YCbCr color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
index a5b5220b9..a44541bdb 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
@@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(CieLab color)
+ public CieLchuv ToCieLchuv(in CieLab color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
@@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(CieLch color)
+ public CieLchuv ToCieLchuv(in CieLch color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
@@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(CieLuv color)
+ public CieLchuv ToCieLchuv(in CieLuv color)
{
// Adaptation
CieLuv adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color;
@@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(CieXyy color)
+ public CieLchuv ToCieLchuv(in CieXyy color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
@@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(CieXyz color)
+ public CieLchuv ToCieLchuv(in CieXyz color)
{
CieLab labColor = this.ToCieLab(color);
return this.ToCieLchuv(labColor);
@@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(Cmyk color)
+ public CieLchuv ToCieLchuv(in Cmyk color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
@@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(Hsl color)
+ public CieLchuv ToCieLchuv(in Hsl color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
@@ -100,7 +100,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(Hsv color)
+ public CieLchuv ToCieLchuv(in Hsv color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
@@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(HunterLab color)
+ public CieLchuv ToCieLchuv(in HunterLab color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
@@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(LinearRgb color)
+ public CieLchuv ToCieLchuv(in LinearRgb color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
@@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(Lms color)
+ public CieLchuv ToCieLchuv(in Lms color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
@@ -155,7 +155,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLchuv ToCieLchuv(YCbCr color)
+ public CieLchuv ToCieLchuv(in YCbCr color)
{
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
index 7260a818f..36e6501a5 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
@@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(CieLab color)
+ public CieLuv ToCieLuv(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
@@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(CieLch color)
+ public CieLuv ToCieLuv(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
@@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(CieLchuv color)
+ public CieLuv ToCieLuv(in CieLchuv color)
{
// Conversion (perserving white point)
CieLuv unadapted = CieLchuvToCieLuvConverter.Convert(color);
@@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(CieXyy color)
+ public CieLuv ToCieLuv(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
@@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(CieXyz color)
+ public CieLuv ToCieLuv(in CieXyz color)
{
// Adaptation
CieXyz adapted = !this.WhitePoint.Equals(this.TargetLabWhitePoint) && this.IsChromaticAdaptationPerformed
@@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(Cmyk color)
+ public CieLuv ToCieLuv(in Cmyk color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
@@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(Hsl color)
+ public CieLuv ToCieLuv(in Hsl color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
@@ -110,7 +110,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(Hsv color)
+ public CieLuv ToCieLuv(in Hsv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
@@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(HunterLab color)
+ public CieLuv ToCieLuv(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
@@ -132,7 +132,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(Lms color)
+ public CieLuv ToCieLuv(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
@@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(LinearRgb color)
+ public CieLuv ToCieLuv(in LinearRgb color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
@@ -154,7 +154,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(Rgb color)
+ public CieLuv ToCieLuv(in Rgb color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
@@ -165,7 +165,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieLuv ToCieLuv(YCbCr color)
+ public CieLuv ToCieLuv(in YCbCr color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs
index 5f6aaea6b..25a9f75a4 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(CieLab color)
+ public CieXyy ToCieXyy(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(CieLch color)
+ public CieXyy ToCieXyy(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
@@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(CieLchuv color)
+ public CieXyy ToCieXyy(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(CieLuv color)
+ public CieXyy ToCieXyy(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(CieXyz color)
+ public CieXyy ToCieXyy(in CieXyz color)
{
return CieXyzAndCieXyyConverter.Convert(color);
}
@@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(Cmyk color)
+ public CieXyy ToCieXyy(in Cmyk color)
{
var xyzColor = this.ToCieXyz(color);
@@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(Hsv color)
+ public CieXyy ToCieXyy(in Hsv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(HunterLab color)
+ public CieXyy ToCieXyy(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
@@ -123,7 +123,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(LinearRgb color)
+ public CieXyy ToCieXyy(in LinearRgb color)
{
var xyzColor = this.ToCieXyz(color);
@@ -135,7 +135,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(Lms color)
+ public CieXyy ToCieXyy(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
@@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(Rgb color)
+ public CieXyy ToCieXyy(in Rgb color)
{
var xyzColor = this.ToCieXyz(color);
@@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(YCbCr color)
+ public CieXyy ToCieXyy(in YCbCr color)
{
var xyzColor = this.ToCieXyz(color);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs
index cd3f7f3c8..f4f28401f 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs
@@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(CieLab color)
+ public CieXyz ToCieXyz(in CieLab color)
{
// Conversion
CieXyz unadapted = CieLabToCieXyzConverter.Convert(color);
@@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(CieLch color)
+ public CieXyz ToCieXyz(in CieLch color)
{
// Conversion to Lab
CieLab labColor = CieLchToCieLabConverter.Convert(color);
@@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(CieLchuv color)
+ public CieXyz ToCieXyz(in CieLchuv color)
{
// Conversion to Luv
CieLuv luvColor = CieLchuvToCieLuvConverter.Convert(color);
@@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(CieLuv color)
+ public CieXyz ToCieXyz(in CieLuv color)
{
// Conversion
CieXyz unadapted = CieLuvToCieXyzConverter.Convert(color);
@@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(CieXyy color)
+ public CieXyz ToCieXyz(in CieXyy color)
{
// Conversion
return CieXyzAndCieXyyConverter.Convert(color);
@@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(Cmyk color)
+ public CieXyz ToCieXyz(in Cmyk color)
{
// Conversion
var rgb = this.ToRgb(color);
@@ -114,7 +114,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(Hsl color)
+ public CieXyz ToCieXyz(in Hsl color)
{
// Conversion
var rgb = this.ToRgb(color);
@@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(Hsv color)
+ public CieXyz ToCieXyz(in Hsv color)
{
// Conversion
var rgb = this.ToRgb(color);
@@ -140,7 +140,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(HunterLab color)
+ public CieXyz ToCieXyz(in HunterLab color)
{
// Conversion
CieXyz unadapted = HunterLabToCieXyzConverter.Convert(color);
@@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(LinearRgb color)
+ public CieXyz ToCieXyz(in LinearRgb color)
{
// Conversion
LinearRgbToCieXyzConverter converter = this.GetLinearRgbToCieXyzConverter(color.WorkingSpace);
@@ -175,7 +175,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(Lms color)
+ public CieXyz ToCieXyz(in Lms color)
{
// Conversion
return this.cachedCieXyzAndLmsConverter.Convert(color);
@@ -186,7 +186,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(Rgb color)
+ public CieXyz ToCieXyz(in Rgb color)
{
// Conversion
LinearRgb linear = RgbToLinearRgbConverter.Convert(color);
@@ -198,7 +198,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(YCbCr color)
+ public CieXyz ToCieXyz(in YCbCr color)
{
// Conversion
var rgb = this.ToRgb(color);
@@ -211,7 +211,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The source working space
/// The
- private LinearRgbToCieXyzConverter GetLinearRgbToCieXyzConverter(IRgbWorkingSpace workingSpace)
+ private LinearRgbToCieXyzConverter GetLinearRgbToCieXyzConverter(RgbWorkingSpace workingSpace)
{
if (this.linearRgbToCieXyzConverter != null && this.linearRgbToCieXyzConverter.SourceWorkingSpace.Equals(workingSpace))
{
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
index 708c2eac0..1e403828a 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(CieLab color)
+ public Cmyk ToCmyk(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(CieLch color)
+ public Cmyk ToCmyk(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
@@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(CieLchuv color)
+ public Cmyk ToCmyk(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(CieLuv color)
+ public Cmyk ToCmyk(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(CieXyy color)
+ public Cmyk ToCmyk(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
@@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(CieXyz color)
+ public Cmyk ToCmyk(in CieXyz color)
{
var rgb = this.ToRgb(color);
@@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(Hsl color)
+ public Cmyk ToCmyk(in Hsl color)
{
var rgb = this.ToRgb(color);
@@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(Hsv color)
+ public Cmyk ToCmyk(in Hsv color)
{
var rgb = this.ToRgb(color);
@@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(HunterLab color)
+ public Cmyk ToCmyk(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
@@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(LinearRgb color)
+ public Cmyk ToCmyk(in LinearRgb color)
{
var rgb = this.ToRgb(color);
@@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(Lms color)
+ public Cmyk ToCmyk(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
@@ -149,7 +149,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(Rgb color)
+ public Cmyk ToCmyk(in Rgb color)
{
return CmykAndRgbConverter.Convert(color);
}
@@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Cmyk ToCmyk(YCbCr color)
+ public Cmyk ToCmyk(in YCbCr color)
{
var rgb = this.ToRgb(color);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
index 909658a06..78f8c36fb 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(CieLab color)
+ public Hsl ToHsl(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(CieLch color)
+ public Hsl ToHsl(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
@@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(CieLchuv color)
+ public Hsl ToHsl(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(CieLuv color)
+ public Hsl ToHsl(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(CieXyy color)
+ public Hsl ToHsl(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
@@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(CieXyz color)
+ public Hsl ToHsl(in CieXyz color)
{
var rgb = this.ToRgb(color);
@@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(Cmyk color)
+ public Hsl ToHsl(in Cmyk color)
{
var rgb = this.ToRgb(color);
@@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(Hsv color)
+ public Hsl ToHsl(in Hsv color)
{
var rgb = this.ToRgb(color);
@@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(HunterLab color)
+ public Hsl ToHsl(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
@@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(LinearRgb color)
+ public Hsl ToHsl(in LinearRgb color)
{
var rgb = this.ToRgb(color);
@@ -149,7 +149,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(Rgb color)
+ public Hsl ToHsl(in Rgb color)
{
return HslAndRgbConverter.Convert(color);
}
@@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsl ToHsl(YCbCr color)
+ public Hsl ToHsl(in YCbCr color)
{
var rgb = this.ToRgb(color);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs
index 0aa644567..3edd72c59 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(CieLab color)
+ public Hsv ToHsv(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(CieLch color)
+ public Hsv ToHsv(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
@@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(CieLchuv color)
+ public Hsv ToHsv(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(CieLuv color)
+ public Hsv ToHsv(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(CieXyy color)
+ public Hsv ToHsv(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
@@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(CieXyz color)
+ public Hsv ToHsv(in CieXyz color)
{
var rgb = this.ToRgb(color);
@@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(Cmyk color)
+ public Hsv ToHsv(in Cmyk color)
{
var rgb = this.ToRgb(color);
@@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(Hsl color)
+ public Hsv ToHsv(in Hsl color)
{
var rgb = this.ToRgb(color);
@@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(HunterLab color)
+ public Hsv ToHsv(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
@@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(LinearRgb color)
+ public Hsv ToHsv(in LinearRgb color)
{
var rgb = this.ToRgb(color);
@@ -149,7 +149,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(Rgb color)
+ public Hsv ToHsv(in Rgb color)
{
return HsvAndRgbConverter.Convert(color);
}
@@ -159,7 +159,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Hsv ToHsv(YCbCr color)
+ public Hsv ToHsv(in YCbCr color)
{
var rgb = this.ToRgb(color);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs
index 880a91551..f3a64164b 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs
@@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(CieLab color)
+ public HunterLab ToHunterLab(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(CieLch color)
+ public HunterLab ToHunterLab(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(CieLchuv color)
+ public HunterLab ToHunterLab(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(CieLuv color)
+ public HunterLab ToHunterLab(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(CieXyy color)
+ public HunterLab ToHunterLab(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(CieXyz color)
+ public HunterLab ToHunterLab(in CieXyz color)
{
// Adaptation
CieXyz adapted = !this.WhitePoint.Equals(this.TargetHunterLabWhitePoint) && this.IsChromaticAdaptationPerformed
@@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(Cmyk color)
+ public HunterLab ToHunterLab(in Cmyk color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(Hsl color)
+ public HunterLab ToHunterLab(in Hsl color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(Hsv color)
+ public HunterLab ToHunterLab(in Hsv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -119,7 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(LinearRgb color)
+ public HunterLab ToHunterLab(in LinearRgb color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -130,7 +130,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(Lms color)
+ public HunterLab ToHunterLab(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(Rgb color)
+ public HunterLab ToHunterLab(in Rgb color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
@@ -152,7 +152,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(YCbCr color)
+ public HunterLab ToHunterLab(in YCbCr color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
index 92d2cd861..5fdde5c75 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
@@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(CieLab color)
+ public LinearRgb ToLinearRgb(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
@@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(CieLch color)
+ public LinearRgb ToLinearRgb(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
@@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(CieLchuv color)
+ public LinearRgb ToLinearRgb(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
@@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(CieLuv color)
+ public LinearRgb ToLinearRgb(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
@@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(CieXyy color)
+ public LinearRgb ToLinearRgb(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
@@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(CieXyz color)
+ public LinearRgb ToLinearRgb(in CieXyz color)
{
// Adaptation
CieXyz adapted = this.TargetRgbWorkingSpace.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed
@@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(Cmyk color)
+ public LinearRgb ToLinearRgb(in Cmyk color)
{
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
@@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(Hsl color)
+ public LinearRgb ToLinearRgb(in Hsl color)
{
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
@@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(Hsv color)
+ public LinearRgb ToLinearRgb(in Hsv color)
{
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
@@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(HunterLab color)
+ public LinearRgb ToLinearRgb(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
@@ -135,7 +135,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(Lms color)
+ public LinearRgb ToLinearRgb(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
@@ -146,7 +146,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(Rgb color)
+ public LinearRgb ToLinearRgb(in Rgb color)
{
// Conversion
return RgbToLinearRgbConverter.Convert(color);
@@ -157,7 +157,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(YCbCr color)
+ public LinearRgb ToLinearRgb(in YCbCr color)
{
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
@@ -168,7 +168,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The target working space
/// The
- private CieXyzToLinearRgbConverter GetCieXyxToLinearRgbConverter(IRgbWorkingSpace workingSpace)
+ private CieXyzToLinearRgbConverter GetCieXyxToLinearRgbConverter(RgbWorkingSpace workingSpace)
{
if (this.cieXyzToLinearRgbConverter != null && this.cieXyzToLinearRgbConverter.TargetWorkingSpace.Equals(workingSpace))
{
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs
index 1de0d70d3..3293e2f4a 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs
@@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(CieLab color)
+ public Lms ToLms(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(CieLch color)
+ public Lms ToLms(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(CieLchuv color)
+ public Lms ToLms(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(CieLuv color)
+ public Lms ToLms(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(CieXyy color)
+ public Lms ToLms(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(CieXyz color)
+ public Lms ToLms(in CieXyz color)
{
return this.cachedCieXyzAndLmsConverter.Convert(color);
}
@@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(Cmyk color)
+ public Lms ToLms(in Cmyk color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(Hsl color)
+ public Lms ToLms(in Hsl color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(Hsv color)
+ public Lms ToLms(in Hsv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(HunterLab color)
+ public Lms ToLms(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(LinearRgb color)
+ public Lms ToLms(in LinearRgb color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -135,7 +135,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(Rgb color)
+ public Lms ToLms(in Rgb color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
@@ -146,7 +146,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Lms ToLms(YCbCr color)
+ public Lms ToLms(in YCbCr color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
index b609934e9..5bfb6ee05 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(CieLab color)
+ public Rgb ToRgb(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
@@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(CieLch color)
+ public Rgb ToRgb(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
@@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(CieLchuv color)
+ public Rgb ToRgb(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
@@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(CieLuv color)
+ public Rgb ToRgb(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
@@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(CieXyy color)
+ public Rgb ToRgb(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
@@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(CieXyz color)
+ public Rgb ToRgb(in CieXyz color)
{
// Conversion
var linear = this.ToLinearRgb(color);
@@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(Cmyk color)
+ public Rgb ToRgb(in Cmyk color)
{
// Conversion
return CmykAndRgbConverter.Convert(color);
@@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(Hsv color)
+ public Rgb ToRgb(in Hsv color)
{
// Conversion
return HsvAndRgbConverter.Convert(color);
@@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(Hsl color)
+ public Rgb ToRgb(in Hsl color)
{
// Conversion
return HslAndRgbConverter.Convert(color);
@@ -119,7 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(HunterLab color)
+ public Rgb ToRgb(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
@@ -130,7 +130,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(LinearRgb color)
+ public Rgb ToRgb(in LinearRgb color)
{
// Conversion
return LinearRgbToRgbConverter.Convert(color);
@@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(Lms color)
+ public Rgb ToRgb(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
@@ -152,7 +152,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public Rgb ToRgb(YCbCr color)
+ public Rgb ToRgb(in YCbCr color)
{
// Conversion
Rgb rgb = YCbCrAndRgbConverter.Convert(color);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
index 97d9f3818..b7fe34f41 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(CieLab color)
+ public YCbCr ToYCbCr(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(CieLch color)
+ public YCbCr ToYCbCr(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
@@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(CieLchuv color)
+ public YCbCr ToYCbCr(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(CieLuv color)
+ public YCbCr ToYCbCr(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(CieXyy color)
+ public YCbCr ToYCbCr(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
@@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(CieXyz color)
+ public YCbCr ToYCbCr(in CieXyz color)
{
var rgb = this.ToRgb(color);
@@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(Cmyk color)
+ public YCbCr ToYCbCr(in Cmyk color)
{
var rgb = this.ToRgb(color);
@@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(Hsl color)
+ public YCbCr ToYCbCr(in Hsl color)
{
var rgb = this.ToRgb(color);
@@ -113,7 +113,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(Hsv color)
+ public YCbCr ToYCbCr(in Hsv color)
{
var rgb = this.ToRgb(color);
@@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(HunterLab color)
+ public YCbCr ToYCbCr(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
@@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(LinearRgb color)
+ public YCbCr ToYCbCr(in LinearRgb color)
{
var rgb = this.ToRgb(color);
@@ -149,7 +149,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(Lms color)
+ public YCbCr ToYCbCr(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
@@ -161,7 +161,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The color to convert.
/// The
- public YCbCr ToYCbCr(Rgb color)
+ public YCbCr ToYCbCr(in Rgb color)
{
return YCbCrAndRgbConverter.Convert(color);
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs
index f86f50538..7142ab0e8 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs
@@ -2,8 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
-using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.LmsColorSapce;
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
@@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// Gets or sets the target working space used *when creating* RGB colors. (RGB colors on the input already contain the working space information)
/// Defaults to: .
///
- public IRgbWorkingSpace TargetRgbWorkingSpace { get; set; }
+ public RgbWorkingSpace TargetRgbWorkingSpace { get; set; }
///
/// Gets or sets the chromatic adaptation method used. When null, no adaptation will be performed.
diff --git a/src/ImageSharp/ColorSpaces/Conversion/IChromaticAdaptation.cs b/src/ImageSharp/ColorSpaces/Conversion/IChromaticAdaptation.cs
index c5d91f9a0..dfba4b926 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/IChromaticAdaptation.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/IChromaticAdaptation.cs
@@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using SixLabors.ImageSharp.ColorSpaces;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -20,6 +18,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The source white point.
/// The target white point.
/// The
- CieXyz Transform(CieXyz sourceColor, CieXyz sourceWhitePoint, CieXyz targetWhitePoint);
+ CieXyz Transform(in CieXyz sourceColor, in CieXyz sourceWhitePoint, in CieXyz targetWhitePoint);
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs b/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs
index 9ef24b38a..009b91c40 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/IColorConversion.cs
@@ -8,13 +8,15 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
/// The input color type.
/// The result color type.
- internal interface IColorConversion
+ internal interface IColorConversion
+ where T : struct
+ where TResult : struct
{
///
/// Performs the conversion from the input to an instance of the output type.
///
/// The input color instance.
/// The converted result
- TResult Convert(T input);
+ TResult Convert(in T input);
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs
index 53d9c927a..ca8f23c56 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColor
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieXyz Convert(CieLab input)
+ public CieXyz Convert(in CieLab input)
{
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html
float l = input.L, a = input.A, b = input.B;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs
index 454601b88..0fe52e6af 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs
@@ -33,15 +33,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLabColor
///
/// Gets the target reference whitepoint. When not set, is used.
///
- public CieXyz LabWhitePoint
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
+ public CieXyz LabWhitePoint { get; }
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieLab Convert(CieXyz input)
+ public CieLab Convert(in CieXyz input)
{
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
float wx = this.LabWhitePoint.X, wy = this.LabWhitePoint.Y, wz = this.LabWhitePoint.Z;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs
index 0b1ebae0e..061d04493 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CIeLchToCieLabConverter.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColor
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieLab Convert(CieLch input)
+ public CieLab Convert(in CieLch input)
{
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs
index ec73a830f..105fb2aa1 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLch/CieLabToCieLchConverter.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchColor
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieLch Convert(CieLab input)
+ public CieLch Convert(in CieLab input)
{
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs
index eb523806a..7f8e0fc1e 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLchuvToCieLuvConverter.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvCol
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieLuv Convert(CieLchuv input)
+ public CieLuv Convert(in CieLchuv input)
{
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs
index 7a9dd2c6a..7a23e2da1 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuv/CieLuvToCieLchuvConverter.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLchuvCol
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieLchuv Convert(CieLuv input)
+ public CieLchuv Convert(in CieLuv input)
{
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs
index 7a264fdfe..cd2ec488d 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieLuvToCieXyzConverter.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieXyz Convert(CieLuv input)
+ public CieXyz Convert(in CieLuv input)
{
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Luv_to_XYZ.html
float l = input.L, u = input.U, v = input.V;
@@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor
/// The whitepoint
/// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static float ComputeU0(CieXyz input)
+ private static float ComputeU0(in CieXyz input)
{
return (4 * input.X) / (input.X + (15 * input.Y) + (3 * input.Z));
}
@@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor
/// The whitepoint
/// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static float ComputeV0(CieXyz input)
+ private static float ComputeV0(in CieXyz input)
{
return (9 * input.Y) / (input.X + (15 * input.Y) + (3 * input.Z));
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs
index e1c5dde4f..c34a2455a 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuv/CieXyzToCieLuvConverter.cs
@@ -34,15 +34,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor
///
/// Gets the target reference whitepoint. When not set, is used.
///
- public CieXyz LuvWhitePoint
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
+ public CieXyz LuvWhitePoint { get; }
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieLuv Convert(CieXyz input)
+ public CieLuv Convert(in CieXyz input)
{
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Luv.html
float yr = input.Y / this.LuvWhitePoint.Y;
@@ -80,7 +76,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor
/// The whitepoint
/// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static float ComputeUp(CieXyz input)
+ private static float ComputeUp(in CieXyz input)
{
return (4 * input.X) / (input.X + (15 * input.Y) + (3 * input.Z));
}
@@ -90,7 +86,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieLuvColor
///
/// The whitepoint
/// The
- private static float ComputeVp(CieXyz input)
+ private static float ComputeVp(in CieXyz input)
{
return (9 * input.Y) / (input.X + (15 * input.Y) + (3 * input.Z));
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs
index 7dfc577dc..d15f7360e 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs
@@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieXyyColor
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieXyy Convert(CieXyz input)
+ public CieXyy Convert(in CieXyz input)
{
float x = input.X / (input.X + input.Y + input.Z);
float y = input.Y / (input.X + input.Y + input.Z);
@@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CieXyyColor
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieXyz Convert(CieXyy input)
+ public CieXyz Convert(in CieXyy input)
{
if (MathF.Abs(input.Y) < Constants.Epsilon)
{
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs
index ed86ec9a5..869178370 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CmykColorSa
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Rgb Convert(Cmyk input)
+ public Rgb Convert(in Cmyk input)
{
float r = (1F - input.C) * (1F - input.K);
float g = (1F - input.M) * (1F - input.K);
@@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.CmykColorSa
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Cmyk Convert(Rgb input)
+ public Cmyk Convert(in Rgb input)
{
// To CMYK
float c = 1F - input.R;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs
index 7983b6ce4..1bec834a8 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs
@@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HslColorSap
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Rgb Convert(Hsl input)
+ public Rgb Convert(in Hsl input)
{
float rangedH = input.H / 360F;
float r = 0;
@@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HslColorSap
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Hsl Convert(Rgb input)
+ public Hsl Convert(in Rgb input)
{
float r = input.R;
float g = input.G;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs
index c46d8f26b..f2c4cc188 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Hsv/HsvAndRgbConverter.cs
@@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HsvColorSap
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Rgb Convert(Hsv input)
+ public Rgb Convert(in Hsv input)
{
float s = input.S;
float v = input.V;
@@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HsvColorSap
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Hsv Convert(Rgb input)
+ public Hsv Convert(in Rgb input)
{
float r = input.R;
float g = input.G;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs
index 58363ea2b..af681e981 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/CieXyzToHunterLabConverter.cs
@@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HunterLabCo
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public HunterLab Convert(CieXyz input)
+ public HunterLab Convert(in CieXyz input)
{
// Conversion algorithm described here: http://en.wikipedia.org/wiki/Lab_color_space#Hunter_Lab
float x = input.X, y = input.Y, z = input.Z;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs
index 228d7362b..eba9fe1c8 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLab/HunterLabToCieXyzConverter.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.HunterLabCo
{
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieXyz Convert(HunterLab input)
+ public CieXyz Convert(in HunterLab input)
{
// Conversion algorithm described here: http://en.wikipedia.org/wiki/Lab_color_space#Hunter_Lab
float l = input.L, a = input.A, b = input.B;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs
index 5241b62f9..c29496c37 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs
@@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.LmsColorSap
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Lms Convert(CieXyz input)
+ public Lms Convert(in CieXyz input)
{
Vector3 vector = Vector3.Transform(input.Vector, this.transformationMatrix);
return new Lms(vector);
@@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.LmsColorSap
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public CieXyz Convert(Lms input)
+ public CieXyz Convert(in Lms input)
{
Vector3 vector = Vector3.Transform(input.Vector, this.inverseTransformationMatrix);
return new CieXyz(vector);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs
index 2f52c2074..217698c23 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/CieXyzToLinearRgbConverter.cs
@@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
/// Color converter between CieXyz and LinearRgb
///
- internal class CieXyzToLinearRgbConverter : LinearRgbAndCieXyzConverterBase, IColorConversion
+ internal sealed class CieXyzToLinearRgbConverter : LinearRgbAndCieXyzConverterBase, IColorConversion
{
private readonly Matrix4x4 conversionMatrix;
@@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
/// Initializes a new instance of the class.
///
/// The target working space.
- public CieXyzToLinearRgbConverter(IRgbWorkingSpace workingSpace)
+ public CieXyzToLinearRgbConverter(RgbWorkingSpace workingSpace)
{
this.TargetWorkingSpace = workingSpace;
this.conversionMatrix = GetRgbToCieXyzMatrix(workingSpace);
@@ -33,10 +33,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
/// Gets the target working space
///
- public IRgbWorkingSpace TargetWorkingSpace { get; }
+ public RgbWorkingSpace TargetWorkingSpace { get; }
///
- public LinearRgb Convert(CieXyz input)
+ public LinearRgb Convert(in CieXyz input)
{
Matrix4x4.Invert(this.conversionMatrix, out Matrix4x4 inverted);
Vector3 vector = Vector3.Transform(input.Vector, inverted);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs
index a0da2bc26..bc11c51b5 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs
@@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
/// The Rgb working space.
/// The based on the chromaticity and working space.
- public static Matrix4x4 GetRgbToCieXyzMatrix(IRgbWorkingSpace workingSpace)
+ public static Matrix4x4 GetRgbToCieXyzMatrix(RgbWorkingSpace workingSpace)
{
DebugGuard.NotNull(workingSpace, nameof(workingSpace));
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs
index 0746c78c3..e597b66af 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs
@@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
/// Color converter between LinearRgb and CieXyz
///
- internal class LinearRgbToCieXyzConverter : LinearRgbAndCieXyzConverterBase, IColorConversion
+ internal sealed class LinearRgbToCieXyzConverter : LinearRgbAndCieXyzConverterBase, IColorConversion
{
private readonly Matrix4x4 conversionMatrix;
@@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
/// Initializes a new instance of the class.
///
/// The target working space.
- public LinearRgbToCieXyzConverter(IRgbWorkingSpace workingSpace)
+ public LinearRgbToCieXyzConverter(RgbWorkingSpace workingSpace)
{
this.SourceWorkingSpace = workingSpace;
this.conversionMatrix = GetRgbToCieXyzMatrix(workingSpace);
@@ -33,10 +33,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
/// Gets the source working space
///
- public IRgbWorkingSpace SourceWorkingSpace { get; }
+ public RgbWorkingSpace SourceWorkingSpace { get; }
///
- public CieXyz Convert(LinearRgb input)
+ public CieXyz Convert(in LinearRgb input)
{
DebugGuard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal.");
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs
index 3b70c02af..34873c1f5 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs
@@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
internal class LinearRgbToRgbConverter : IColorConversion
{
///
- public Rgb Convert(LinearRgb input)
+ public Rgb Convert(in LinearRgb input)
{
Vector3 vector = input.Vector;
vector.X = input.WorkingSpace.Companding.Compress(vector.X);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs
index 8afe2ffa0..4359d666e 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs
@@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
{
///
/// Represents the chromaticity coordinates of RGB primaries.
- /// One of the specifiers of .
+ /// One of the specifiers of .
///
internal readonly struct RgbPrimariesChromaticityCoordinates : IEquatable
{
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs
index ed415df8c..4cc3d607f 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs
@@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
internal class RgbToLinearRgbConverter : IColorConversion
{
///
- public LinearRgb Convert(Rgb input)
+ public LinearRgb Convert(in Rgb input)
{
Vector3 vector = input.Vector;
vector.X = input.WorkingSpace.Companding.Expand(vector.X);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
index 530c01691..f4a79c744 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
@@ -4,12 +4,12 @@
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce
{
///
- /// Trivial implementation of
+ /// Trivial implementation of
///
- internal readonly struct RgbWorkingSpace : IRgbWorkingSpace
+ internal class RgbWorkingSpace
{
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the class.
///
/// The reference white point.
/// The function pair for converting to and back.
@@ -70,14 +70,12 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
return !Equals(left, right);
}
- ///
public override bool Equals(object obj)
{
return obj is RgbWorkingSpace other && this.Equals(other);
}
- ///
- public bool Equals(IRgbWorkingSpace other)
+ public bool Equals(RgbWorkingSpace other)
{
// TODO: Object.Equals for ICompanding will be slow.
return this.WhitePoint.Equals(other.WhitePoint)
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs
index 99149a592..e8d32572a 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCr/YCbCrAndRgbConverter.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.YCbCrColorS
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Rgb Convert(YCbCr input)
+ public Rgb Convert(in YCbCr input)
{
float y = input.Y;
float cb = input.Cb - 128F;
@@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.YCbCrColorS
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public YCbCr Convert(Rgb input)
+ public YCbCr Convert(in Rgb input)
{
Vector3 rgb = input.Vector * MaxBytes;
float r = rgb.X;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs b/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs
index 22ba5928e..0ab194af2 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs
@@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
///
- public CieXyz Transform(CieXyz sourceColor, CieXyz sourceWhitePoint, CieXyz targetWhitePoint)
+ public CieXyz Transform(in CieXyz sourceColor, in CieXyz sourceWhitePoint, in CieXyz targetWhitePoint)
{
if (sourceWhitePoint.Equals(targetWhitePoint))
{
diff --git a/src/ImageSharp/ColorSpaces/Hsl.cs b/src/ImageSharp/ColorSpaces/Hsl.cs
index 88b14fa97..8ed406753 100644
--- a/src/ImageSharp/ColorSpaces/Hsl.cs
+++ b/src/ImageSharp/ColorSpaces/Hsl.cs
@@ -14,12 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
internal readonly struct Hsl : IColorVector, IEquatable, IAlmostEquatable
{
///
- /// Represents a that has H, S, and L values set to zero.
- ///
- public static readonly Hsl Empty = default;
-
- ///
- /// Max range used for clamping
+ /// Max range used for clamping.
///
private static readonly Vector3 VectorMax = new Vector3(360, 1, 1);
@@ -80,18 +75,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -130,6 +115,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
@@ -138,16 +124,12 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "Hsl [ Empty ]";
- }
-
- return $"Hsl [ H={this.H:#0.##}, S={this.S:#0.##}, L={this.L:#0.##} ]";
+ return this.Equals(default)
+ ? "Hsl [ Empty ]"
+ : $"Hsl [ H={this.H:#0.##}, S={this.S:#0.##}, L={this.L:#0.##} ]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is Hsl other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/Hsv.cs b/src/ImageSharp/ColorSpaces/Hsv.cs
index 1f6c8d5eb..78a49097e 100644
--- a/src/ImageSharp/ColorSpaces/Hsv.cs
+++ b/src/ImageSharp/ColorSpaces/Hsv.cs
@@ -16,12 +16,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
internal readonly struct Hsv : IColorVector, IEquatable, IAlmostEquatable
{
///
- /// Represents a that has H, S, and V values set to zero.
- ///
- public static readonly Hsv Empty = default;
-
- ///
- /// Max range used for clamping
+ /// Max range used for clamping.
///
private static readonly Vector3 VectorMax = new Vector3(360, 1, 1);
@@ -82,18 +77,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Allows the implicit conversion of an instance of to a
@@ -182,6 +167,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
@@ -190,16 +176,12 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "Hsv [ Empty ]";
- }
-
- return $"Hsv [ H={this.H:#0.##}, S={this.S:#0.##}, V={this.V:#0.##} ]";
+ return this.Equals(default)
+ ? "Hsv [ Empty ]"
+ : $"Hsv [ H={this.H:#0.##}, S={this.S:#0.##}, V={this.V:#0.##} ]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is Hsv other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/HunterLab.cs b/src/ImageSharp/ColorSpaces/HunterLab.cs
index 4395d9d7c..44f31bc29 100644
--- a/src/ImageSharp/ColorSpaces/HunterLab.cs
+++ b/src/ImageSharp/ColorSpaces/HunterLab.cs
@@ -20,11 +20,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public static readonly CieXyz DefaultWhitePoint = Illuminants.C;
- ///
- /// Represents a that has L, A, B values set to zero.
- ///
- public static readonly HunterLab Empty = default;
-
///
/// The backing vector for SIMD support.
///
@@ -115,18 +110,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -140,7 +125,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// True if the current left is equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(HunterLab left, HunterLab right)
{
return left.Equals(right);
@@ -165,29 +149,21 @@ namespace SixLabors.ImageSharp.ColorSpaces
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
- unchecked
- {
- int hashCode = this.WhitePoint.GetHashCode();
- hashCode = (hashCode * 397) ^ this.backingVector.GetHashCode();
- return hashCode;
- }
+ return HashHelpers.Combine(this.WhitePoint.GetHashCode(), this.backingVector.GetHashCode());
}
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "HunterLab [Empty]";
- }
-
- return $"HunterLab [ L={this.L:#0.##}, A={this.A:#0.##}, B={this.B:#0.##}]";
+ return this.Equals(default)
+ ? "HunterLab [Empty]"
+ : $"HunterLab [ L={this.L:#0.##}, A={this.A:#0.##}, B={this.B:#0.##}]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is HunterLab other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/ICompanding.cs b/src/ImageSharp/ColorSpaces/ICompanding.cs
index 2dfa575ed..053c8d17b 100644
--- a/src/ImageSharp/ColorSpaces/ICompanding.cs
+++ b/src/ImageSharp/ColorSpaces/ICompanding.cs
@@ -1,12 +1,14 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce;
+
namespace SixLabors.ImageSharp.ColorSpaces
{
///
- /// Pair of companding functions for .
+ /// Pair of companding functions for .
/// Used for conversion to and backwards.
- /// See also:
+ /// See also:
///
internal interface ICompanding
{
diff --git a/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs
deleted file mode 100644
index 156e94ed3..000000000
--- a/src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce;
-
-namespace SixLabors.ImageSharp.ColorSpaces
-{
- ///
- /// Encasulates the RGB working color space
- ///
- internal interface IRgbWorkingSpace : IEquatable
- {
- ///
- /// Gets the reference white of the color space
- ///
- CieXyz WhitePoint { get; }
-
- ///
- /// Gets the chromaticity coordinates of the primaries
- ///
- RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
-
- ///
- /// Gets the companding function associated with the RGB color system. Used for conversion to XYZ and backwards.
- ///
- ///
- ///
- ICompanding Companding { get; }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/LinearRgb.cs b/src/ImageSharp/ColorSpaces/LinearRgb.cs
index c721347be..aaf05e035 100644
--- a/src/ImageSharp/ColorSpaces/LinearRgb.cs
+++ b/src/ImageSharp/ColorSpaces/LinearRgb.cs
@@ -2,26 +2,21 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce;
namespace SixLabors.ImageSharp.ColorSpaces
{
///
- /// Represents an linear Rgb color with specified working space
+ /// Represents an linear Rgb color with specified working space
///
internal readonly struct LinearRgb : IColorVector, IEquatable, IAlmostEquatable
{
///
- /// Represents a that has R, G, and B values set to zero.
+ /// The default LinearRgb working space.
///
- public static readonly LinearRgb Empty = default;
-
- ///
- /// The default LinearRgb working space
- ///
- public static readonly IRgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb;
+ public static readonly RgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb;
///
/// The backing vector for SIMD support.
@@ -48,7 +43,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// The blue component ranging between 0 and 1.
/// The rgb working space.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public LinearRgb(float r, float g, float b, IRgbWorkingSpace workingSpace)
+ public LinearRgb(float r, float g, float b, RgbWorkingSpace workingSpace)
: this(new Vector3(r, g, b), workingSpace)
{
}
@@ -69,7 +64,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// The vector representing the r, g, b components.
/// The LinearRgb working space.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public LinearRgb(Vector3 vector, IRgbWorkingSpace workingSpace)
+ public LinearRgb(Vector3 vector, RgbWorkingSpace workingSpace)
: this()
{
// Clamp to 0-1 range.
@@ -110,20 +105,10 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Gets the LinearRgb color space
///
- public IRgbWorkingSpace WorkingSpace { get; }
-
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
+ public RgbWorkingSpace WorkingSpace { get; }
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -162,6 +147,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
@@ -170,16 +156,12 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "LinearRgb [ Empty ]";
- }
-
- return $"LinearRgb [ R={this.R:#0.##}, G={this.G:#0.##}, B={this.B:#0.##} ]";
+ return this.Equals(default)
+ ? "LinearRgb [ Empty ]"
+ : $"LinearRgb [ R={this.R:#0.##}, G={this.G:#0.##}, B={this.B:#0.##} ]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is LinearRgb other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/Lms.cs b/src/ImageSharp/ColorSpaces/Lms.cs
index e46249569..9b0331e0b 100644
--- a/src/ImageSharp/ColorSpaces/Lms.cs
+++ b/src/ImageSharp/ColorSpaces/Lms.cs
@@ -15,11 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
internal readonly struct Lms : IColorVector, IEquatable, IAlmostEquatable
{
- ///
- /// Represents a that has L, M, and S values set to zero.
- ///
- public static readonly Lms Empty = default;
-
///
/// The backing vector for SIMD support.
///
@@ -79,18 +74,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -137,16 +122,12 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "Lms [ Empty ]";
- }
-
- return $"Lms [ L={this.L:#0.##}, M={this.M:#0.##}, S={this.S:#0.##} ]";
+ return this.Equals(default)
+ ? "Lms [ Empty ]"
+ : $"Lms [ L={this.L:#0.##}, M={this.M:#0.##}, S={this.S:#0.##} ]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is Lms other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs
index 8cdf54ace..ccfa1760f 100644
--- a/src/ImageSharp/ColorSpaces/Rgb.cs
+++ b/src/ImageSharp/ColorSpaces/Rgb.cs
@@ -2,28 +2,22 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
-
+using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.ColorSpaces
{
///
- /// Represents an RGB color with specified working space
+ /// Represents an RGB color with specified working space
///
internal readonly struct Rgb : IColorVector, IEquatable, IAlmostEquatable
{
- ///
- /// Represents a that has R, G, and B values set to zero.
- ///
- public static readonly Rgb Empty = default;
-
///
/// The default rgb working space
///
- public static readonly IRgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb;
+ public static readonly RgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb;
///
/// The backing vector for SIMD support.
@@ -50,7 +44,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// The blue component ranging between 0 and 1.
/// The rgb working space.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Rgb(float r, float g, float b, IRgbWorkingSpace workingSpace)
+ public Rgb(float r, float g, float b, RgbWorkingSpace workingSpace)
: this(new Vector3(r, g, b), workingSpace)
{
}
@@ -71,7 +65,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// The vector representing the r, g, b components.
/// The rgb working space.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Rgb(Vector3 vector, IRgbWorkingSpace workingSpace)
+ public Rgb(Vector3 vector, RgbWorkingSpace workingSpace)
: this()
{
// Clamp to 0-1 range.
@@ -112,24 +106,10 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Gets the Rgb color space
///
- public IRgbWorkingSpace WorkingSpace
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
-
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
+ public RgbWorkingSpace WorkingSpace { get; }
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Allows the implicit conversion of an instance of to a
@@ -192,16 +172,12 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "Rgb [ Empty ]";
- }
-
- return $"Rgb [ R={this.R:#0.##}, G={this.G:#0.##}, B={this.B:#0.##} ]";
+ return this.Equals(default)
+ ? "Rgb [ Empty ]"
+ : $"Rgb [ R={this.R:#0.##}, G={this.G:#0.##}, B={this.B:#0.##} ]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is Rgb other && this.Equals(other);
diff --git a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs
index 098ca9a4a..978a35725 100644
--- a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs
+++ b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs
@@ -19,97 +19,97 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Uses proper companding function, according to:
///
///
- public static readonly IRgbWorkingSpace SRgb = new RgbWorkingSpace(Illuminants.D65, new SRgbCompanding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
+ public static readonly RgbWorkingSpace SRgb = new RgbWorkingSpace(Illuminants.D65, new SRgbCompanding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
///
/// Simplified sRgb working space (uses gamma companding instead of ).
/// See also .
///
- public static readonly IRgbWorkingSpace SRgbSimplified = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
+ public static readonly RgbWorkingSpace SRgbSimplified = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
///
- /// Rec. 709 (ITU-R Recommendation BT.709) working space
+ /// Rec. 709 (ITU-R Recommendation BT.709) working space.
///
- public static readonly IRgbWorkingSpace Rec709 = new RgbWorkingSpace(Illuminants.D65, new Rec709Companding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.64F, 0.33F), new CieXyChromaticityCoordinates(0.30F, 0.60F), new CieXyChromaticityCoordinates(0.15F, 0.06F)));
+ public static readonly RgbWorkingSpace Rec709 = new RgbWorkingSpace(Illuminants.D65, new Rec709Companding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.64F, 0.33F), new CieXyChromaticityCoordinates(0.30F, 0.60F), new CieXyChromaticityCoordinates(0.15F, 0.06F)));
///
- /// Rec. 2020 (ITU-R Recommendation BT.2020F) working space
+ /// Rec. 2020 (ITU-R Recommendation BT.2020F) working space.
///
- public static readonly IRgbWorkingSpace Rec2020 = new RgbWorkingSpace(Illuminants.D65, new Rec2020Companding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.708F, 0.292F), new CieXyChromaticityCoordinates(0.170F, 0.797F), new CieXyChromaticityCoordinates(0.131F, 0.046F)));
+ public static readonly RgbWorkingSpace Rec2020 = new RgbWorkingSpace(Illuminants.D65, new Rec2020Companding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.708F, 0.292F), new CieXyChromaticityCoordinates(0.170F, 0.797F), new CieXyChromaticityCoordinates(0.131F, 0.046F)));
///
- /// ECI Rgb v2 working space
+ /// ECI Rgb v2 working space.
///
- public static readonly IRgbWorkingSpace ECIRgbv2 = new RgbWorkingSpace(Illuminants.D50, new LCompanding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F)));
+ public static readonly RgbWorkingSpace ECIRgbv2 = new RgbWorkingSpace(Illuminants.D50, new LCompanding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F)));
///
- /// Adobe Rgb (1998) working space
+ /// Adobe Rgb (1998) working space.
///
- public static readonly IRgbWorkingSpace AdobeRgb1998 = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
+ public static readonly RgbWorkingSpace AdobeRgb1998 = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
///
- /// Apple sRgb working space
+ /// Apple sRgb working space.
///
- public static readonly IRgbWorkingSpace ApplesRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6250F, 0.3400F), new CieXyChromaticityCoordinates(0.2800F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F)));
+ public static readonly RgbWorkingSpace ApplesRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6250F, 0.3400F), new CieXyChromaticityCoordinates(0.2800F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F)));
///
- /// Best Rgb working space
+ /// Best Rgb working space.
///
- public static readonly IRgbWorkingSpace BestRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.2150F, 0.7750F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F)));
+ public static readonly RgbWorkingSpace BestRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.2150F, 0.7750F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F)));
///
- /// Beta Rgb working space
+ /// Beta Rgb working space.
///
- public static readonly IRgbWorkingSpace BetaRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6888F, 0.3112F), new CieXyChromaticityCoordinates(0.1986F, 0.7551F), new CieXyChromaticityCoordinates(0.1265F, 0.0352F)));
+ public static readonly RgbWorkingSpace BetaRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6888F, 0.3112F), new CieXyChromaticityCoordinates(0.1986F, 0.7551F), new CieXyChromaticityCoordinates(0.1265F, 0.0352F)));
///
- /// Bruce Rgb working space
+ /// Bruce Rgb working space.
///
- public static readonly IRgbWorkingSpace BruceRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2800F, 0.6500F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
+ public static readonly RgbWorkingSpace BruceRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2800F, 0.6500F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
///
- /// CIE Rgb working space
+ /// CIE Rgb working space.
///
- public static readonly IRgbWorkingSpace CIERgb = new RgbWorkingSpace(Illuminants.E, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.2740F, 0.7170F), new CieXyChromaticityCoordinates(0.1670F, 0.0090F)));
+ public static readonly RgbWorkingSpace CIERgb = new RgbWorkingSpace(Illuminants.E, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.2740F, 0.7170F), new CieXyChromaticityCoordinates(0.1670F, 0.0090F)));
///
- /// ColorMatch Rgb working space
+ /// ColorMatch Rgb working space.
///
- public static readonly IRgbWorkingSpace ColorMatchRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.2950F, 0.6050F), new CieXyChromaticityCoordinates(0.1500F, 0.0750F)));
+ public static readonly RgbWorkingSpace ColorMatchRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.2950F, 0.6050F), new CieXyChromaticityCoordinates(0.1500F, 0.0750F)));
///
- /// Don Rgb 4 working space
+ /// Don Rgb 4 working space.
///
- public static readonly IRgbWorkingSpace DonRgb4 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6960F, 0.3000F), new CieXyChromaticityCoordinates(0.2150F, 0.7650F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F)));
+ public static readonly RgbWorkingSpace DonRgb4 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6960F, 0.3000F), new CieXyChromaticityCoordinates(0.2150F, 0.7650F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F)));
///
- /// Ekta Space PS5 working space
+ /// Ekta Space PS5 working space.
///
- public static readonly IRgbWorkingSpace EktaSpacePS5 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6950F, 0.3050F), new CieXyChromaticityCoordinates(0.2600F, 0.7000F), new CieXyChromaticityCoordinates(0.1100F, 0.0050F)));
+ public static readonly RgbWorkingSpace EktaSpacePS5 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6950F, 0.3050F), new CieXyChromaticityCoordinates(0.2600F, 0.7000F), new CieXyChromaticityCoordinates(0.1100F, 0.0050F)));
///
- /// NTSC Rgb working space
+ /// NTSC Rgb working space.
///
- public static readonly IRgbWorkingSpace NTSCRgb = new RgbWorkingSpace(Illuminants.C, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F)));
+ public static readonly RgbWorkingSpace NTSCRgb = new RgbWorkingSpace(Illuminants.C, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F)));
///
- /// PAL/SECAM Rgb working space
+ /// PAL/SECAM Rgb working space.
///
- public static readonly IRgbWorkingSpace PALSECAMRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2900F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
+ public static readonly RgbWorkingSpace PALSECAMRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2900F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
///
- /// ProPhoto Rgb working space
+ /// ProPhoto Rgb working space.
///
- public static readonly IRgbWorkingSpace ProPhotoRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.1596F, 0.8404F), new CieXyChromaticityCoordinates(0.0366F, 0.0001F)));
+ public static readonly RgbWorkingSpace ProPhotoRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.1596F, 0.8404F), new CieXyChromaticityCoordinates(0.0366F, 0.0001F)));
///
- /// SMPTE-C Rgb working space
+ /// SMPTE-C Rgb working space.
///
- public static readonly IRgbWorkingSpace SMPTECRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.3100F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F)));
+ public static readonly RgbWorkingSpace SMPTECRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.3100F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F)));
///
- /// Wide Gamut Rgb working space
+ /// Wide Gamut Rgb working space.
///
- public static readonly IRgbWorkingSpace WideGamutRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F)));
+ public static readonly RgbWorkingSpace WideGamutRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F)));
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/YCbCr.cs b/src/ImageSharp/ColorSpaces/YCbCr.cs
index 2c3feffa9..00533c699 100644
--- a/src/ImageSharp/ColorSpaces/YCbCr.cs
+++ b/src/ImageSharp/ColorSpaces/YCbCr.cs
@@ -16,12 +16,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
internal readonly struct YCbCr : IColorVector, IEquatable, IAlmostEquatable
{
///
- /// Represents a that has Y, Cb, and Cr values set to zero.
- ///
- public static readonly YCbCr Empty = default;
-
- ///
- /// Vector which is used in clamping to the max value
+ /// Vector which is used in clamping to the max value.
///
private static readonly Vector3 VectorMax = new Vector3(255F);
@@ -82,18 +77,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
get => this.backingVector.Z;
}
- ///
- /// Gets a value indicating whether this is empty.
- ///
- [EditorBrowsable(EditorBrowsableState.Never)]
- public bool IsEmpty => this.Equals(Empty);
-
///
- public Vector3 Vector
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => this.backingVector;
- }
+ public Vector3 Vector => this.backingVector;
///
/// Compares two objects for equality.
@@ -107,7 +92,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// True if the current left is equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(YCbCr left, YCbCr right)
{
return left.Equals(right);
@@ -132,6 +116,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
@@ -140,16 +125,12 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public override string ToString()
{
- if (this.IsEmpty)
- {
- return "YCbCr [ Empty ]";
- }
-
- return $"YCbCr [ Y={this.Y}, Cb={this.Cb}, Cr={this.Cr} ]";
+ return this.Equals(default)
+ ? "YCbCr [ Empty ]"
+ : $"YCbCr [ Y={this.Y}, Cb={this.Cb}, Cr={this.Cr} ]";
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
return obj is YCbCr other && this.Equals(other);
diff --git a/src/ImageSharp/Common/Constants.cs b/src/ImageSharp/Common/Constants.cs
index b7cfddcb6..a8a693fa6 100644
--- a/src/ImageSharp/Common/Constants.cs
+++ b/src/ImageSharp/Common/Constants.cs
@@ -18,4 +18,4 @@ namespace SixLabors.ImageSharp
///
public static readonly float EpsilonSquared = Epsilon * Epsilon;
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Common/Extensions/Vector4Extensions.cs b/src/ImageSharp/Common/Extensions/Vector4Extensions.cs
index 88712a736..b88c229c5 100644
--- a/src/ImageSharp/Common/Extensions/Vector4Extensions.cs
+++ b/src/ImageSharp/Common/Extensions/Vector4Extensions.cs
@@ -110,4 +110,4 @@ namespace SixLabors.ImageSharp
return MathF.Pow((signal + 0.055F) / 1.055F, 2.4F);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Common/Helpers/ParallelFor.cs b/src/ImageSharp/Common/Helpers/ParallelFor.cs
index 7061475a7..02c6deda3 100644
--- a/src/ImageSharp/Common/Helpers/ParallelFor.cs
+++ b/src/ImageSharp/Common/Helpers/ParallelFor.cs
@@ -1,4 +1,5 @@
using System;
+using System.Buffers;
using System.Threading.Tasks;
using SixLabors.Memory;
@@ -32,23 +33,23 @@ namespace SixLabors.ImageSharp
int toExclusive,
Configuration configuration,
int bufferLength,
- Action> body)
+ Action> body)
where T : struct
{
MemoryAllocator memoryAllocator = configuration.MemoryAllocator;
ParallelOptions parallelOptions = configuration.ParallelOptions;
- IBuffer InitBuffer()
+ IMemoryOwner InitBuffer()
{
return memoryAllocator.Allocate(bufferLength);
}
- void CleanUpBuffer(IBuffer buffer)
+ void CleanUpBuffer(IMemoryOwner buffer)
{
buffer.Dispose();
}
- IBuffer BodyFunc(int i, ParallelLoopState state, IBuffer buffer)
+ IMemoryOwner BodyFunc(int i, ParallelLoopState state, IMemoryOwner buffer)
{
body(i, buffer);
return buffer;
diff --git a/src/ImageSharp/Common/Helpers/UnitConverter.cs b/src/ImageSharp/Common/Helpers/UnitConverter.cs
new file mode 100644
index 000000000..c8b25bf56
--- /dev/null
+++ b/src/ImageSharp/Common/Helpers/UnitConverter.cs
@@ -0,0 +1,94 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.MetaData;
+using SixLabors.ImageSharp.MetaData.Profiles.Exif;
+
+namespace SixLabors.ImageSharp.Common.Helpers
+{
+ ///
+ /// Contains methods for converting values between unit scales.
+ ///
+ internal static class UnitConverter
+ {
+ ///
+ /// The number of centimeters in a meter.
+ /// 1 cm is equal to exactly 0.01 meters.
+ ///
+ private const double CmsInMeter = 1 / 0.01D;
+
+ ///
+ /// The number of centimeters in an inch.
+ /// 1 inch is equal to exactly 2.54 centimeters.
+ ///
+ private const double CmsInInch = 2.54D;
+
+ ///
+ /// The number of inches in a meter.
+ /// 1 inch is equal to exactly 0.0254 meters.
+ ///
+ private const double InchesInMeter = 1 / 0.0254D;
+
+ ///
+ /// Scales the value from centimeters to meters.
+ ///
+ /// The value to scale.
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static double CmToMeter(double x) => x * CmsInMeter;
+
+ ///
+ /// Scales the value from meters to centimeters.
+ ///
+ /// The value to scale.
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static double MeterToCm(double x) => x / CmsInMeter;
+
+ ///
+ /// Scales the value from meters to inches.
+ ///
+ /// The value to scale.
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static double MeterToInch(double x) => x / InchesInMeter;
+
+ ///
+ /// Scales the value from inches to meters.
+ ///
+ /// The value to scale.
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static double InchToMeter(double x) => x * InchesInMeter;
+
+ ///
+ /// Scales the value from centimeters to inches.
+ ///
+ /// The value to scale.
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static double CmToInch(double x) => x / CmsInInch;
+
+ ///
+ /// Scales the value from inches to centimeters.
+ ///
+ /// The value to scale.
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static double InchToCm(double x) => x * CmsInInch;
+
+ ///
+ /// Converts an to a .
+ ///
+ /// The EXIF profile containing the value.
+ /// The
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static PixelResolutionUnit ExifProfileToResolutionUnit(ExifProfile profile)
+ {
+ return profile.TryGetValue(ExifTag.ResolutionUnit, out ExifValue resolution)
+ ? (PixelResolutionUnit)(byte)(((ushort)resolution.Value) - 1) // EXIF is 1, 2, 3
+ : default;
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 20175613e..612850e5f 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -5,6 +5,7 @@ using System;
using System.Buffers.Binary;
using System.IO;
using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
@@ -59,6 +60,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
private Stream stream;
+ ///
+ /// The metadata
+ ///
+ private ImageMetaData metaData;
+
///
/// The file header containing general information.
/// TODO: Why is this not used? We advance the stream but do not use the values parsed.
@@ -103,7 +109,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
this.ReadImageHeaders(stream, out bool inverted, out byte[] palette);
- var image = new Image(this.configuration, this.infoHeader.Width, this.infoHeader.Height);
+ var image = new Image(this.configuration, this.infoHeader.Width, this.infoHeader.Height, this.metaData);
Buffer2D pixels = image.GetRootFramePixelBuffer();
@@ -157,7 +163,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
public IImageInfo Identify(Stream stream)
{
this.ReadImageHeaders(stream, out _, out _);
- return new ImageInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), this.infoHeader.Width, this.infoHeader.Height, new ImageMetaData());
+ return new ImageInfo(new PixelTypeInfo(this.infoHeader.BitsPerPixel), this.infoHeader.Width, this.infoHeader.Height, this.metaData);
}
///
@@ -220,7 +226,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
TPixel color = default;
var rgba = new Rgba32(0, 0, 0, 255);
- using (Buffer2D buffer = this.memoryAllocator.AllocateClean2D(width, height))
+ using (Buffer2D buffer = this.memoryAllocator.Allocate2D(width, height, AllocationOptions.Clean))
{
this.UncompressRle8(width, buffer.GetSpan());
@@ -348,7 +354,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
padding = 4 - padding;
}
- using (IManagedByteBuffer row = this.memoryAllocator.AllocateCleanManagedByteBuffer(arrayWidth + padding))
+ using (IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(arrayWidth + padding, AllocationOptions.Clean))
{
TPixel color = default;
var rgba = new Rgba32(0, 0, 0, 255);
@@ -518,6 +524,23 @@ namespace SixLabors.ImageSharp.Formats.Bmp
throw new NotSupportedException($"ImageSharp does not support this BMP file. HeaderSize: {headerSize}.");
}
+ // Resolution is stored in PPM.
+ var meta = new ImageMetaData();
+ meta.ResolutionUnits = PixelResolutionUnit.PixelsPerMeter;
+ if (this.infoHeader.XPelsPerMeter > 0 && this.infoHeader.YPelsPerMeter > 0)
+ {
+ meta.HorizontalResolution = this.infoHeader.XPelsPerMeter;
+ meta.VerticalResolution = this.infoHeader.YPelsPerMeter;
+ }
+ else
+ {
+ // Convert default metadata values to PPM.
+ meta.HorizontalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetaData.DefaultHorizontalResolution));
+ meta.VerticalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetaData.DefaultVerticalResolution));
+ }
+
+ this.metaData = meta;
+
// skip the remaining header because we can't read those parts
this.stream.Skip(skipAmount);
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index a4e61f910..80fc6330a 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -3,6 +3,8 @@
using System;
using System.IO;
+using SixLabors.ImageSharp.Common.Helpers;
+using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
@@ -50,6 +52,38 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32);
this.padding = bytesPerLine - (image.Width * (int)this.bitsPerPixel);
+ // Set Resolution.
+ ImageMetaData meta = image.MetaData;
+ int hResolution = 0;
+ int vResolution = 0;
+
+ if (meta.ResolutionUnits != PixelResolutionUnit.AspectRatio)
+ {
+ if (meta.HorizontalResolution > 0 && meta.VerticalResolution > 0)
+ {
+ switch (meta.ResolutionUnits)
+ {
+ case PixelResolutionUnit.PixelsPerInch:
+
+ hResolution = (int)Math.Round(UnitConverter.InchToMeter(meta.HorizontalResolution));
+ vResolution = (int)Math.Round(UnitConverter.InchToMeter(meta.VerticalResolution));
+ break;
+
+ case PixelResolutionUnit.PixelsPerCentimeter:
+
+ hResolution = (int)Math.Round(UnitConverter.CmToMeter(meta.HorizontalResolution));
+ vResolution = (int)Math.Round(UnitConverter.CmToMeter(meta.VerticalResolution));
+ break;
+
+ case PixelResolutionUnit.PixelsPerMeter:
+ hResolution = (int)Math.Round(meta.HorizontalResolution);
+ vResolution = (int)Math.Round(meta.VerticalResolution);
+
+ break;
+ }
+ }
+ }
+
var infoHeader = new BmpInfoHeader(
headerSize: BmpInfoHeader.Size,
height: image.Height,
@@ -58,7 +92,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
planes: 1,
imageSize: image.Height * bytesPerLine,
clrUsed: 0,
- clrImportant: 0);
+ clrImportant: 0,
+ xPelsPerMeter: hResolution,
+ yPelsPerMeter: vResolution);
var fileHeader = new BmpFileHeader(
type: 19778, // BM
diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
index 0bfd6980b..56952f035 100644
--- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
@@ -14,4 +14,4 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
BmpBitsPerPixel BitsPerPixel { get; }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/DisposalMethod.cs b/src/ImageSharp/Formats/Gif/DisposalMethod.cs
index 5371fc0fa..5d3e1b4d8 100644
--- a/src/ImageSharp/Formats/Gif/DisposalMethod.cs
+++ b/src/ImageSharp/Formats/Gif/DisposalMethod.cs
@@ -35,4 +35,4 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
RestoreToPrevious = 3
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index fc73f55a1..591f787ea 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -321,11 +321,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
if (imageDescriptor.LocalColorTableFlag)
{
int length = imageDescriptor.LocalColorTableSize * 3;
- localColorTable = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(length, true);
+ localColorTable = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(length, AllocationOptions.Clean);
this.stream.Read(localColorTable.Array, 0, length);
}
- indices = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(imageDescriptor.Width * imageDescriptor.Height, true);
+ indices = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(imageDescriptor.Width * imageDescriptor.Height, AllocationOptions.Clean);
this.ReadFrameIndices(imageDescriptor, indices.GetSpan());
ReadOnlySpan colorTable = MemoryMarshal.Cast((localColorTable ?? this.globalColorTable).GetSpan());
@@ -450,8 +450,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
int index = Unsafe.Add(ref indicesRef, i);
- if (this.graphicsControlExtension.TransparencyFlag == false ||
- this.graphicsControlExtension.TransparencyIndex != index)
+ if (!this.graphicsControlExtension.TransparencyFlag
+ || this.graphicsControlExtension.TransparencyIndex != index)
{
ref TPixel pixel = ref Unsafe.Add(ref rowRef, x);
rgba.Rgb = colorTable[index];
@@ -516,19 +516,47 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The stream containing image data.
private void ReadLogicalScreenDescriptorAndGlobalColorTable(Stream stream)
{
- this.metaData = new ImageMetaData();
-
this.stream = stream;
// Skip the identifier
this.stream.Skip(6);
this.ReadLogicalScreenDescriptor();
+ var meta = new ImageMetaData();
+
+ // The Pixel Aspect Ratio is defined to be the quotient of the pixel's
+ // width over its height. The value range in this field allows
+ // specification of the widest pixel of 4:1 to the tallest pixel of
+ // 1:4 in increments of 1/64th.
+ //
+ // Values : 0 - No aspect ratio information is given.
+ // 1..255 - Value used in the computation.
+ //
+ // Aspect Ratio = (Pixel Aspect Ratio + 15) / 64
+ if (this.logicalScreenDescriptor.PixelAspectRatio > 0)
+ {
+ meta.ResolutionUnits = PixelResolutionUnit.AspectRatio;
+ float ratio = (this.logicalScreenDescriptor.PixelAspectRatio + 15) / 64F;
+
+ if (ratio > 1)
+ {
+ meta.HorizontalResolution = ratio;
+ meta.VerticalResolution = 1;
+ }
+ else
+ {
+ meta.VerticalResolution = 1 / ratio;
+ meta.HorizontalResolution = 1;
+ }
+ }
+
+ this.metaData = meta;
+
if (this.logicalScreenDescriptor.GlobalColorTableFlag)
{
int globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3;
- this.globalColorTable = this.MemoryAllocator.AllocateManagedByteBuffer(globalColorTableLength, true);
+ this.globalColorTable = this.MemoryAllocator.AllocateManagedByteBuffer(globalColorTableLength, AllocationOptions.Clean);
// Read the global color table data from the stream
stream.Read(this.globalColorTable.Array, 0, globalColorTableLength);
diff --git a/src/ImageSharp/Formats/Gif/GifEncoder.cs b/src/ImageSharp/Formats/Gif/GifEncoder.cs
index 07a70ad96..e8e28ccdd 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoder.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoder.cs
@@ -5,7 +5,7 @@ using System.IO;
using System.Text;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Quantization;
+using SixLabors.ImageSharp.Processing.Processors.Quantization;
namespace SixLabors.ImageSharp.Formats.Gif
{
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index 8a6415c3b..ea507c781 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
using System.Text;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Quantization;
+using SixLabors.ImageSharp.Processing.Processors.Quantization;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Gif
@@ -226,11 +226,41 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
byte packedValue = GifLogicalScreenDescriptor.GetPackedValue(useGlobalTable, this.bitDepth - 1, false, this.bitDepth - 1);
+ // The Pixel Aspect Ratio is defined to be the quotient of the pixel's
+ // width over its height. The value range in this field allows
+ // specification of the widest pixel of 4:1 to the tallest pixel of
+ // 1:4 in increments of 1/64th.
+ //
+ // Values : 0 - No aspect ratio information is given.
+ // 1..255 - Value used in the computation.
+ //
+ // Aspect Ratio = (Pixel Aspect Ratio + 15) / 64
+ ImageMetaData meta = image.MetaData;
+ byte ratio = 0;
+
+ if (meta.ResolutionUnits == PixelResolutionUnit.AspectRatio)
+ {
+ double hr = meta.HorizontalResolution;
+ double vr = meta.VerticalResolution;
+ if (hr != vr)
+ {
+ if (hr > vr)
+ {
+ ratio = (byte)((hr * 64) - 15);
+ }
+ else
+ {
+ ratio = (byte)(((1 / vr) * 64) - 15);
+ }
+ }
+ }
+
var descriptor = new GifLogicalScreenDescriptor(
width: (ushort)image.Width,
height: (ushort)image.Height,
packed: packedValue,
- backgroundColorIndex: unchecked((byte)transparencyIndex));
+ backgroundColorIndex: unchecked((byte)transparencyIndex),
+ ratio);
descriptor.WriteTo(this.buffer);
diff --git a/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
index 30e476e7e..bad6e0031 100644
--- a/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
@@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System.Text;
-using SixLabors.ImageSharp.Processing.Quantization;
+using SixLabors.ImageSharp.Processing.Processors.Quantization;
namespace SixLabors.ImageSharp.Formats.Gif
{
diff --git a/src/ImageSharp/Formats/Gif/LzwDecoder.cs b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
index 35eb43a8a..7a2aef180 100644
--- a/src/ImageSharp/Formats/Gif/LzwDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -32,17 +33,17 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The prefix buffer.
///
- private readonly IBuffer prefix;
+ private readonly IMemoryOwner prefix;
///
/// The suffix buffer.
///
- private readonly IBuffer suffix;
+ private readonly IMemoryOwner suffix;
///
/// The pixel stack buffer.
///
- private readonly IBuffer pixelStack;
+ private readonly IMemoryOwner pixelStack;
///
/// Initializes a new instance of the class
@@ -57,9 +58,9 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.stream = stream;
- this.prefix = memoryAllocator.Allocate(MaxStackSize, true);
- this.suffix = memoryAllocator.Allocate(MaxStackSize, true);
- this.pixelStack = memoryAllocator.Allocate(MaxStackSize + 1, true);
+ this.prefix = memoryAllocator.Allocate(MaxStackSize, AllocationOptions.Clean);
+ this.suffix = memoryAllocator.Allocate(MaxStackSize, AllocationOptions.Clean);
+ this.pixelStack = memoryAllocator.Allocate(MaxStackSize + 1, AllocationOptions.Clean);
}
///
diff --git a/src/ImageSharp/Formats/Gif/LzwEncoder.cs b/src/ImageSharp/Formats/Gif/LzwEncoder.cs
index 347609a54..002457db3 100644
--- a/src/ImageSharp/Formats/Gif/LzwEncoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwEncoder.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -66,12 +67,12 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The hash table.
///
- private readonly IBuffer hashTable;
+ private readonly IMemoryOwner hashTable;
///
/// The code table.
///
- private readonly IBuffer codeTable;
+ private readonly IMemoryOwner codeTable;
///
/// Define the storage for the packet accumulator.
@@ -168,8 +169,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
public LzwEncoder(MemoryAllocator memoryAllocator, int colorDepth)
{
this.initialCodeSize = Math.Max(2, colorDepth);
- this.hashTable = memoryAllocator.Allocate(HashSize, true);
- this.codeTable = memoryAllocator.Allocate(HashSize, true);
+ this.hashTable = memoryAllocator.Allocate(HashSize, AllocationOptions.Clean);
+ this.codeTable = memoryAllocator.Allocate(HashSize, AllocationOptions.Clean);
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FastACTables.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTables.cs
similarity index 87%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FastACTables.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTables.cs
index 6cb0d6dfe..95693c09b 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FastACTables.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTables.cs
@@ -5,7 +5,7 @@ using System;
using System.Runtime.CompilerServices;
using SixLabors.Memory;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
///
/// The collection of lookup tables used for fast AC entropy scan decoding.
@@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// The memory allocator used to allocate memory for image processing operations.
public FastACTables(MemoryAllocator memoryAllocator)
{
- this.tables = memoryAllocator.AllocateClean2D(512, 4);
+ this.tables = memoryAllocator.Allocate2D(512, 4, AllocationOptions.Clean);
}
///
@@ -35,10 +35,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
///
- /// Gets a reference to the first element of the AC table indexed by
- ///
+ /// Gets a reference to the first element of the AC table indexed by ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ref short GetAcTableReference(PdfJsFrameComponent component)
+ public ref short GetAcTableReference(JpegComponent component)
{
return ref this.tables.GetRowSpan(component.ACHuffmanTableId)[0];
}
@@ -48,11 +47,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
/// The table index.
/// The collection of AC Huffman tables.
- public void BuildACTableLut(int index, PdfJsHuffmanTables acHuffmanTables)
+ public void BuildACTableLut(int index, HuffmanTables acHuffmanTables)
{
const int FastBits = ScanDecoder.FastBits;
Span fastAC = this.tables.GetRowSpan(index);
- ref PdfJsHuffmanTable huffman = ref acHuffmanTables[index];
+ ref HuffmanTable huffman = ref acHuffmanTables[index];
int i;
for (i = 0; i < (1 << FastBits); i++)
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer256.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedByteBuffer256.cs
similarity index 90%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer256.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedByteBuffer256.cs
index 5870e3da8..1d26178e0 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer256.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedByteBuffer256.cs
@@ -4,7 +4,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedByteBuffer256
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer512.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedByteBuffer512.cs
similarity index 90%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer512.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedByteBuffer512.cs
index c509903c9..556e74fd5 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer512.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedByteBuffer512.cs
@@ -4,7 +4,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedByteBuffer512
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer257.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedInt16Buffer257.cs
similarity index 90%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer257.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedInt16Buffer257.cs
index b304dbf8c..a3b67a700 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer257.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedInt16Buffer257.cs
@@ -4,7 +4,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedInt16Buffer257
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt32Buffer18.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedInt32Buffer18.cs
similarity index 90%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt32Buffer18.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedInt32Buffer18.cs
index f8507ec47..bba89f072 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt32Buffer18.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedInt32Buffer18.cs
@@ -4,7 +4,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedInt32Buffer18
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedUInt32Buffer18.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedUInt32Buffer18.cs
similarity index 90%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedUInt32Buffer18.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedUInt32Buffer18.cs
index 9b076d9da..1d3ca9933 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedUInt32Buffer18.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/FixedUInt32Buffer18.cs
@@ -4,7 +4,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedUInt32Buffer18
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs
similarity index 91%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs
index 15ae56331..f159bda07 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs
@@ -2,17 +2,18 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.Memory;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
///
/// Represents a Huffman Table
///
[StructLayout(LayoutKind.Sequential)]
- internal unsafe struct PdfJsHuffmanTable
+ internal unsafe struct HuffmanTable
{
///
/// Gets the max code array
@@ -40,15 +41,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
public FixedInt16Buffer257 Sizes;
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
/// The to use for buffer allocations.
/// The code lengths
/// The huffman values
- public PdfJsHuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan count, ReadOnlySpan values)
+ public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan count, ReadOnlySpan values)
{
const int Length = 257;
- using (IBuffer huffcode = memoryAllocator.Allocate(Length))
+ using (IMemoryOwner huffcode = memoryAllocator.Allocate(Length))
{
ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.GetSpan());
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTables.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTables.cs
similarity index 54%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTables.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTables.cs
index 5cbde2b88..dc066aa0a 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTables.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTables.cs
@@ -1,24 +1,23 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System.Collections.Generic;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
///
- /// Defines a 2 pairs of huffman tables
+ /// Defines a 2 pairs of huffman tables.
///
- internal sealed class PdfJsHuffmanTables
+ internal sealed class HuffmanTables
{
- private readonly PdfJsHuffmanTable[] tables = new PdfJsHuffmanTable[4];
+ private readonly HuffmanTable[] tables = new HuffmanTable[4];
///
/// Gets or sets the table at the given index.
///
/// The index
- /// The
- public ref PdfJsHuffmanTable this[int index]
+ /// The
+ public ref HuffmanTable this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref this.tables[index];
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs
index 591af6344..f153ce062 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using SixLabors.ImageSharp.MetaData;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
@@ -28,10 +29,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
Guard.MustBeGreaterThan(xDensity, 0, nameof(xDensity));
Guard.MustBeGreaterThan(yDensity, 0, nameof(yDensity));
+ Guard.MustBeBetweenOrEqualTo(densityUnits, 0, 2, nameof(densityUnits));
this.MajorVersion = majorVersion;
this.MinorVersion = minorVersion;
- this.DensityUnits = densityUnits;
+ this.DensityUnits = (PixelResolutionUnit)densityUnits;
this.XDensity = xDensity;
this.YDensity = yDensity;
}
@@ -52,7 +54,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// 01 : Pixels per inch (2.54 cm)
/// 02 : Pixels per centimeter
///
- public byte DensityUnits { get; }
+ public PixelResolutionUnit DensityUnits { get; }
///
/// Gets the horizontal pixel density. Must not be zero.
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs
index 2baefff9b..87f675491 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs
@@ -9,7 +9,7 @@ using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
///
- /// Encapsulates the implementation of processing "raw" -s into Jpeg image channels.
+ /// Encapsulates the implementation of processing "raw" jpeg buffers into Jpeg image channels.
///
[StructLayout(LayoutKind.Sequential)]
internal struct JpegBlockPostProcessor
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs
similarity index 82%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs
index 7501b0d83..73a69a069 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs
@@ -5,21 +5,19 @@ using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.Formats.Jpeg.Components;
-using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
using SixLabors.Memory;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
///
/// Represents a single frame component
///
- internal class PdfJsFrameComponent : IDisposable, IJpegComponent
+ internal class JpegComponent : IDisposable, IJpegComponent
{
private readonly MemoryAllocator memoryAllocator;
- public PdfJsFrameComponent(MemoryAllocator memoryAllocator, PdfJsFrame frame, byte id, int horizontalFactor, int verticalFactor, byte quantizationTableIndex, int index)
+ public JpegComponent(MemoryAllocator memoryAllocator, JpegFrame frame, byte id, int horizontalFactor, int verticalFactor, byte quantizationTableIndex, int index)
{
this.memoryAllocator = memoryAllocator;
this.Frame = frame;
@@ -89,7 +87,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
public int ACHuffmanTableId { get; set; }
- public PdfJsFrame Frame { get; }
+ public JpegFrame Frame { get; }
///
public void Dispose()
@@ -125,11 +123,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
else
{
- PdfJsFrameComponent c0 = this.Frame.Components[0];
+ JpegComponent c0 = this.Frame.Components[0];
this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors);
}
- this.SpectralBlocks = this.memoryAllocator.AllocateClean2D(blocksPerColumnForMcu, blocksPerLineForMcu + 1);
+ this.SpectralBlocks = this.memoryAllocator.Allocate2D(blocksPerColumnForMcu, blocksPerLineForMcu + 1, AllocationOptions.Clean);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -140,16 +138,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public int GetBlockBufferOffset(int row, int col)
+ public ref short GetBlockDataReference(int column, int row)
{
- return 64 * (((this.WidthInBlocks + 1) * row) + col);
- }
-
- // TODO: we need consistence in (row, col) VS (col, row) ordering
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ref short GetBlockDataReference(int row, int col)
- {
- ref Block8x8 blockRef = ref this.GetBlockReference(col, row);
+ ref Block8x8 blockRef = ref this.GetBlockReference(column, row);
return ref Unsafe.As(ref blockRef);
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFileMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFileMarker.cs
similarity index 74%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFileMarker.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFileMarker.cs
index 85c9f9466..d2b0ee26e 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFileMarker.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFileMarker.cs
@@ -3,32 +3,30 @@
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
///
- /// Represents a jpeg file marker
+ /// Represents a jpeg file marker.
///
- internal readonly struct PdfJsFileMarker
+ internal readonly struct JpegFileMarker
{
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
/// The marker
/// The position within the stream
- public PdfJsFileMarker(byte marker, long position)
+ public JpegFileMarker(byte marker, long position)
+ : this(marker, position, false)
{
- this.Marker = marker;
- this.Position = position;
- this.Invalid = false;
}
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
/// The marker
/// The position within the stream
/// Whether the current marker is invalid
- public PdfJsFileMarker(byte marker, long position, bool invalid)
+ public JpegFileMarker(byte marker, long position, bool invalid)
{
this.Marker = marker;
this.Position = position;
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrame.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs
similarity index 92%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrame.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs
index 8ce981a09..da089fa44 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrame.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs
@@ -3,12 +3,12 @@
using System;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
///
/// Represent a single jpeg frame
///
- internal sealed class PdfJsFrame : IDisposable
+ internal sealed class JpegFrame : IDisposable
{
///
/// Gets or sets a value indicating whether the frame uses the extended specification
@@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
/// Gets or sets the frame component collection
///
- public PdfJsFrameComponent[] Components { get; set; }
+ public JpegComponent[] Components { get; set; }
///
/// Gets or sets the maximum horizontal sampling factor
@@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
for (int i = 0; i < this.ComponentCount; i++)
{
- PdfJsFrameComponent component = this.Components[i];
+ JpegComponent component = this.Components[i];
component.Init();
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs
index 99408cf57..1b513c612 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Linq;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
@@ -37,7 +38,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
///
/// Temporal buffer to store a row of colors.
///
- private readonly IBuffer rgbaBuffer;
+ private readonly IMemoryOwner rgbaBuffer;
///
/// The corresponding to the current determined by .
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/ScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs
similarity index 93%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/ScanDecoder.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs
index 8575bac69..8c525335b 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/ScanDecoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ScanDecoder.cs
@@ -2,10 +2,9 @@
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.Formats.Jpeg.Components;
+using SixLabors.ImageSharp.IO;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
///
/// Decodes the Huffman encoded spectral scan.
@@ -23,13 +22,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
// LUT Bias[n] = (-1 << n) + 1
private static readonly int[] Bias = { 0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047, -4095, -8191, -16383, -32767 };
- private readonly PdfJsFrame frame;
- private readonly PdfJsHuffmanTables dcHuffmanTables;
- private readonly PdfJsHuffmanTables acHuffmanTables;
+ private readonly JpegFrame frame;
+ private readonly HuffmanTables dcHuffmanTables;
+ private readonly HuffmanTables acHuffmanTables;
private readonly FastACTables fastACTables;
private readonly DoubleBufferedStreamReader stream;
- private readonly PdfJsFrameComponent[] components;
+ private readonly JpegComponent[] components;
private readonly ZigZag dctZigZag;
// The restart interval.
@@ -97,9 +96,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// The successive approximation bit low end.
public ScanDecoder(
DoubleBufferedStreamReader stream,
- PdfJsFrame frame,
- PdfJsHuffmanTables dcHuffmanTables,
- PdfJsHuffmanTables acHuffmanTables,
+ JpegFrame frame,
+ HuffmanTables dcHuffmanTables,
+ HuffmanTables acHuffmanTables,
FastACTables fastACTables,
int componentIndex,
int componentsLength,
@@ -177,10 +176,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
// Scan an interleaved mcu... process components in order
for (int k = 0; k < this.componentsLength; k++)
{
- PdfJsFrameComponent component = this.components[k];
+ JpegComponent component = this.components[k];
- ref PdfJsHuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
- ref PdfJsHuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId];
+ ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
+ ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId];
ref short fastACRef = ref this.fastACTables.GetAcTableReference(component);
int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor;
@@ -231,13 +230,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
private void ParseBaselineDataNonInterleaved()
{
- PdfJsFrameComponent component = this.components[this.componentIndex];
+ JpegComponent component = this.components[this.componentIndex];
int w = component.WidthInBlocks;
int h = component.HeightInBlocks;
- ref PdfJsHuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
- ref PdfJsHuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId];
+ ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
+ ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId];
ref short fastACRef = ref this.fastACTables.GetAcTableReference(component);
int mcu = 0;
@@ -296,8 +295,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
// Scan an interleaved mcu... process components in order
for (int k = 0; k < this.componentsLength; k++)
{
- PdfJsFrameComponent component = this.components[k];
- ref PdfJsHuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
+ JpegComponent component = this.components[k];
+ ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor;
@@ -345,13 +344,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
private void ParseProgressiveDataNonInterleaved()
{
- PdfJsFrameComponent component = this.components[this.componentIndex];
+ JpegComponent component = this.components[this.componentIndex];
int w = component.WidthInBlocks;
int h = component.HeightInBlocks;
- ref PdfJsHuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
- ref PdfJsHuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId];
+ ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DCHuffmanTableId];
+ ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.ACHuffmanTableId];
ref short fastACRef = ref this.fastACTables.GetAcTableReference(component);
int mcu = 0;
@@ -396,11 +395,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
private void DecodeBlockBaseline(
- PdfJsFrameComponent component,
+ JpegComponent component,
int row,
int col,
- ref PdfJsHuffmanTable dcTable,
- ref PdfJsHuffmanTable acTable,
+ ref HuffmanTable dcTable,
+ ref HuffmanTable acTable,
ref short fastACRef)
{
this.CheckBits();
@@ -411,7 +410,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
JpegThrowHelper.ThrowBadHuffmanCode();
}
- ref short blockDataRef = ref component.GetBlockDataReference(row, col);
+ ref short blockDataRef = ref component.GetBlockDataReference(col, row);
int diff = t != 0 ? this.ExtendReceive(t) : 0;
int dc = component.DcPredictor + diff;
@@ -475,10 +474,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
private void DecodeBlockProgressiveDC(
- PdfJsFrameComponent component,
+ JpegComponent component,
int row,
int col,
- ref PdfJsHuffmanTable dcTable)
+ ref HuffmanTable dcTable)
{
if (this.spectralEnd != 0)
{
@@ -487,7 +486,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
this.CheckBits();
- ref short blockDataRef = ref component.GetBlockDataReference(row, col);
+ ref short blockDataRef = ref component.GetBlockDataReference(col, row);
if (this.successiveHigh == 0)
{
@@ -511,10 +510,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
private void DecodeBlockProgressiveAC(
- PdfJsFrameComponent component,
+ JpegComponent component,
int row,
int col,
- ref PdfJsHuffmanTable acTable,
+ ref HuffmanTable acTable,
ref short fastACRef)
{
if (this.spectralStart == 0)
@@ -522,7 +521,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
JpegThrowHelper.ThrowImageFormatException("Can't merge DC and AC.");
}
- ref short blockDataRef = ref component.GetBlockDataReference(row, col);
+ ref short blockDataRef = ref component.GetBlockDataReference(col, row);
if (this.successiveHigh == 0)
{
@@ -603,7 +602,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
}
- private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref PdfJsHuffmanTable acTable)
+ private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref HuffmanTable acTable)
{
int k;
@@ -805,7 +804,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
[MethodImpl(InliningOptions.ShortMethod)]
- private int DecodeHuffman(ref PdfJsHuffmanTable table)
+ private int DecodeHuffman(ref HuffmanTable table)
{
this.CheckBits();
@@ -830,7 +829,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
[MethodImpl(InliningOptions.ColdPath)]
- private int DecodeHuffmanSlow(ref PdfJsHuffmanTable table)
+ private int DecodeHuffmanSlow(ref HuffmanTable table)
{
// Naive test is to shift the code_buffer down so k bits are
// valid, then test against MaxCode. To speed this up, we've
@@ -941,7 +940,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
for (int i = 0; i < this.components.Length; i++)
{
- PdfJsFrameComponent c = this.components[i];
+ JpegComponent c = this.components[i];
c.DcPredictor = 0;
}
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/Bits.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/Bits.cs
deleted file mode 100644
index 353eb01fe..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/Bits.cs
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.Runtime.CompilerServices;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Holds the unprocessed bits that have been taken from the byte-stream.
- /// The n least significant bits of a form the unread bits, to be read in MSB to
- /// LSB order.
- ///
- internal struct Bits
- {
- ///
- /// Gets or sets the accumulator.
- ///
- public int Accumulator;
-
- ///
- /// Gets or sets the mask.
- /// 0, with mask==0 when unreadbits==0.]]>
- ///
- public int Mask;
-
- ///
- /// Gets or sets the number of unread bits in the accumulator.
- ///
- public int UnreadBits;
-
- ///
- /// Reads bytes from the byte buffer to ensure that bits.UnreadBits is at
- /// least n. For best performance (avoiding function calls inside hot loops),
- /// the caller is the one responsible for first checking that bits.UnreadBits < n.
- ///
- /// The number of bits to ensure.
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void EnsureNBits(int n, ref InputProcessor inputProcessor)
- {
- GolangDecoderErrorCode errorCode = this.EnsureNBitsUnsafe(n, ref inputProcessor);
- errorCode.EnsureNoError();
- }
-
- ///
- /// Reads bytes from the byte buffer to ensure that bits.UnreadBits is at
- /// least n. For best performance (avoiding function calls inside hot loops),
- /// the caller is the one responsible for first checking that bits.UnreadBits < n.
- /// This method does not throw. Returns instead.
- ///
- /// The number of bits to ensure.
- /// The
- /// Error code
- public GolangDecoderErrorCode EnsureNBitsUnsafe(int n, ref InputProcessor inputProcessor)
- {
- while (true)
- {
- GolangDecoderErrorCode errorCode = this.EnsureBitsStepImpl(ref inputProcessor);
- if (errorCode != GolangDecoderErrorCode.NoError || this.UnreadBits >= n)
- {
- return errorCode;
- }
- }
- }
-
- ///
- /// Unrolled version of for n==8
- ///
- /// The
- /// A
- public GolangDecoderErrorCode Ensure8BitsUnsafe(ref InputProcessor inputProcessor)
- {
- return this.EnsureBitsStepImpl(ref inputProcessor);
- }
-
- ///
- /// Unrolled version of for n==1
- ///
- /// The
- /// A
- public GolangDecoderErrorCode Ensure1BitUnsafe(ref InputProcessor inputProcessor)
- {
- return this.EnsureBitsStepImpl(ref inputProcessor);
- }
-
- ///
- /// Receive extend
- ///
- /// Byte
- /// The
- /// Read bits value
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public int ReceiveExtend(int t, ref InputProcessor inputProcessor)
- {
- GolangDecoderErrorCode errorCode = this.ReceiveExtendUnsafe(t, ref inputProcessor, out int x);
- errorCode.EnsureNoError();
- return x;
- }
-
- ///
- /// Receive extend
- ///
- /// Byte
- /// The
- /// Read bits value
- /// The
- public GolangDecoderErrorCode ReceiveExtendUnsafe(int t, ref InputProcessor inputProcessor, out int x)
- {
- if (this.UnreadBits < t)
- {
- GolangDecoderErrorCode errorCode = this.EnsureNBitsUnsafe(t, ref inputProcessor);
- if (errorCode != GolangDecoderErrorCode.NoError)
- {
- x = int.MaxValue;
- return errorCode;
- }
- }
-
- this.UnreadBits -= t;
- this.Mask >>= t;
- int s = 1 << t;
- x = (this.Accumulator >> this.UnreadBits) & (s - 1);
-
- if (x < (s >> 1))
- {
- x += ((-1) << t) + 1;
- }
-
- return GolangDecoderErrorCode.NoError;
- }
-
- private GolangDecoderErrorCode EnsureBitsStepImpl(ref InputProcessor inputProcessor)
- {
- GolangDecoderErrorCode errorCode = inputProcessor.Bytes.ReadByteStuffedByteUnsafe(inputProcessor.InputStream, out int c);
-
- if (errorCode != GolangDecoderErrorCode.NoError)
- {
- return errorCode;
- }
-
- this.Accumulator = (this.Accumulator << 8) | c;
- this.UnreadBits += 8;
- if (this.Mask == 0)
- {
- this.Mask = 1 << 7;
- }
- else
- {
- this.Mask <<= 8;
- }
-
- return errorCode;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/Bytes.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/Bytes.cs
deleted file mode 100644
index c8c68aa7e..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/Bytes.cs
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.IO;
-using System.Runtime.CompilerServices;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Bytes is a byte buffer, similar to a stream, except that it
- /// has to be able to unread more than 1 byte, due to byte stuffing.
- /// Byte stuffing is specified in section F.1.2.3.
- /// TODO: Optimize buffer management inside this class!
- ///
- internal struct Bytes : IDisposable
- {
- ///
- /// Specifies the buffer size for and
- ///
- public const int BufferSize = 4096;
-
- ///
- /// Gets or sets the buffer.
- /// buffer[i:j] are the buffered bytes read from the underlying
- /// stream that haven't yet been passed further on.
- ///
- public byte[] Buffer;
-
- ///
- /// Values of converted to -s
- ///
- public int[] BufferAsInt;
-
- ///
- /// Start of bytes read
- ///
- public int I;
-
- ///
- /// End of bytes read
- ///
- public int J;
-
- ///
- /// Gets or sets the unreadable bytes. The number of bytes to back up i after
- /// overshooting. It can be 0, 1 or 2.
- ///
- public int UnreadableBytes;
-
- ///
- /// Creates a new instance of the , and initializes it's buffer.
- ///
- /// The bytes created
- public static Bytes Create()
- {
- // DO NOT bother with buffers and array pooling here!
- // It only makes things worse!
- return new Bytes
- {
- Buffer = new byte[BufferSize],
- BufferAsInt = new int[BufferSize]
- };
- }
-
- ///
- /// Disposes of the underlying buffer
- ///
- public void Dispose()
- {
- this.Buffer = null;
- this.BufferAsInt = null;
- }
-
- ///
- /// ReadByteStuffedByte is like ReadByte but is for byte-stuffed Huffman data.
- ///
- /// Input stream
- /// The result byte as
- /// The
- public GolangDecoderErrorCode ReadByteStuffedByteUnsafe(Stream inputStream, out int x)
- {
- // Take the fast path if bytes.buf contains at least two bytes.
- if (this.I + 2 <= this.J)
- {
- x = this.BufferAsInt[this.I];
- this.I++;
- this.UnreadableBytes = 1;
- if (x != JpegConstants.Markers.XFFInt)
- {
- return GolangDecoderErrorCode.NoError;
- }
-
- if (this.BufferAsInt[this.I] != 0x00)
- {
- return GolangDecoderErrorCode.MissingFF00;
- }
-
- this.I++;
- this.UnreadableBytes = 2;
- x = JpegConstants.Markers.XFF;
- return GolangDecoderErrorCode.NoError;
- }
-
- this.UnreadableBytes = 0;
-
- GolangDecoderErrorCode errorCode = this.ReadByteAsIntUnsafe(inputStream, out x);
- this.UnreadableBytes = 1;
- if (errorCode != GolangDecoderErrorCode.NoError)
- {
- return errorCode;
- }
-
- if (x != JpegConstants.Markers.XFF)
- {
- return GolangDecoderErrorCode.NoError;
- }
-
- errorCode = this.ReadByteAsIntUnsafe(inputStream, out x);
- this.UnreadableBytes = 2;
- if (errorCode != GolangDecoderErrorCode.NoError)
- {
- return errorCode;
- }
-
- if (x != 0x00)
- {
- return GolangDecoderErrorCode.MissingFF00;
- }
-
- x = JpegConstants.Markers.XFF;
- return GolangDecoderErrorCode.NoError;
- }
-
- ///
- /// Returns the next byte, whether buffered or not buffered. It does not care about byte stuffing.
- ///
- /// Input stream
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public byte ReadByte(Stream inputStream)
- {
- GolangDecoderErrorCode errorCode = this.ReadByteUnsafe(inputStream, out byte result);
- errorCode.EnsureNoError();
- return result;
- }
-
- ///
- /// Extracts the next byte, whether buffered or not buffered into the result out parameter. It does not care about byte stuffing.
- /// This method does not throw on format error, it returns a instead.
- ///
- /// Input stream
- /// The result as out parameter
- /// The
- public GolangDecoderErrorCode ReadByteUnsafe(Stream inputStream, out byte result)
- {
- GolangDecoderErrorCode errorCode = GolangDecoderErrorCode.NoError;
- while (this.I == this.J)
- {
- errorCode = this.FillUnsafe(inputStream);
- if (errorCode != GolangDecoderErrorCode.NoError)
- {
- result = 0;
- return errorCode;
- }
- }
-
- result = this.Buffer[this.I];
- this.I++;
- this.UnreadableBytes = 0;
- return errorCode;
- }
-
- ///
- /// Same as but the result is an
- ///
- /// The input stream
- /// The result
- /// A
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public GolangDecoderErrorCode ReadByteAsIntUnsafe(Stream inputStream, out int result)
- {
- GolangDecoderErrorCode errorCode = GolangDecoderErrorCode.NoError;
- while (this.I == this.J)
- {
- errorCode = this.FillUnsafe(inputStream);
- if (errorCode != GolangDecoderErrorCode.NoError)
- {
- result = 0;
- return errorCode;
- }
- }
-
- result = this.BufferAsInt[this.I];
- this.I++;
- this.UnreadableBytes = 0;
- return errorCode;
- }
-
- ///
- /// Fills up the bytes buffer from the underlying stream.
- /// It should only be called when there are no unread bytes in bytes.
- ///
- /// Thrown when reached end of stream unexpectedly.
- /// Input stream
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Fill(Stream inputStream)
- {
- GolangDecoderErrorCode errorCode = this.FillUnsafe(inputStream);
- errorCode.EnsureNoError();
- }
-
- ///
- /// Fills up the bytes buffer from the underlying stream.
- /// It should only be called when there are no unread bytes in bytes.
- /// This method does not throw , returns a instead!
- ///
- /// Input stream
- /// The
- public GolangDecoderErrorCode FillUnsafe(Stream inputStream)
- {
- if (this.I != this.J)
- {
- // Unrecoverable error in the input, throwing!
- DecoderThrowHelper.ThrowImageFormatException.FillCalledWhenUnreadBytesExist();
- }
-
- // Move the last 2 bytes to the start of the buffer, in case we need
- // to call UnreadByteStuffedByte.
- if (this.J > 2)
- {
- this.Buffer[0] = this.Buffer[this.J - 2];
- this.Buffer[1] = this.Buffer[this.J - 1];
- this.I = 2;
- this.J = 2;
- }
-
- // Fill in the rest of the buffer.
- int n = inputStream.Read(this.Buffer, this.J, this.Buffer.Length - this.J);
- if (n == 0)
- {
- return GolangDecoderErrorCode.UnexpectedEndOfStream;
- }
-
- this.J += n;
-
- for (int i = 0; i < this.Buffer.Length; i++)
- {
- this.BufferAsInt[i] = this.Buffer[i];
- }
-
- return GolangDecoderErrorCode.NoError;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/DecoderThrowHelper.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/DecoderThrowHelper.cs
deleted file mode 100644
index 2b2bc61ba..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/DecoderThrowHelper.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Runtime.CompilerServices;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Encapsulates exception thrower methods for the Jpeg Encoder
- ///
- internal static class DecoderThrowHelper
- {
- ///
- /// Throws an exception that belongs to the given
- ///
- /// The
- [MethodImpl(MethodImplOptions.NoInlining)]
- public static void ThrowExceptionForErrorCode(this GolangDecoderErrorCode errorCode)
- {
- // REMARK: If this method throws for an image that is expected to be decodable,
- // consider using the ***Unsafe variant of the parsing method that asks for ThrowExceptionForErrorCode()
- // then verify the error code + implement fallback logic manually!
- switch (errorCode)
- {
- case GolangDecoderErrorCode.NoError:
- throw new ArgumentException("ThrowExceptionForErrorCode() called with NoError!", nameof(errorCode));
- case GolangDecoderErrorCode.MissingFF00:
- throw new MissingFF00Exception();
- case GolangDecoderErrorCode.UnexpectedEndOfStream:
- throw new EOFException();
- default:
- throw new ArgumentOutOfRangeException(nameof(errorCode), errorCode, null);
- }
- }
-
- ///
- /// Throws an exception if the given defines an error.
- ///
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void EnsureNoError(this GolangDecoderErrorCode errorCode)
- {
- if (errorCode != GolangDecoderErrorCode.NoError)
- {
- ThrowExceptionForErrorCode(errorCode);
- }
- }
-
- ///
- /// Throws an exception if the given is .
- ///
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void EnsureNoEOF(this GolangDecoderErrorCode errorCode)
- {
- if (errorCode == GolangDecoderErrorCode.UnexpectedEndOfStream)
- {
- errorCode.ThrowExceptionForErrorCode();
- }
- }
-
- ///
- /// Encapsulates methods throwing different flavours of -s.
- ///
- public static class ThrowImageFormatException
- {
- ///
- /// Throws "Fill called when unread bytes exist".
- ///
- [MethodImpl(MethodImplOptions.NoInlining)]
- public static void FillCalledWhenUnreadBytesExist()
- {
- throw new ImageFormatException("Fill called when unread bytes exist!");
- }
-
- ///
- /// Throws "Bad Huffman code".
- ///
- [MethodImpl(MethodImplOptions.NoInlining)]
- public static void BadHuffmanCode()
- {
- throw new ImageFormatException("Bad Huffman code!");
- }
-
- ///
- /// Throws "Uninitialized Huffman table".
- ///
- [MethodImpl(MethodImplOptions.NoInlining)]
- public static void UninitializedHuffmanTable()
- {
- throw new ImageFormatException("Uninitialized Huffman table");
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/EOFException.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/EOFException.cs
deleted file mode 100644
index 60d9b1e1a..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/EOFException.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// The EOF (End of File exception).
- /// Thrown when the decoder encounters an EOF marker without a proceeding EOI (End Of Image) marker
- /// TODO: Rename to UnexpectedEndOfStreamException
- ///
- internal class EOFException : Exception
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public EOFException()
- : base("Reached end of stream before proceeding EOI marker!")
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangComponent.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangComponent.cs
deleted file mode 100644
index 75cea5551..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangComponent.cs
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Runtime.CompilerServices;
-
-using SixLabors.ImageSharp.Formats.Jpeg.Components;
-using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
-using SixLabors.Memory;
-using SixLabors.Primitives;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- ///
- /// Represents a single color component
- ///
- internal class GolangComponent : IDisposable, IJpegComponent
- {
- public GolangComponent(byte identifier, int index)
- {
- this.Identifier = identifier;
- this.Index = index;
- }
-
- ///
- /// Gets the identifier
- ///
- public byte Identifier { get; }
-
- ///
- public int Index { get; }
-
- public Size SizeInBlocks { get; private set; }
-
- public Size SamplingFactors { get; private set; }
-
- public Size SubSamplingDivisors { get; private set; }
-
- public int HorizontalSamplingFactor => this.SamplingFactors.Width;
-
- public int VerticalSamplingFactor => this.SamplingFactors.Height;
-
- ///
- public int QuantizationTableIndex { get; private set; }
-
- ///
- ///
- /// Gets the storing the "raw" frequency-domain decoded blocks.
- /// We need to apply IDCT, dequantiazition and unzigging to transform them into color-space blocks.
- /// This is done by .
- /// When us true, we are touching these blocks multiple times - each time we process a Scan.
- ///
- public Buffer2D SpectralBlocks { get; private set; }
-
- ///
- /// Initializes
- ///
- /// The to use for buffer allocations.
- /// The instance
- public void InitializeDerivedData(MemoryAllocator memoryAllocator, GolangJpegDecoderCore decoder)
- {
- // For 4-component images (either CMYK or YCbCrK), we only support two
- // hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22].
- // Theoretically, 4-component JPEG images could mix and match hv values
- // but in practice, those two combinations are the only ones in use,
- // and it simplifies the applyBlack code below if we can assume that:
- // - for CMYK, the C and K channels have full samples, and if the M
- // and Y channels subsample, they subsample both horizontally and
- // vertically.
- // - for YCbCrK, the Y and K channels have full samples.
- this.SizeInBlocks = decoder.ImageSizeInMCU.MultiplyBy(this.SamplingFactors);
-
- if (this.Index == 0 || this.Index == 3)
- {
- this.SubSamplingDivisors = new Size(1, 1);
- }
- else
- {
- GolangComponent c0 = decoder.Components[0];
- this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors);
- }
-
- this.SpectralBlocks = memoryAllocator.Allocate2D(this.SizeInBlocks.Width, this.SizeInBlocks.Height, true);
- }
-
- ///
- /// Initializes all component data except .
- ///
- /// The instance
- public void InitializeCoreData(GolangJpegDecoderCore decoder)
- {
- // Section B.2.2 states that "the value of C_i shall be different from
- // the values of C_1 through C_(i-1)".
- int i = this.Index;
-
- for (int j = 0; j < this.Index; j++)
- {
- if (this.Identifier == decoder.Components[j].Identifier)
- {
- throw new ImageFormatException("Repeated component identifier");
- }
- }
-
- this.QuantizationTableIndex = decoder.Temp[8 + (3 * i)];
- if (this.QuantizationTableIndex > GolangJpegDecoderCore.MaxTq)
- {
- throw new ImageFormatException("Bad Tq value");
- }
-
- byte hv = decoder.Temp[7 + (3 * i)];
- int h = hv >> 4;
- int v = hv & 0x0f;
- if (h < 1 || h > 4 || v < 1 || v > 4)
- {
- throw new ImageFormatException("Unsupported Luma/chroma subsampling ratio");
- }
-
- if (h == 3 || v == 3)
- {
- throw new ImageFormatException("Lnsupported subsampling ratio");
- }
-
- switch (decoder.ComponentCount)
- {
- case 1:
-
- // If a JPEG image has only one component, section A.2 says "this data
- // is non-interleaved by definition" and section A.2.2 says "[in this
- // case...] the order of data units within a scan shall be left-to-right
- // and top-to-bottom... regardless of the values of H_1 and V_1". Section
- // 4.8.2 also says "[for non-interleaved data], the MCU is defined to be
- // one data unit". Similarly, section A.1.1 explains that it is the ratio
- // of H_i to max_j(H_j) that matters, and similarly for V. For grayscale
- // images, H_1 is the maximum H_j for all components j, so that ratio is
- // always 1. The component's (h, v) is effectively always (1, 1): even if
- // the nominal (h, v) is (2, 1), a 20x5 image is encoded in three 8x8
- // MCUs, not two 16x8 MCUs.
- h = 1;
- v = 1;
- break;
-
- case 3:
-
- // For YCbCr images, we only support 4:4:4, 4:4:0, 4:2:2, 4:2:0,
- // 4:1:1 or 4:1:0 chroma subsampling ratios. This implies that the
- // (h, v) values for the Y component are either (1, 1), (1, 2),
- // (2, 1), (2, 2), (4, 1) or (4, 2), and the Y component's values
- // must be a multiple of the Cb and Cr component's values. We also
- // assume that the two chroma components have the same subsampling
- // ratio.
- switch (i)
- {
- case 0:
- {
- // Y.
- // We have already verified, above, that h and v are both
- // either 1, 2 or 4, so invalid (h, v) combinations are those
- // with v == 4.
- if (v == 4)
- {
- throw new ImageFormatException("Unsupported subsampling ratio");
- }
-
- break;
- }
-
- case 1:
- {
- // Cb.
- Size s0 = decoder.Components[0].SamplingFactors;
-
- if (s0.Width % h != 0 || s0.Height % v != 0)
- {
- throw new ImageFormatException("Unsupported subsampling ratio");
- }
-
- break;
- }
-
- case 2:
- {
- // Cr.
- Size s1 = decoder.Components[1].SamplingFactors;
-
- if (s1.Width != h || s1.Height != v)
- {
- throw new ImageFormatException("Unsupported subsampling ratio");
- }
-
- break;
- }
- }
-
- break;
-
- case 4:
-
- // For 4-component images (either CMYK or YCbCrK), we only support two
- // hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22].
- // Theoretically, 4-component JPEG images could mix and match hv values
- // but in practice, those two combinations are the only ones in use,
- // and it simplifies the applyBlack code below if we can assume that:
- // - for CMYK, the C and K channels have full samples, and if the M
- // and Y channels subsample, they subsample both horizontally and
- // vertically.
- // - for YCbCrK, the Y and K channels have full samples.
- switch (i)
- {
- case 0:
- if (hv != 0x11 && hv != 0x22)
- {
- throw new ImageFormatException("Unsupported subsampling ratio");
- }
-
- break;
- case 1:
- case 2:
- if (hv != 0x11)
- {
- throw new ImageFormatException("Unsupported subsampling ratio");
- }
-
- break;
- case 3:
- Size s0 = decoder.Components[0].SamplingFactors;
-
- if (s0.Width != h || s0.Height != v)
- {
- throw new ImageFormatException("Unsupported subsampling ratio");
- }
-
- break;
- }
-
- break;
- }
-
- this.SamplingFactors = new Size(h, v);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ref Block8x8 GetBlockReference(int column, int row)
- {
- return ref this.SpectralBlocks[column, row];
- }
-
- public void Dispose()
- {
- this.SpectralBlocks?.Dispose();
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangComponentScan.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangComponentScan.cs
deleted file mode 100644
index 6752768ff..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangComponentScan.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.Runtime.InteropServices;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Represents a component scan
- ///
- [StructLayout(LayoutKind.Sequential)]
- internal struct GolangComponentScan
- {
- ///
- /// Gets or sets the component index.
- ///
- public byte ComponentIndex;
-
- ///
- /// Gets or sets the DC table selector
- ///
- public byte DcTableSelector;
-
- ///
- /// Gets or sets the AC table selector
- ///
- public byte AcTableSelector;
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangDecoderErrorCode.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangDecoderErrorCode.cs
deleted file mode 100644
index fa3364527..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangDecoderErrorCode.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Represents "recoverable" decoder errors.
- ///
- internal enum GolangDecoderErrorCode
- {
- ///
- /// NoError
- ///
- NoError,
-
- ///
- /// MissingFF00
- ///
- // ReSharper disable once InconsistentNaming
- MissingFF00,
-
- ///
- /// End of stream reached unexpectedly
- ///
- UnexpectedEndOfStream
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangHuffmanTree.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangHuffmanTree.cs
deleted file mode 100644
index dccce2aaa..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangHuffmanTree.cs
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Represents a Huffman tree
- ///
- [StructLayout(LayoutKind.Sequential)]
- internal unsafe struct GolangHuffmanTree
- {
- ///
- /// The index of the AC table row
- ///
- public const int AcTableIndex = 1;
-
- ///
- /// The index of the DC table row
- ///
- public const int DcTableIndex = 0;
-
- ///
- /// The maximum (inclusive) number of codes in a Huffman tree.
- ///
- public const int MaxNCodes = 256;
-
- ///
- /// The maximum (inclusive) number of bits in a Huffman code.
- ///
- public const int MaxCodeLength = 16;
-
- ///
- /// The maximum number of Huffman table classes
- ///
- public const int MaxTc = 1;
-
- ///
- /// The maximum number of Huffman table identifiers
- ///
- public const int MaxTh = 3;
-
- ///
- /// Row size of the Huffman table
- ///
- public const int ThRowSize = MaxTh + 1;
-
- ///
- /// Number of Hufman Trees in the Huffman table
- ///
- public const int NumberOfTrees = (MaxTc + 1) * (MaxTh + 1);
-
- ///
- /// The log-2 size of the Huffman decoder's look-up table.
- ///
- public const int LutSizeLog2 = 8;
-
- ///
- /// Gets or sets the number of codes in the tree.
- ///
- public int Length;
-
- ///
- /// Gets the look-up table for the next LutSize bits in the bit-stream.
- /// The high 8 bits of the uint16 are the encoded value. The low 8 bits
- /// are 1 plus the code length, or 0 if the value is too large to fit in
- /// lutSize bits.
- ///
- public FixedInt32Buffer256 Lut;
-
- ///
- /// Gets the the decoded values, sorted by their encoding.
- ///
- public FixedInt32Buffer256 Values;
-
- ///
- /// Gets the array of minimum codes.
- /// MinCodes[i] is the minimum code of length i, or -1 if there are no codes of that length.
- ///
- public FixedInt32Buffer16 MinCodes;
-
- ///
- /// Gets the array of maximum codes.
- /// MaxCodes[i] is the maximum code of length i, or -1 if there are no codes of that length.
- ///
- public FixedInt32Buffer16 MaxCodes;
-
- ///
- /// Gets the array of indices. Indices[i] is the index into Values of MinCodes[i].
- ///
- public FixedInt32Buffer16 Indices;
-
- ///
- /// Creates and initializes an array of instances of size
- ///
- /// An array of instances representing the Huffman tables
- public static GolangHuffmanTree[] CreateHuffmanTrees()
- {
- return new GolangHuffmanTree[NumberOfTrees];
- }
-
- ///
- /// Internal part of the DHT processor, whatever does it mean
- ///
- /// The decoder instance
- /// The temporary buffer that holds the data that has been read from the Jpeg stream
- /// Remaining bits
- public void ProcessDefineHuffmanTablesMarkerLoop(
- ref InputProcessor inputProcessor,
- byte[] defineHuffmanTablesData,
- ref int remaining)
- {
- // Read nCodes and huffman.Valuess (and derive h.Length).
- // nCodes[i] is the number of codes with code length i.
- // h.Length is the total number of codes.
- this.Length = 0;
-
- int[] ncodes = new int[MaxCodeLength];
- for (int i = 0; i < ncodes.Length; i++)
- {
- ncodes[i] = defineHuffmanTablesData[i + 1];
- this.Length += ncodes[i];
- }
-
- if (this.Length == 0)
- {
- throw new ImageFormatException("Huffman table has zero length");
- }
-
- if (this.Length > MaxNCodes)
- {
- throw new ImageFormatException("Huffman table has excessive length");
- }
-
- remaining -= this.Length + 17;
- if (remaining < 0)
- {
- throw new ImageFormatException("DHT has wrong length");
- }
-
- byte[] values = new byte[MaxNCodes];
- inputProcessor.ReadFull(values, 0, this.Length);
-
- fixed (int* valuesPtr = this.Values.Data)
- fixed (int* lutPtr = this.Lut.Data)
- {
- for (int i = 0; i < values.Length; i++)
- {
- valuesPtr[i] = values[i];
- }
-
- // Derive the look-up table.
- for (int i = 0; i < MaxNCodes; i++)
- {
- lutPtr[i] = 0;
- }
-
- int x = 0, code = 0;
-
- for (int i = 0; i < LutSizeLog2; i++)
- {
- code <<= 1;
-
- for (int j = 0; j < ncodes[i]; j++)
- {
- // The codeLength is 1+i, so shift code by 8-(1+i) to
- // calculate the high bits for every 8-bit sequence
- // whose codeLength's high bits matches code.
- // The high 8 bits of lutValue are the encoded value.
- // The low 8 bits are 1 plus the codeLength.
- int base2 = code << (7 - i);
- int lutValue = (valuesPtr[x] << 8) | (2 + i);
-
- for (int k = 0; k < 1 << (7 - i); k++)
- {
- lutPtr[base2 | k] = lutValue;
- }
-
- code++;
- x++;
- }
- }
- }
-
- fixed (int* minCodesPtr = this.MinCodes.Data)
- fixed (int* maxCodesPtr = this.MaxCodes.Data)
- fixed (int* indicesPtr = this.Indices.Data)
- {
- // Derive minCodes, maxCodes, and indices.
- int c = 0, index = 0;
- for (int i = 0; i < ncodes.Length; i++)
- {
- int nc = ncodes[i];
- if (nc == 0)
- {
- minCodesPtr[i] = -1;
- maxCodesPtr[i] = -1;
- indicesPtr[i] = -1;
- }
- else
- {
- minCodesPtr[i] = c;
- maxCodesPtr[i] = c + nc - 1;
- indicesPtr[i] = index;
- c += nc;
- index += nc;
- }
-
- c <<= 1;
- }
- }
- }
-
- ///
- /// Gets the value for the given code and index.
- ///
- /// The code
- /// The code length
- /// The value
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public int GetValue(int code, int codeLength)
- {
- return this.Values[this.Indices[codeLength] + code - this.MinCodes[codeLength]];
- }
-
- [StructLayout(LayoutKind.Sequential)]
- internal struct FixedInt32Buffer256
- {
- public fixed int Data[256];
-
- public int this[int idx]
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- ref int self = ref Unsafe.As(ref this);
- return Unsafe.Add(ref self, idx);
- }
- }
- }
-
- [StructLayout(LayoutKind.Sequential)]
- internal struct FixedInt32Buffer16
- {
- public fixed int Data[16];
-
- public int this[int idx]
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- ref int self = ref Unsafe.As(ref this);
- return Unsafe.Add(ref self, idx);
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangJpegScanDecoder.ComputationData.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangJpegScanDecoder.ComputationData.cs
deleted file mode 100644
index f3c8aa91b..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangJpegScanDecoder.ComputationData.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.Runtime.InteropServices;
-
-using SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Conains the definition of
- ///
- internal unsafe partial struct GolangJpegScanDecoder
- {
- ///
- /// Holds the "large" data blocks needed for computations.
- ///
- [StructLayout(LayoutKind.Sequential)]
- public struct ComputationData
- {
- ///
- /// The main input/working block
- ///
- public Block8x8 Block;
-
- ///
- /// The jpeg unzig data
- ///
- public ZigZag Unzig;
-
- ///
- /// The buffer storing the -s for each component
- ///
- public fixed byte ScanData[3 * GolangJpegDecoderCore.MaxComponents];
-
- ///
- /// The DC values for each component
- ///
- public fixed int Dc[GolangJpegDecoderCore.MaxComponents];
-
- ///
- /// Creates and initializes a new instance
- ///
- /// The
- public static ComputationData Create()
- {
- ComputationData data = default;
- data.Unzig = ZigZag.CreateUnzigTable();
- return data;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangJpegScanDecoder.DataPointers.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangJpegScanDecoder.DataPointers.cs
deleted file mode 100644
index a00da6fca..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangJpegScanDecoder.DataPointers.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Conains the definition of
- ///
- internal unsafe partial struct GolangJpegScanDecoder
- {
- ///
- /// Contains pointers to the memory regions of so they can be easily passed around to pointer based utility methods of
- ///
- public struct DataPointers
- {
- ///
- /// Pointer to
- ///
- public Block8x8* Block;
-
- ///
- /// Pointer to as byte*
- ///
- public byte* Unzig;
-
- ///
- /// Pointer to as Scan*
- ///
- public GolangComponentScan* ComponentScan;
-
- ///
- /// Pointer to
- ///
- public int* Dc;
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The pointer pointing to
- public DataPointers(ComputationData* basePtr)
- {
- this.Block = &basePtr->Block;
- this.Unzig = basePtr->Unzig.Data;
- this.ComponentScan = (GolangComponentScan*)basePtr->ScanData;
- this.Dc = basePtr->Dc;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangJpegScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangJpegScanDecoder.cs
deleted file mode 100644
index 3a88cfad4..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/GolangJpegScanDecoder.cs
+++ /dev/null
@@ -1,705 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-using SixLabors.ImageSharp.Formats.Jpeg.Components;
-
-// ReSharper disable InconsistentNaming
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Encapsulates the impementation of Jpeg SOS Huffman decoding. See JpegScanDecoder.md!
- ///
- /// and are the spectral selection bounds.
- /// and are the successive approximation high and low values.
- /// The spec calls these values Ss, Se, Ah and Al.
- /// For progressive JPEGs, these are the two more-or-less independent
- /// aspects of progression. Spectral selection progression is when not
- /// all of a block's 64 DCT coefficients are transmitted in one pass.
- /// For example, three passes could transmit coefficient 0 (the DC
- /// component), coefficients 1-5, and coefficients 6-63, in zig-zag
- /// order. Successive approximation is when not all of the bits of a
- /// band of coefficients are transmitted in one pass. For example,
- /// three passes could transmit the 6 most significant bits, followed
- /// by the second-least significant bit, followed by the least
- /// significant bit.
- /// For baseline JPEGs, these parameters are hard-coded to 0/63/0/0.
- ///
- [StructLayout(LayoutKind.Sequential)]
- internal unsafe partial struct GolangJpegScanDecoder
- {
- // The JpegScanDecoder members should be ordered in a way that results in optimal memory layout.
-#pragma warning disable SA1202 // ElementsMustBeOrderedByAccess
-
- ///
- /// The buffer
- ///
- private ComputationData data;
-
- ///
- /// Pointers to elements of
- ///
- private DataPointers pointers;
-
- ///
- /// The current component index
- ///
- public int ComponentIndex;
-
- ///
- /// X coordinate of the current block, in units of 8x8. (The third block in the first row has (bx, by) = (2, 0))
- ///
- private int bx;
-
- ///
- /// Y coordinate of the current block, in units of 8x8. (The third block in the first row has (bx, by) = (2, 0))
- ///
- private int by;
-
- ///
- /// Start index of the zig-zag selection bound
- ///
- private int zigStart;
-
- ///
- /// End index of the zig-zag selection bound
- ///
- private int zigEnd;
-
- ///
- /// Successive approximation high value
- ///
- private int ah;
-
- ///
- /// Successive approximation low value
- ///
- private int al;
-
- ///
- /// The number of component scans
- ///
- private int componentScanCount;
-
- ///
- /// Horizontal sampling factor at the current component index
- ///
- private int hi;
-
- ///
- /// End-of-Band run, specified in section G.1.2.2.
- ///
- private int eobRun;
-
- ///
- /// The block counter
- ///
- private int blockCounter;
-
- ///
- /// The MCU counter
- ///
- private int mcuCounter;
-
- ///
- /// The expected RST marker value
- ///
- private byte expectedRst;
-
- ///
- /// Initializes a default-constructed instance for reading data from -s stream.
- ///
- /// Pointer to on the stack
- /// The instance
- /// The remaining bytes in the segment block.
- public static void InitStreamReading(GolangJpegScanDecoder* p, GolangJpegDecoderCore decoder, int remaining)
- {
- p->data = ComputationData.Create();
- p->pointers = new DataPointers(&p->data);
- p->InitStreamReadingImpl(decoder, remaining);
- }
-
- ///
- /// Read Huffman data from Jpeg scans in ,
- /// and decode it as into .
- ///
- /// The blocks are traversed one MCU at a time. For 4:2:0 chroma
- /// subsampling, there are four Y 8x8 blocks in every 16x16 MCU.
- /// For a baseline 32x16 pixel image, the Y blocks visiting order is:
- /// 0 1 4 5
- /// 2 3 6 7
- /// For progressive images, the interleaved scans (those with component count > 1)
- /// are traversed as above, but non-interleaved scans are traversed left
- /// to right, top to bottom:
- /// 0 1 2 3
- /// 4 5 6 7
- /// Only DC scans (zigStart == 0) can be interleave AC scans must have
- /// only one component.
- /// To further complicate matters, for non-interleaved scans, there is no
- /// data for any blocks that are inside the image at the MCU level but
- /// outside the image at the pixel level. For example, a 24x16 pixel 4:2:0
- /// progressive image consists of two 16x16 MCUs. The interleaved scans
- /// will process 8 Y blocks:
- /// 0 1 4 5
- /// 2 3 6 7
- /// The non-interleaved scans will process only 6 Y blocks:
- /// 0 1 2
- /// 3 4 5
- ///
- /// The instance
- public void DecodeBlocks(GolangJpegDecoderCore decoder)
- {
- decoder.InputProcessor.ResetErrorState();
-
- this.blockCounter = 0;
- this.mcuCounter = 0;
- this.expectedRst = JpegConstants.Markers.RST0;
-
- for (int my = 0; my < decoder.MCUCountY; my++)
- {
- for (int mx = 0; mx < decoder.MCUCountX; mx++)
- {
- this.DecodeBlocksAtMcuIndex(decoder, mx, my);
-
- this.mcuCounter++;
-
- // Handling restart intervals
- // Useful info: https://stackoverflow.com/a/8751802
- if (decoder.IsAtRestartInterval(this.mcuCounter))
- {
- this.ProcessRSTMarker(decoder);
- this.Reset(decoder);
- }
- }
- }
- }
-
- private void DecodeBlocksAtMcuIndex(GolangJpegDecoderCore decoder, int mx, int my)
- {
- for (int scanIndex = 0; scanIndex < this.componentScanCount; scanIndex++)
- {
- this.ComponentIndex = this.pointers.ComponentScan[scanIndex].ComponentIndex;
- GolangComponent component = decoder.Components[this.ComponentIndex];
-
- this.hi = component.HorizontalSamplingFactor;
- int vi = component.VerticalSamplingFactor;
-
- for (int j = 0; j < this.hi * vi; j++)
- {
- if (this.componentScanCount != 1)
- {
- this.bx = (this.hi * mx) + (j % this.hi);
- this.by = (vi * my) + (j / this.hi);
- }
- else
- {
- int q = decoder.MCUCountX * this.hi;
- this.bx = this.blockCounter % q;
- this.by = this.blockCounter / q;
- this.blockCounter++;
- if (this.bx * 8 >= decoder.ImageWidth || this.by * 8 >= decoder.ImageHeight)
- {
- continue;
- }
- }
-
- // Find the block at (bx,by) in the component's buffer:
- ref Block8x8 blockRefOnHeap = ref component.GetBlockReference(this.bx, this.by);
-
- // Copy block to stack
- this.data.Block = blockRefOnHeap;
-
- if (!decoder.InputProcessor.ReachedEOF)
- {
- this.DecodeBlock(decoder, scanIndex);
- }
-
- // Store the result block:
- blockRefOnHeap = this.data.Block;
- }
- }
- }
-
- private void ProcessRSTMarker(GolangJpegDecoderCore decoder)
- {
- // Attempt to look for RST[0-7] markers to resynchronize from corrupt input.
- if (!decoder.InputProcessor.ReachedEOF)
- {
- decoder.InputProcessor.ReadFullUnsafe(decoder.Temp, 0, 2);
- if (decoder.InputProcessor.CheckEOFEnsureNoError())
- {
- if (decoder.Temp[0] != 0xFF || decoder.Temp[1] != this.expectedRst)
- {
- bool invalidRst = true;
-
- // Most jpeg's containing well-formed input will have a RST[0-7] marker following immediately
- // but some, see Issue #481, contain padding bytes "0xFF" before the RST[0-7] marker.
- // If we identify that case we attempt to read until we have bypassed the padded bytes.
- // We then check again for our RST marker and throw if invalid.
- // No other methods are attempted to resynchronize from corrupt input.
- if (decoder.Temp[0] == 0xFF && decoder.Temp[1] == 0xFF)
- {
- while (decoder.Temp[0] == 0xFF && decoder.InputProcessor.CheckEOFEnsureNoError())
- {
- decoder.InputProcessor.ReadFullUnsafe(decoder.Temp, 0, 1);
- if (!decoder.InputProcessor.CheckEOFEnsureNoError())
- {
- break;
- }
- }
-
- // Have we found a valid restart marker?
- invalidRst = decoder.Temp[0] != this.expectedRst;
- }
-
- if (invalidRst)
- {
- throw new ImageFormatException("Bad RST marker");
- }
- }
-
- this.expectedRst++;
- if (this.expectedRst == JpegConstants.Markers.RST7 + 1)
- {
- this.expectedRst = JpegConstants.Markers.RST0;
- }
- }
- }
- }
-
- private void Reset(GolangJpegDecoderCore decoder)
- {
- decoder.InputProcessor.ResetHuffmanDecoder();
-
- this.ResetDcValues();
-
- // Reset the progressive decoder state, as per section G.1.2.2.
- this.eobRun = 0;
- }
-
- ///
- /// Reset the DC components, as per section F.2.1.3.1.
- ///
- private void ResetDcValues()
- {
- Unsafe.InitBlock(this.pointers.Dc, default, sizeof(int) * GolangJpegDecoderCore.MaxComponents);
- }
-
- ///
- /// The implementation part of as an instance method.
- ///
- /// The
- /// The remaining bytes
- private void InitStreamReadingImpl(GolangJpegDecoderCore decoder, int remaining)
- {
- if (decoder.ComponentCount == 0)
- {
- throw new ImageFormatException("Missing SOF marker");
- }
-
- if (remaining < 6 || 4 + (2 * decoder.ComponentCount) < remaining || remaining % 2 != 0)
- {
- throw new ImageFormatException("SOS has wrong length");
- }
-
- decoder.InputProcessor.ReadFull(decoder.Temp, 0, remaining);
- this.componentScanCount = decoder.Temp[0];
-
- int scanComponentCountX2 = 2 * this.componentScanCount;
- if (remaining != 4 + scanComponentCountX2)
- {
- throw new ImageFormatException("SOS length inconsistent with number of components");
- }
-
- int totalHv = 0;
-
- for (int i = 0; i < this.componentScanCount; i++)
- {
- this.InitComponentScan(decoder, i, ref this.pointers.ComponentScan[i], ref totalHv);
- }
-
- // Section B.2.3 states that if there is more than one component then the
- // total H*V values in a scan must be <= 10.
- if (decoder.ComponentCount > 1 && totalHv > 10)
- {
- throw new ImageFormatException("Total sampling factors too large.");
- }
-
- this.zigEnd = Block8x8F.Size - 1;
-
- if (decoder.IsProgressive)
- {
- this.zigStart = decoder.Temp[1 + scanComponentCountX2];
- this.zigEnd = decoder.Temp[2 + scanComponentCountX2];
- this.ah = decoder.Temp[3 + scanComponentCountX2] >> 4;
- this.al = decoder.Temp[3 + scanComponentCountX2] & 0x0f;
-
- if ((this.zigStart == 0 && this.zigEnd != 0) || this.zigStart > this.zigEnd
- || this.zigEnd >= Block8x8F.Size)
- {
- throw new ImageFormatException("Bad spectral selection bounds");
- }
-
- if (this.zigStart != 0 && this.componentScanCount != 1)
- {
- throw new ImageFormatException("Progressive AC coefficients for more than one component");
- }
-
- if (this.ah != 0 && this.ah != this.al + 1)
- {
- throw new ImageFormatException("Bad successive approximation values");
- }
- }
- }
-
- ///
- /// Read the current the current block at (, ) from the decoders stream
- ///
- /// The decoder
- /// The index of the scan
- private void DecodeBlock(GolangJpegDecoderCore decoder, int scanIndex)
- {
- Block8x8* b = this.pointers.Block;
- int huffmannIdx = (GolangHuffmanTree.AcTableIndex * GolangHuffmanTree.ThRowSize) + this.pointers.ComponentScan[scanIndex].AcTableSelector;
- if (this.ah != 0)
- {
- this.Refine(ref decoder.InputProcessor, ref decoder.HuffmanTrees[huffmannIdx], 1 << this.al);
- }
- else
- {
- int zig = this.zigStart;
-
- if (zig == 0)
- {
- zig++;
-
- // Decode the DC coefficient, as specified in section F.2.2.1.
- int huffmanIndex = (GolangHuffmanTree.DcTableIndex * GolangHuffmanTree.ThRowSize) + this.pointers.ComponentScan[scanIndex].DcTableSelector;
- decoder.InputProcessor.DecodeHuffmanUnsafe(
- ref decoder.HuffmanTrees[huffmanIndex],
- out int value);
- if (!decoder.InputProcessor.CheckEOF())
- {
- return;
- }
-
- if (value > 16)
- {
- throw new ImageFormatException("Excessive DC component");
- }
-
- decoder.InputProcessor.ReceiveExtendUnsafe(value, out int deltaDC);
- if (!decoder.InputProcessor.CheckEOFEnsureNoError())
- {
- return;
- }
-
- this.pointers.Dc[this.ComponentIndex] += deltaDC;
-
- // b[0] = dc[compIndex] << al;
- value = this.pointers.Dc[this.ComponentIndex] << this.al;
- Block8x8.SetScalarAt(b, 0, (short)value);
- }
-
- if (zig <= this.zigEnd && this.eobRun > 0)
- {
- this.eobRun--;
- }
- else
- {
- // Decode the AC coefficients, as specified in section F.2.2.2.
- for (; zig <= this.zigEnd; zig++)
- {
- decoder.InputProcessor.DecodeHuffmanUnsafe(ref decoder.HuffmanTrees[huffmannIdx], out int value);
- if (decoder.InputProcessor.HasError)
- {
- return;
- }
-
- int val0 = value >> 4;
- int val1 = value & 0x0f;
- if (val1 != 0)
- {
- zig += val0;
- if (zig > this.zigEnd)
- {
- break;
- }
-
- decoder.InputProcessor.ReceiveExtendUnsafe(val1, out int ac);
- if (decoder.InputProcessor.HasError)
- {
- return;
- }
-
- // b[Unzig[zig]] = ac << al;
- value = ac << this.al;
- Block8x8.SetScalarAt(b, this.pointers.Unzig[zig], (short)value);
- }
- else
- {
- if (val0 != 0x0f)
- {
- this.eobRun = (ushort)(1 << val0);
- if (val0 != 0)
- {
- this.DecodeEobRun(val0, ref decoder.InputProcessor);
- if (!decoder.InputProcessor.CheckEOFEnsureNoError())
- {
- return;
- }
- }
-
- this.eobRun--;
- break;
- }
-
- zig += 0x0f;
- }
- }
- }
- }
- }
-
- private void DecodeEobRun(int count, ref InputProcessor processor)
- {
- processor.DecodeBitsUnsafe(count, out int bitsResult);
- if (processor.LastErrorCode != GolangDecoderErrorCode.NoError)
- {
- return;
- }
-
- this.eobRun |= bitsResult;
- }
-
- private void InitComponentScan(GolangJpegDecoderCore decoder, int i, ref GolangComponentScan currentComponentScan, ref int totalHv)
- {
- // Component selector.
- int cs = decoder.Temp[1 + (2 * i)];
- int compIndex = -1;
- for (int j = 0; j < decoder.ComponentCount; j++)
- {
- // Component compv = ;
- if (cs == decoder.Components[j].Identifier)
- {
- compIndex = j;
- }
- }
-
- if (compIndex < 0)
- {
- throw new ImageFormatException("Unknown component selector");
- }
-
- currentComponentScan.ComponentIndex = (byte)compIndex;
-
- this.ProcessComponentImpl(decoder, i, ref currentComponentScan, ref totalHv, decoder.Components[compIndex]);
- }
-
- private void ProcessComponentImpl(
- GolangJpegDecoderCore decoder,
- int i,
- ref GolangComponentScan currentComponentScan,
- ref int totalHv,
- GolangComponent currentComponent)
- {
- // Section B.2.3 states that "the value of Cs_j shall be different from
- // the values of Cs_1 through Cs_(j-1)". Since we have previously
- // verified that a frame's component identifiers (C_i values in section
- // B.2.2) are unique, it suffices to check that the implicit indexes
- // into comp are unique.
- for (int j = 0; j < i; j++)
- {
- if (currentComponentScan.ComponentIndex == this.pointers.ComponentScan[j].ComponentIndex)
- {
- throw new ImageFormatException("Repeated component selector");
- }
- }
-
- totalHv += currentComponent.HorizontalSamplingFactor * currentComponent.VerticalSamplingFactor;
-
- currentComponentScan.DcTableSelector = (byte)(decoder.Temp[2 + (2 * i)] >> 4);
- if (currentComponentScan.DcTableSelector > GolangHuffmanTree.MaxTh)
- {
- throw new ImageFormatException("Bad DC table selector value");
- }
-
- currentComponentScan.AcTableSelector = (byte)(decoder.Temp[2 + (2 * i)] & 0x0f);
- if (currentComponentScan.AcTableSelector > GolangHuffmanTree.MaxTh)
- {
- throw new ImageFormatException("Bad AC table selector value");
- }
- }
-
- ///
- /// Decodes a successive approximation refinement block, as specified in section G.1.2.
- ///
- /// The instance
- /// The Huffman tree
- /// The low transform offset
- private void Refine(ref InputProcessor bp, ref GolangHuffmanTree h, int delta)
- {
- Block8x8* b = this.pointers.Block;
-
- // Refining a DC component is trivial.
- if (this.zigStart == 0)
- {
- if (this.zigEnd != 0)
- {
- throw new ImageFormatException("Invalid state for zig DC component");
- }
-
- bp.DecodeBitUnsafe(out bool bit);
- if (!bp.CheckEOFEnsureNoError())
- {
- return;
- }
-
- if (bit)
- {
- int stuff = Block8x8.GetScalarAt(b, 0);
-
- // int stuff = (int)b[0];
- stuff |= delta;
-
- // b[0] = stuff;
- Block8x8.SetScalarAt(b, 0, (short)stuff);
- }
-
- return;
- }
-
- // Refining AC components is more complicated; see sections G.1.2.2 and G.1.2.3.
- int zig = this.zigStart;
- if (this.eobRun == 0)
- {
- for (; zig <= this.zigEnd; zig++)
- {
- bool done = false;
- int z = 0;
-
- bp.DecodeHuffmanUnsafe(ref h, out int val);
- if (!bp.CheckEOF())
- {
- return;
- }
-
- int val0 = val >> 4;
- int val1 = val & 0x0f;
-
- switch (val1)
- {
- case 0:
- if (val0 != 0x0f)
- {
- this.eobRun = 1 << val0;
- if (val0 != 0)
- {
- this.DecodeEobRun(val0, ref bp);
- if (!bp.CheckEOFEnsureNoError())
- {
- return;
- }
- }
-
- done = true;
- }
-
- break;
- case 1:
- z = delta;
-
- bp.DecodeBitUnsafe(out bool bit);
- if (!bp.CheckEOFEnsureNoError())
- {
- return;
- }
-
- if (!bit)
- {
- z = -z;
- }
-
- break;
- default:
- throw new ImageFormatException("Unexpected Huffman code");
- }
-
- if (done)
- {
- break;
- }
-
- zig = this.RefineNonZeroes(ref bp, zig, val0, delta);
-
- if (bp.ReachedEOF || bp.HasError)
- {
- return;
- }
-
- if (z != 0 && zig <= this.zigEnd)
- {
- // b[Unzig[zig]] = z;
- Block8x8.SetScalarAt(b, this.pointers.Unzig[zig], (short)z);
- }
- }
- }
-
- if (this.eobRun > 0)
- {
- this.eobRun--;
- this.RefineNonZeroes(ref bp, zig, -1, delta);
- }
- }
-
- ///
- /// Refines non-zero entries of b in zig-zag order.
- /// If >= 0, the first zero entries are skipped over.
- ///
- /// The
- /// The zig-zag start index
- /// The non-zero entry
- /// The low transform offset
- /// The
- private int RefineNonZeroes(ref InputProcessor bp, int zig, int nz, int delta)
- {
- Block8x8* b = this.pointers.Block;
- for (; zig <= this.zigEnd; zig++)
- {
- int u = this.pointers.Unzig[zig];
- int bu = Block8x8.GetScalarAt(b, u);
-
- // TODO: Are the equality comparsions OK with floating point values? Isn't an epsilon value necessary?
- if (bu == 0)
- {
- if (nz == 0)
- {
- break;
- }
-
- nz--;
- continue;
- }
-
- bp.DecodeBitUnsafe(out bool bit);
- if (bp.HasError)
- {
- return int.MinValue;
- }
-
- if (!bit)
- {
- continue;
- }
-
- int val = bu >= 0 ? bu + delta : bu - delta;
-
- Block8x8.SetScalarAt(b, u, (short)val);
- }
-
- return zig;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs
deleted file mode 100644
index c7e14ee4f..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs
+++ /dev/null
@@ -1,392 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.IO;
-using System.Runtime.CompilerServices;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// Encapsulates stream reading and processing data and operations for .
- /// It's a value type for imporved data locality, and reduced number of CALLVIRT-s
- ///
- internal struct InputProcessor : IDisposable
- {
- ///
- /// Holds the unprocessed bits that have been taken from the byte-stream.
- ///
- public Bits Bits;
-
- ///
- /// The byte buffer
- ///
- public Bytes Bytes;
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The input
- /// Temporal buffer, same as
- public InputProcessor(Stream inputStream, byte[] temp)
- {
- this.Bits = default;
- this.Bytes = Bytes.Create();
- this.InputStream = inputStream;
- this.Temp = temp;
- this.LastErrorCode = GolangDecoderErrorCode.NoError;
- }
-
- ///
- /// Gets the input stream
- ///
- public Stream InputStream { get; }
-
- ///
- /// Gets the temporary buffer, same instance as
- ///
- public byte[] Temp { get; }
-
- ///
- /// Gets a value indicating whether an unexpected EOF reached in .
- ///
- public bool ReachedEOF => this.LastErrorCode == GolangDecoderErrorCode.UnexpectedEndOfStream;
-
- public bool HasError => this.LastErrorCode != GolangDecoderErrorCode.NoError;
-
- public GolangDecoderErrorCode LastErrorCode { get; private set; }
-
- public void ResetErrorState() => this.LastErrorCode = GolangDecoderErrorCode.NoError;
-
- ///
- /// If errorCode indicates unexpected EOF, sets to true and returns false.
- /// Calls and returns true otherwise.
- ///
- /// A indicating whether EOF reached
- public bool CheckEOFEnsureNoError()
- {
- if (this.LastErrorCode == GolangDecoderErrorCode.UnexpectedEndOfStream)
- {
- return false;
- }
-
- this.LastErrorCode.EnsureNoError();
- return true;
- }
-
- ///
- /// If errorCode indicates unexpected EOF, sets to true and returns false.
- /// Returns true otherwise.
- ///
- /// A indicating whether EOF reached
- public bool CheckEOF()
- {
- if (this.LastErrorCode == GolangDecoderErrorCode.UnexpectedEndOfStream)
- {
- return false;
- }
-
- return true;
- }
-
- ///
- public void Dispose()
- {
- this.Bytes.Dispose();
- }
-
- ///
- /// Returns the next byte, whether buffered or not buffered. It does not care about byte stuffing.
- ///
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public byte ReadByte()
- {
- return this.Bytes.ReadByte(this.InputStream);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public GolangDecoderErrorCode ReadByteUnsafe(out byte result)
- {
- this.LastErrorCode = this.Bytes.ReadByteUnsafe(this.InputStream, out result);
- return this.LastErrorCode;
- }
-
- ///
- /// Decodes a single bit
- /// TODO: This method (and also the usages) could be optimized by batching!
- ///
- /// The decoded bit as a
- /// The
- public GolangDecoderErrorCode DecodeBitUnsafe(out bool result)
- {
- if (this.Bits.UnreadBits == 0)
- {
- this.LastErrorCode = this.Bits.Ensure1BitUnsafe(ref this);
- if (this.LastErrorCode != GolangDecoderErrorCode.NoError)
- {
- result = false;
- return this.LastErrorCode;
- }
- }
-
- result = (this.Bits.Accumulator & this.Bits.Mask) != 0;
- this.Bits.UnreadBits--;
- this.Bits.Mask >>= 1;
- return this.LastErrorCode = GolangDecoderErrorCode.NoError;
- }
-
- ///
- /// Reads exactly length bytes into data. It does not care about byte stuffing.
- /// Does not throw on errors, returns instead!
- ///
- /// The data to write to.
- /// The offset in the source buffer
- /// The number of bytes to read
- /// The
- public GolangDecoderErrorCode ReadFullUnsafe(byte[] data, int offset, int length)
- {
- // Unread the overshot bytes, if any.
- if (this.Bytes.UnreadableBytes != 0)
- {
- if (this.Bits.UnreadBits >= 8)
- {
- this.UnreadByteStuffedByte();
- }
-
- this.Bytes.UnreadableBytes = 0;
- }
-
- this.LastErrorCode = GolangDecoderErrorCode.NoError;
- while (length > 0 && this.LastErrorCode == GolangDecoderErrorCode.NoError)
- {
- if (this.Bytes.J - this.Bytes.I >= length)
- {
- Array.Copy(this.Bytes.Buffer, this.Bytes.I, data, offset, length);
- this.Bytes.I += length;
- length -= length;
- }
- else
- {
- Array.Copy(this.Bytes.Buffer, this.Bytes.I, data, offset, this.Bytes.J - this.Bytes.I);
- offset += this.Bytes.J - this.Bytes.I;
- length -= this.Bytes.J - this.Bytes.I;
- this.Bytes.I += this.Bytes.J - this.Bytes.I;
-
- this.LastErrorCode = this.Bytes.FillUnsafe(this.InputStream);
- }
- }
-
- return this.LastErrorCode;
- }
-
- ///
- /// Decodes the given number of bits
- ///
- /// The number of bits to decode.
- /// The result
- /// The
- public GolangDecoderErrorCode DecodeBitsUnsafe(int count, out int result)
- {
- if (this.Bits.UnreadBits < count)
- {
- this.LastErrorCode = this.Bits.EnsureNBitsUnsafe(count, ref this);
- if (this.LastErrorCode != GolangDecoderErrorCode.NoError)
- {
- result = 0;
- return this.LastErrorCode;
- }
- }
-
- result = this.Bits.Accumulator >> (this.Bits.UnreadBits - count);
- result = result & ((1 << count) - 1);
- this.Bits.UnreadBits -= count;
- this.Bits.Mask >>= count;
- return this.LastErrorCode = GolangDecoderErrorCode.NoError;
- }
-
- ///
- /// Extracts the next Huffman-coded value from the bit-stream into result, decoded according to the given value.
- ///
- /// The huffman value
- /// The decoded
- /// The
- public GolangDecoderErrorCode DecodeHuffmanUnsafe(ref GolangHuffmanTree huffmanTree, out int result)
- {
- result = 0;
-
- if (huffmanTree.Length == 0)
- {
- DecoderThrowHelper.ThrowImageFormatException.UninitializedHuffmanTable();
- }
-
- if (this.Bits.UnreadBits < 8)
- {
- this.LastErrorCode = this.Bits.Ensure8BitsUnsafe(ref this);
-
- if (this.LastErrorCode == GolangDecoderErrorCode.NoError)
- {
- int lutIndex = (this.Bits.Accumulator >> (this.Bits.UnreadBits - GolangHuffmanTree.LutSizeLog2)) & 0xFF;
- int v = huffmanTree.Lut[lutIndex];
-
- if (v != 0)
- {
- int n = (v & 0xFF) - 1;
- this.Bits.UnreadBits -= n;
- this.Bits.Mask >>= n;
- result = v >> 8;
- return this.LastErrorCode;
- }
- }
- else
- {
- this.UnreadByteStuffedByte();
- return this.LastErrorCode;
- }
- }
-
- int code = 0;
- for (int i = 0; i < GolangHuffmanTree.MaxCodeLength; i++)
- {
- if (this.Bits.UnreadBits == 0)
- {
- this.LastErrorCode = this.Bits.EnsureNBitsUnsafe(1, ref this);
-
- if (this.HasError)
- {
- return this.LastErrorCode;
- }
- }
-
- if ((this.Bits.Accumulator & this.Bits.Mask) != 0)
- {
- code |= 1;
- }
-
- this.Bits.UnreadBits--;
- this.Bits.Mask >>= 1;
-
- if (code <= huffmanTree.MaxCodes[i])
- {
- result = huffmanTree.GetValue(code, i);
- return this.LastErrorCode = GolangDecoderErrorCode.NoError;
- }
-
- code <<= 1;
- }
-
- // Unrecoverable error, throwing:
- DecoderThrowHelper.ThrowImageFormatException.BadHuffmanCode();
-
- // DUMMY RETURN! C# doesn't know we have thrown an exception!
- return GolangDecoderErrorCode.NoError;
- }
-
- ///
- /// Skips the next n bytes.
- ///
- /// The number of bytes to ignore.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Skip(int count)
- {
- this.LastErrorCode = this.SkipUnsafe(count);
- this.LastErrorCode.EnsureNoError();
- }
-
- ///
- /// Skips the next n bytes.
- /// Does not throw, returns instead!
- ///
- /// The number of bytes to ignore.
- /// The
- public GolangDecoderErrorCode SkipUnsafe(int count)
- {
- // Unread the overshot bytes, if any.
- if (this.Bytes.UnreadableBytes != 0)
- {
- if (this.Bits.UnreadBits >= 8)
- {
- this.UnreadByteStuffedByte();
- }
-
- this.Bytes.UnreadableBytes = 0;
- }
-
- while (true)
- {
- int m = this.Bytes.J - this.Bytes.I;
- if (m > count)
- {
- m = count;
- }
-
- this.Bytes.I += m;
- count -= m;
- if (count == 0)
- {
- break;
- }
-
- this.LastErrorCode = this.Bytes.FillUnsafe(this.InputStream);
- if (this.LastErrorCode != GolangDecoderErrorCode.NoError)
- {
- return this.LastErrorCode;
- }
- }
-
- return this.LastErrorCode = GolangDecoderErrorCode.NoError;
- }
-
- ///
- /// Reads exactly length bytes into data. It does not care about byte stuffing.
- ///
- /// The data to write to.
- /// The offset in the source buffer
- /// The number of bytes to read
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ReadFull(byte[] data, int offset, int length)
- {
- this.LastErrorCode = this.ReadFullUnsafe(data, offset, length);
- this.LastErrorCode.EnsureNoError();
- }
-
- ///
- /// Undoes the most recent ReadByteStuffedByte call,
- /// giving a byte of data back from bits to bytes. The Huffman look-up table
- /// requires at least 8 bits for look-up, which means that Huffman decoding can
- /// sometimes overshoot and read one or two too many bytes. Two-byte overshoot
- /// can happen when expecting to read a 0xff 0x00 byte-stuffed byte.
- ///
- public void UnreadByteStuffedByte()
- {
- this.Bytes.I -= this.Bytes.UnreadableBytes;
- this.Bytes.UnreadableBytes = 0;
- if (this.Bits.UnreadBits >= 8)
- {
- this.Bits.Accumulator >>= 8;
- this.Bits.UnreadBits -= 8;
- this.Bits.Mask >>= 8;
- }
- }
-
- ///
- /// Receive extend
- ///
- /// Byte
- /// Read bits value
- /// The
- public GolangDecoderErrorCode ReceiveExtendUnsafe(int t, out int x)
- {
- this.LastErrorCode = this.Bits.ReceiveExtendUnsafe(t, ref this, out x);
- return this.LastErrorCode;
- }
-
- ///
- /// Reset the Huffman decoder.
- ///
- public void ResetHuffmanDecoder()
- {
- this.Bits = default;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegScanDecoder.md b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegScanDecoder.md
deleted file mode 100644
index 4ca4d1f64..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegScanDecoder.md
+++ /dev/null
@@ -1,25 +0,0 @@
-## JpegScanDecoder
-Encapsulates the impementation of the Jpeg top-to bottom scan decoder triggered by the `SOS` marker.
-The implementation is optimized to hold most of the necessary data in a single value type, which is intended to be used as an on-stack object.
-
-#### Benefits:
-- Maximized locality of reference by keeping most of the operation data on the stack
-- Achieving this without long parameter lists, most of the values describing the state of the decoder algorithm
-are members of the `JpegScanDecoder` struct
-- Most of the logic related to Scan decoding is refactored & simplified now to live in the methods of `JpegScanDecoder`
-- The first step is done towards separating the stream reading from block processing. They can be refactored later to be executed in two disctinct loops.
- - The input processing loop can be `async`
- - The block processing loop can be parallelized
-
-#### Data layout
-
-|JpegScanDecoder |
-|-------------------|
-|Variables |
-|DataPointers |
-|ComputationData |
-
-- **ComputationData** holds the "large" data blocks needed for computations (Mostly `Block8x8F`-s)
-- **DataPointers** contains pointers to the memory regions of `ComponentData` so they can be easily passed around to pointer based utility methods of `Block8x8F`
-
-
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/MissingFF00Exception.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/MissingFF00Exception.cs
deleted file mode 100644
index 005034b9d..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/MissingFF00Exception.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- ///
- /// The missing ff00 exception.
- ///
- // ReSharper disable once InconsistentNaming
- internal class MissingFF00Exception : Exception
- {
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoder.cs
deleted file mode 100644
index 29255204b..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoder.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.IO;
-using SixLabors.ImageSharp.PixelFormats;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
-{
- ///
- /// Image decoder for generating an image out of a jpg stream.
- ///
- internal sealed class GolangJpegDecoder : IImageDecoder, IJpegDecoderOptions, IImageInfoDetector
- {
- ///
- /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
- ///
- public bool IgnoreMetadata { get; set; }
-
- ///
- public Image Decode(Configuration configuration, Stream stream)
- where TPixel : struct, IPixel
- {
- Guard.NotNull(stream, nameof(stream));
-
- using (var decoder = new GolangJpegDecoderCore(configuration, this))
- {
- return decoder.Decode(stream);
- }
- }
-
- ///
- public IImageInfo Identify(Configuration configuration, Stream stream)
- {
- Guard.NotNull(stream, nameof(stream));
-
- using (var decoder = new GolangJpegDecoderCore(configuration, this))
- {
- return decoder.Identify(stream);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoderCore.cs
deleted file mode 100644
index 46cdcddb4..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/GolangJpegDecoderCore.cs
+++ /dev/null
@@ -1,824 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.Collections.Generic;
-using System.IO;
-
-using SixLabors.ImageSharp.Formats.Jpeg.Components;
-using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
-using SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder;
-using SixLabors.ImageSharp.MetaData;
-using SixLabors.ImageSharp.MetaData.Profiles.Exif;
-using SixLabors.ImageSharp.MetaData.Profiles.Icc;
-using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Primitives;
-using SixLabors.Primitives;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
-{
- ///
- ///
- /// Performs the jpeg decoding operation.
- ///
- internal sealed unsafe class GolangJpegDecoderCore : IRawJpegData
- {
- ///
- /// The maximum number of color components
- ///
- public const int MaxComponents = 4;
-
- ///
- /// The maximum number of quantization tables
- ///
- public const int MaxTq = 3;
-
- ///
- /// The only supported precision
- ///
- public const int SupportedPrecision = 8;
-
- // Complex value type field + mutable + available to other classes = the field MUST NOT be private :P
-#pragma warning disable SA1401 // FieldsMustBePrivate
-
- ///
- /// Encapsulates stream reading and processing data and operations for .
- /// It's a value type for improved data locality, and reduced number of CALLVIRT-s
- ///
- public InputProcessor InputProcessor;
-#pragma warning restore SA401
-
- ///
- /// The global configuration
- ///
- private readonly Configuration configuration;
-
- ///
- /// Whether the image has a JFIF header
- /// It's faster to check this than to use the equality operator on the struct
- ///
- private bool isJFif;
-
- ///
- /// Contains information about the JFIF marker
- ///
- private JFifMarker jFif;
-
- ///
- /// Whether the image has a EXIF header
- ///
- private bool isExif;
-
- ///
- /// Whether the image has an Adobe marker.
- /// It's faster to check this than to use the equality operator on the struct
- ///
- private bool isAdobe;
-
- ///
- /// Contains information about the Adobe marker
- ///
- private AdobeMarker adobe;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The configuration.
- /// The options.
- public GolangJpegDecoderCore(Configuration configuration, IJpegDecoderOptions options)
- {
- this.IgnoreMetadata = options.IgnoreMetadata;
- this.configuration = configuration ?? Configuration.Default;
- this.Temp = new byte[2 * Block8x8F.Size];
- }
-
- ///
- public JpegColorSpace ColorSpace { get; private set; }
-
- ///
- /// Gets the component array
- ///
- public GolangComponent[] Components { get; private set; }
-
- ///
- /// Gets the huffman trees
- ///
- public GolangHuffmanTree[] HuffmanTrees { get; private set; }
-
- ///
- public Block8x8F[] QuantizationTables { get; private set; }
-
- ///
- /// Gets the temporary buffer used to store bytes read from the stream.
- /// TODO: Should be stack allocated, fixed sized buffer!
- ///
- public byte[] Temp { get; }
-
- ///
- public Size ImageSizeInPixels { get; private set; }
-
- ///
- /// Gets the number of MCU blocks in the image as .
- ///
- public Size ImageSizeInMCU { get; private set; }
-
- ///
- public int ComponentCount { get; private set; }
-
- IEnumerable IRawJpegData.Components => this.Components;
-
- ///
- /// Gets the color depth, in number of bits per pixel.
- ///
- public int BitsPerPixel => this.ComponentCount * SupportedPrecision;
-
- ///
- /// Gets the image height
- ///
- public int ImageHeight => this.ImageSizeInPixels.Height;
-
- ///
- /// Gets the image width
- ///
- public int ImageWidth => this.ImageSizeInPixels.Width;
-
- ///
- /// Gets the input stream.
- ///
- public Stream InputStream { get; private set; }
-
- ///
- /// Gets a value indicating whether the image is interlaced (progressive)
- ///
- public bool IsProgressive { get; private set; }
-
- ///
- /// Gets the restart interval
- ///
- public int RestartInterval { get; private set; }
-
- ///
- /// Gets the number of MCU-s (Minimum Coded Units) in the image along the X axis
- ///
- public int MCUCountX => this.ImageSizeInMCU.Width;
-
- ///
- /// Gets the number of MCU-s (Minimum Coded Units) in the image along the Y axis
- ///
- public int MCUCountY => this.ImageSizeInMCU.Height;
-
- ///
- /// Gets the total number of MCU-s (Minimum Coded Units) in the image.
- ///
- public int TotalMCUCount => this.MCUCountX * this.MCUCountY;
-
- ///
- /// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
- ///
- public bool IgnoreMetadata { get; }
-
- ///
- /// Gets the decoded by this decoder instance.
- ///
- public ImageMetaData MetaData { get; private set; }
-
- ///
- /// Decodes the image from the specified and sets
- /// the data to image.
- ///
- /// The pixel format.
- /// The stream, where the image should be.
- /// The decoded image.
- public Image Decode(Stream stream)
- where TPixel : struct, IPixel
- {
- this.ParseStream(stream);
- return this.PostProcessIntoImage();
- }
-
- ///
- /// Reads the raw image information from the specified stream.
- ///
- /// The containing image data.
- public IImageInfo Identify(Stream stream)
- {
- this.ParseStream(stream, true);
- return new ImageInfo(new PixelTypeInfo(this.BitsPerPixel), this.ImageWidth, this.ImageHeight, this.MetaData);
- }
-
- ///
- public void Dispose()
- {
- if (this.Components != null)
- {
- foreach (GolangComponent component in this.Components)
- {
- component?.Dispose();
- }
- }
-
- this.InputProcessor.Dispose();
- }
-
- ///
- /// Read metadata from stream and read the blocks in the scans into .
- ///
- /// The stream
- /// Whether to decode metadata only.
- public void ParseStream(Stream stream, bool metadataOnly = false)
- {
- this.MetaData = new ImageMetaData();
- this.InputStream = stream;
- this.InputProcessor = new InputProcessor(stream, this.Temp);
-
- if (!metadataOnly)
- {
- this.HuffmanTrees = GolangHuffmanTree.CreateHuffmanTrees();
- this.QuantizationTables = new Block8x8F[MaxTq + 1];
- }
-
- // Check for the Start Of Image marker.
- this.InputProcessor.ReadFull(this.Temp, 0, 2);
-
- if (this.Temp[0] != JpegConstants.Markers.XFF || this.Temp[1] != JpegConstants.Markers.SOI)
- {
- throw new ImageFormatException("Missing SOI marker.");
- }
-
- // Process the remaining segments until the End Of Image marker.
- bool processBytes = true;
-
- // we can't currently short circute progressive images so don't try.
- while (processBytes)
- {
- this.InputProcessor.ReadFull(this.Temp, 0, 2);
-
- if (this.InputProcessor.ReachedEOF)
- {
- // We've reached the end of the stream.
- processBytes = false;
- }
-
- while (this.Temp[0] != 0xff)
- {
- // Strictly speaking, this is a format error. However, libjpeg is
- // liberal in what it accepts. As of version 9, next_marker in
- // jdmarker.c treats this as a warning (JWRN_EXTRANEOUS_DATA) and
- // continues to decode the stream. Even before next_marker sees
- // extraneous data, jpeg_fill_bit_buffer in jdhuff.c reads as many
- // bytes as it can, possibly past the end of a scan's data. It
- // effectively puts back any markers that it overscanned (e.g. an
- // "\xff\xd9" EOI marker), but it does not put back non-marker data,
- // and thus it can silently ignore a small number of extraneous
- // non-marker bytes before next_marker has a chance to see them (and
- // print a warning).
- // We are therefore also liberal in what we accept. Extraneous data
- // is silently ignore
- // This is similar to, but not exactly the same as, the restart
- // mechanism within a scan (the RST[0-7] markers).
- // Note that extraneous 0xff bytes in e.g. SOS data are escaped as
- // "\xff\x00", and so are detected a little further down below.
- this.Temp[0] = this.Temp[1];
- this.Temp[1] = this.InputProcessor.ReadByte();
- }
-
- byte marker = this.Temp[1];
- if (marker == 0)
- {
- // Treat "\xff\x00" as extraneous data.
- continue;
- }
-
- while (marker == 0xff)
- {
- // Section B.1.1.2 says, "Any marker may optionally be preceded by any
- // number of fill bytes, which are bytes assigned code X'FF'".
- this.InputProcessor.ReadByteUnsafe(out marker);
-
- if (this.InputProcessor.ReachedEOF)
- {
- // We've reached the end of the stream.
- processBytes = false;
- break;
- }
- }
-
- // End Of Image.
- if (marker == JpegConstants.Markers.EOI)
- {
- break;
- }
-
- if (marker >= JpegConstants.Markers.RST0 && marker <= JpegConstants.Markers.RST7)
- {
- // Figures B.2 and B.16 of the specification suggest that restart markers should
- // only occur between Entropy Coded Segments and not after the final ECS.
- // However, some encoders may generate incorrect JPEGs with a final restart
- // marker. That restart marker will be seen here instead of inside the ProcessSOS
- // method, and is ignored as a harmless error. Restart markers have no extra data,
- // so we check for this before we read the 16-bit length of the segment.
- continue;
- }
-
- // Read the 16-bit length of the segment. The value includes the 2 bytes for the
- // length itself, so we subtract 2 to get the number of remaining bytes.
- this.InputProcessor.ReadFullUnsafe(this.Temp, 0, 2);
- int remaining = (this.Temp[0] << 8) + this.Temp[1] - 2;
- if (remaining < 0)
- {
- throw new ImageFormatException("Short segment length.");
- }
-
- switch (marker)
- {
- case JpegConstants.Markers.SOF0:
- case JpegConstants.Markers.SOF1:
- case JpegConstants.Markers.SOF2:
- this.IsProgressive = marker == JpegConstants.Markers.SOF2;
- this.ProcessStartOfFrameMarker(remaining, metadataOnly);
-
- break;
- case JpegConstants.Markers.DHT:
-
- if (metadataOnly)
- {
- this.InputProcessor.Skip(remaining);
- }
- else
- {
- this.ProcessDefineHuffmanTablesMarker(remaining);
- }
-
- break;
- case JpegConstants.Markers.DQT:
- if (metadataOnly)
- {
- this.InputProcessor.Skip(remaining);
- }
- else
- {
- this.ProcessDefineQuantizationTablesMarker(remaining);
- }
-
- break;
- case JpegConstants.Markers.SOS:
- if (!metadataOnly)
- {
- this.ProcessStartOfScanMarker(remaining);
- if (this.InputProcessor.ReachedEOF)
- {
- // If unexpected EOF reached. We can stop processing bytes as we now have the image data.
- processBytes = false;
- }
- }
- else
- {
- // It's highly unlikely that APPn related data will be found after the SOS marker
- // We should have gathered everything we need by now.
- processBytes = false;
- }
-
- break;
-
- case JpegConstants.Markers.DRI:
- if (metadataOnly)
- {
- this.InputProcessor.Skip(remaining);
- }
- else
- {
- this.ProcessDefineRestartIntervalMarker(remaining);
- }
-
- break;
- case JpegConstants.Markers.APP0:
- this.ProcessApplicationHeaderMarker(remaining);
- break;
- case JpegConstants.Markers.APP1:
- this.ProcessApp1Marker(remaining);
- break;
- case JpegConstants.Markers.APP2:
- this.ProcessApp2Marker(remaining);
- break;
- case JpegConstants.Markers.APP14:
- this.ProcessApp14Marker(remaining);
- break;
- default:
- if ((marker >= JpegConstants.Markers.APP0 && marker <= JpegConstants.Markers.APP15)
- || marker == JpegConstants.Markers.COM)
- {
- this.InputProcessor.Skip(remaining);
- }
-
- break;
- }
- }
-
- this.InitDerivedMetaDataProperties();
- }
-
- ///
- /// Returns true if 'mcuCounter' is at restart interval
- ///
- public bool IsAtRestartInterval(int mcuCounter)
- {
- return this.RestartInterval > 0 && mcuCounter % this.RestartInterval == 0
- && mcuCounter < this.TotalMCUCount;
- }
-
- ///
- /// Assigns derived metadata properties to , eg. horizontal and vertical resolution if it has a JFIF header.
- ///
- private void InitDerivedMetaDataProperties()
- {
- if (this.isJFif)
- {
- this.MetaData.HorizontalResolution = this.jFif.XDensity;
- this.MetaData.VerticalResolution = this.jFif.YDensity;
- }
- else if (this.isExif)
- {
- double horizontalValue = this.MetaData.ExifProfile.TryGetValue(ExifTag.XResolution, out ExifValue horizonalTag)
- ? ((Rational)horizonalTag.Value).ToDouble()
- : 0;
-
- double verticalValue = this.MetaData.ExifProfile.TryGetValue(ExifTag.YResolution, out ExifValue verticalTag)
- ? ((Rational)verticalTag.Value).ToDouble()
- : 0;
-
- if (horizontalValue > 0 && verticalValue > 0)
- {
- this.MetaData.HorizontalResolution = horizontalValue;
- this.MetaData.VerticalResolution = verticalValue;
- }
- }
-
- if (this.MetaData.IccProfile?.CheckIsValid() == false)
- {
- this.MetaData.IccProfile = null;
- }
- }
-
- ///
- /// Processes the application header containing the JFIF identifier plus extra data.
- ///
- /// The remaining bytes in the segment block.
- private void ProcessApplicationHeaderMarker(int remaining)
- {
- if (remaining < 5)
- {
- this.InputProcessor.Skip(remaining);
- return;
- }
-
- const int MarkerLength = JFifMarker.Length;
- this.InputProcessor.ReadFull(this.Temp, 0, MarkerLength);
- remaining -= MarkerLength;
-
- this.isJFif = JFifMarker.TryParse(this.Temp, out this.jFif);
-
- if (remaining > 0)
- {
- this.InputProcessor.Skip(remaining);
- }
- }
-
- ///
- /// Processes the App1 marker retrieving any stored metadata
- ///
- /// The remaining bytes in the segment block.
- private void ProcessApp1Marker(int remaining)
- {
- if (remaining < 6 || this.IgnoreMetadata)
- {
- this.InputProcessor.Skip(remaining);
- return;
- }
-
- byte[] profile = new byte[remaining];
- this.InputProcessor.ReadFull(profile, 0, remaining);
-
- if (ProfileResolver.IsProfile(profile, ProfileResolver.ExifMarker))
- {
- this.isExif = true;
- this.MetaData.ExifProfile = new ExifProfile(profile);
- }
- }
-
- ///
- /// Processes the App2 marker retrieving any stored ICC profile information
- ///
- /// The remaining bytes in the segment block.
- private void ProcessApp2Marker(int remaining)
- {
- // Length is 14 though we only need to check 12.
- const int Icclength = 14;
- if (remaining < Icclength || this.IgnoreMetadata)
- {
- this.InputProcessor.Skip(remaining);
- return;
- }
-
- byte[] identifier = new byte[Icclength];
- this.InputProcessor.ReadFull(identifier, 0, Icclength);
- remaining -= Icclength; // We have read it by this point
-
- if (ProfileResolver.IsProfile(identifier, ProfileResolver.IccMarker))
- {
- byte[] profile = new byte[remaining];
- this.InputProcessor.ReadFull(profile, 0, remaining);
-
- if (this.MetaData.IccProfile == null)
- {
- this.MetaData.IccProfile = new IccProfile(profile);
- }
- else
- {
- this.MetaData.IccProfile.Extend(profile);
- }
- }
- else
- {
- // Not an ICC profile we can handle. Skip the remaining bytes so we can carry on and ignore this.
- this.InputProcessor.Skip(remaining);
- }
- }
-
- ///
- /// Processes the application header containing the Adobe identifier
- /// which stores image encoding information for DCT filters.
- ///
- /// The remaining bytes in the segment block.
- private void ProcessApp14Marker(int remaining)
- {
- const int MarkerLength = AdobeMarker.Length;
- if (remaining < MarkerLength)
- {
- // Skip the application header length
- this.InputProcessor.Skip(remaining);
- return;
- }
-
- this.InputProcessor.ReadFull(this.Temp, 0, MarkerLength);
- remaining -= MarkerLength;
-
- this.isAdobe = AdobeMarker.TryParse(this.Temp, out this.adobe);
-
- if (remaining > 0)
- {
- this.InputProcessor.Skip(remaining);
- }
- }
-
- ///
- /// Processes the Define Quantization Marker and tables. Specified in section B.2.4.1.
- ///
- /// The remaining bytes in the segment block.
- ///
- /// Thrown if the tables do not match the header
- ///
- private void ProcessDefineQuantizationTablesMarker(int remaining)
- {
- while (remaining > 0)
- {
- bool done = false;
-
- remaining--;
- byte x = this.InputProcessor.ReadByte();
- int tq = x & 0x0F;
- if (tq > MaxTq)
- {
- throw new ImageFormatException("Bad Tq value");
- }
-
- switch (x >> 4)
- {
- case 0:
- if (remaining < Block8x8F.Size)
- {
- done = true;
- break;
- }
-
- remaining -= Block8x8F.Size;
- this.InputProcessor.ReadFull(this.Temp, 0, Block8x8F.Size);
-
- for (int i = 0; i < Block8x8F.Size; i++)
- {
- this.QuantizationTables[tq][i] = this.Temp[i];
- }
-
- break;
- case 1:
- if (remaining < 2 * Block8x8F.Size)
- {
- done = true;
- break;
- }
-
- remaining -= 2 * Block8x8F.Size;
- this.InputProcessor.ReadFull(this.Temp, 0, 2 * Block8x8F.Size);
-
- for (int i = 0; i < Block8x8F.Size; i++)
- {
- this.QuantizationTables[tq][i] = (this.Temp[2 * i] << 8) | this.Temp[(2 * i) + 1];
- }
-
- break;
- default:
- throw new ImageFormatException("Bad Pq value");
- }
-
- if (done)
- {
- break;
- }
- }
-
- if (remaining != 0)
- {
- throw new ImageFormatException("DQT has wrong length");
- }
- }
-
- ///
- /// Processes the Start of Frame marker. Specified in section B.2.2.
- ///
- /// The remaining bytes in the segment block.
- /// Whether to decode metadata only.
- private void ProcessStartOfFrameMarker(int remaining, bool metadataOnly)
- {
- if (this.ComponentCount != 0)
- {
- throw new ImageFormatException("Multiple SOF markers");
- }
-
- switch (remaining)
- {
- case 6 + (3 * 1): // grayscale image.
- this.ComponentCount = 1;
- break;
- case 6 + (3 * 3): // YCbCr or RGB image.
- this.ComponentCount = 3;
- break;
- case 6 + (3 * 4): // YCbCrK or CMYK image.
- this.ComponentCount = 4;
- break;
- default:
- throw new ImageFormatException("Incorrect number of components");
- }
-
- this.InputProcessor.ReadFull(this.Temp, 0, remaining);
-
- // We only support 8-bit precision.
- if (this.Temp[0] != SupportedPrecision)
- {
- throw new ImageFormatException("Only 8-Bit precision supported.");
- }
-
- int height = (this.Temp[1] << 8) + this.Temp[2];
- int width = (this.Temp[3] << 8) + this.Temp[4];
-
- this.ImageSizeInPixels = new Size(width, height);
-
- if (this.Temp[5] != this.ComponentCount)
- {
- throw new ImageFormatException("SOF has wrong length");
- }
-
- if (!metadataOnly)
- {
- this.Components = new GolangComponent[this.ComponentCount];
-
- for (int i = 0; i < this.ComponentCount; i++)
- {
- byte componentIdentifier = this.Temp[6 + (3 * i)];
- var component = new GolangComponent(componentIdentifier, i);
- component.InitializeCoreData(this);
- this.Components[i] = component;
- }
-
- int h0 = this.Components[0].HorizontalSamplingFactor;
- int v0 = this.Components[0].VerticalSamplingFactor;
-
- this.ImageSizeInMCU = this.ImageSizeInPixels.DivideRoundUp(8 * h0, 8 * v0);
-
- this.ColorSpace = this.DeduceJpegColorSpace();
-
- foreach (GolangComponent component in this.Components)
- {
- component.InitializeDerivedData(this.configuration.MemoryAllocator, this);
- }
- }
- }
-
- ///
- /// Processes a Define Huffman Table marker, and initializes a huffman
- /// struct from its contents. Specified in section B.2.4.2.
- ///
- /// The remaining bytes in the segment block.
- private void ProcessDefineHuffmanTablesMarker(int remaining)
- {
- while (remaining > 0)
- {
- if (remaining < 17)
- {
- throw new ImageFormatException($"DHT has wrong length. {remaining}");
- }
-
- this.InputProcessor.ReadFull(this.Temp, 0, 17);
-
- int tc = this.Temp[0] >> 4;
- if (tc > GolangHuffmanTree.MaxTc)
- {
- throw new ImageFormatException("Bad Tc value");
- }
-
- int th = this.Temp[0] & 0x0f;
- if (th > GolangHuffmanTree.MaxTh)
- {
- throw new ImageFormatException("Bad Th value");
- }
-
- int huffTreeIndex = (tc * GolangHuffmanTree.ThRowSize) + th;
- this.HuffmanTrees[huffTreeIndex].ProcessDefineHuffmanTablesMarkerLoop(
- ref this.InputProcessor,
- this.Temp,
- ref remaining);
- }
- }
-
- ///
- /// Processes the DRI (Define Restart Interval Marker) Which specifies the interval between RSTn markers, in
- /// macroblocks
- ///
- /// The remaining bytes in the segment block.
- private void ProcessDefineRestartIntervalMarker(int remaining)
- {
- if (remaining != 2)
- {
- throw new ImageFormatException("DRI has wrong length");
- }
-
- this.InputProcessor.ReadFull(this.Temp, 0, remaining);
- this.RestartInterval = (this.Temp[0] << 8) + this.Temp[1];
- }
-
- ///
- /// Processes the SOS (Start of scan marker).
- ///
- /// The remaining bytes in the segment block.
- ///
- /// Missing SOF Marker
- /// SOS has wrong length
- ///
- private void ProcessStartOfScanMarker(int remaining)
- {
- GolangJpegScanDecoder scan = default;
- GolangJpegScanDecoder.InitStreamReading(&scan, this, remaining);
- this.InputProcessor.Bits = default;
- scan.DecodeBlocks(this);
- }
-
- private JpegColorSpace DeduceJpegColorSpace()
- {
- switch (this.ComponentCount)
- {
- case 1:
- return JpegColorSpace.Grayscale;
- case 3:
- if (!this.isAdobe || this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformYCbCr)
- {
- return JpegColorSpace.YCbCr;
- }
-
- if (this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformUnknown)
- {
- return JpegColorSpace.RGB;
- }
-
- break;
- case 4:
- if (this.adobe.ColorTransform == JpegConstants.Adobe.ColorTransformYcck)
- {
- return JpegColorSpace.Ycck;
- }
-
- return JpegColorSpace.Cmyk;
- }
-
- throw new ImageFormatException($"Unsupported color mode. Max components 4; found {this.ComponentCount}."
- + "JpegDecoder only supports YCbCr, RGB, YccK, CMYK and grayscale color spaces.");
- }
-
- private Image PostProcessIntoImage()
- where TPixel : struct, IPixel
- {
- using (var postProcessor = new JpegImagePostProcessor(this.configuration.MemoryAllocator, this))
- {
- var image = new Image(this.configuration, this.ImageWidth, this.ImageHeight, this.MetaData);
- postProcessor.PostProcess(image.Frames.RootFrame);
- return image;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
index eafbb391c..57b70dd26 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
@@ -2,8 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System.IO;
-
-using SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Jpeg
@@ -24,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{
Guard.NotNull(stream, nameof(stream));
- using (var decoder = new PdfJsJpegDecoderCore(configuration, this))
+ using (var decoder = new JpegDecoderCore(configuration, this))
{
return decoder.Decode(stream);
}
@@ -35,7 +33,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{
Guard.NotNull(stream, nameof(stream));
- using (var decoder = new PdfJsJpegDecoderCore(configuration, this))
+ using (var decoder = new JpegDecoderCore(configuration, this))
{
return decoder.Identify(stream);
}
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
similarity index 92%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
rename to src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
index a360d5477..3b34719a8 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
@@ -7,10 +7,10 @@ using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-
+using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
-using SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components;
+using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.MetaData.Profiles.Icc;
@@ -19,14 +19,14 @@ using SixLabors.ImageSharp.Primitives;
using SixLabors.Memory;
using SixLabors.Primitives;
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
+namespace SixLabors.ImageSharp.Formats.Jpeg
{
///
/// Performs the jpeg decoding operation.
/// Originally ported from
/// with additional fixes for both performance and common encoding errors.
///
- internal sealed class PdfJsJpegDecoderCore : IRawJpegData
+ internal sealed class JpegDecoderCore : IRawJpegData
{
///
/// The only supported precision
@@ -51,12 +51,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
///
/// The DC HUffman tables
///
- private PdfJsHuffmanTables dcHuffmanTables;
+ private HuffmanTables dcHuffmanTables;
///
/// The AC HUffman tables
///
- private PdfJsHuffmanTables acHuffmanTables;
+ private HuffmanTables acHuffmanTables;
///
/// The fast AC tables used for entropy decoding
@@ -84,11 +84,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
private AdobeMarker adobe;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The configuration.
/// The options.
- public PdfJsJpegDecoderCore(Configuration configuration, IJpegDecoderOptions options)
+ public JpegDecoderCore(Configuration configuration, IJpegDecoderOptions options)
{
this.configuration = configuration ?? Configuration.Default;
this.IgnoreMetadata = options.IgnoreMetadata;
@@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
///
/// Gets the frame
///
- public PdfJsFrame Frame { get; private set; }
+ public JpegFrame Frame { get; private set; }
///
public Size ImageSizeInPixels { get; private set; }
@@ -146,7 +146,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
///
/// Gets the components.
///
- public PdfJsFrameComponent[] Components => this.Frame.Components;
+ public JpegComponent[] Components => this.Frame.Components;
///
IEnumerable IRawJpegData.Components => this.Components;
@@ -159,14 +159,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
///
/// The buffer to read file markers to
/// The input stream
- /// The
- public static PdfJsFileMarker FindNextFileMarker(byte[] marker, DoubleBufferedStreamReader stream)
+ /// The
+ public static JpegFileMarker FindNextFileMarker(byte[] marker, DoubleBufferedStreamReader stream)
{
int value = stream.Read(marker, 0, 2);
if (value == 0)
{
- return new PdfJsFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
+ return new JpegFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
}
if (marker[0] == JpegConstants.Markers.XFF)
@@ -179,16 +179,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
int suffix = stream.ReadByte();
if (suffix == -1)
{
- return new PdfJsFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
+ return new JpegFileMarker(JpegConstants.Markers.EOI, stream.Length - 2);
}
m = suffix;
}
- return new PdfJsFileMarker((byte)m, stream.Position - 2);
+ return new JpegFileMarker((byte)m, stream.Position - 2);
}
- return new PdfJsFileMarker(marker[1], stream.Position - 2, true);
+ return new JpegFileMarker(marker[1], stream.Position - 2, true);
}
///
@@ -228,7 +228,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
// Check for the Start Of Image marker.
this.InputStream.Read(this.markerBuffer, 0, 2);
- var fileMarker = new PdfJsFileMarker(this.markerBuffer[1], 0);
+ var fileMarker = new JpegFileMarker(this.markerBuffer[1], 0);
if (fileMarker.Marker != JpegConstants.Markers.SOI)
{
throw new ImageFormatException("Missing SOI marker.");
@@ -236,14 +236,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.InputStream.Read(this.markerBuffer, 0, 2);
byte marker = this.markerBuffer[1];
- fileMarker = new PdfJsFileMarker(marker, (int)this.InputStream.Position - 2);
+ fileMarker = new JpegFileMarker(marker, (int)this.InputStream.Position - 2);
// Only assign what we need
if (!metadataOnly)
{
this.QuantizationTables = new Block8x8F[4];
- this.dcHuffmanTables = new PdfJsHuffmanTables();
- this.acHuffmanTables = new PdfJsHuffmanTables();
+ this.dcHuffmanTables = new HuffmanTables();
+ this.acHuffmanTables = new HuffmanTables();
this.fastACTables = new FastACTables(this.configuration.MemoryAllocator);
}
@@ -412,6 +412,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
{
this.MetaData.HorizontalResolution = this.jFif.XDensity;
this.MetaData.VerticalResolution = this.jFif.YDensity;
+ this.MetaData.ResolutionUnits = this.jFif.DensityUnits;
}
else if (this.isExif)
{
@@ -427,6 +428,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
{
this.MetaData.HorizontalResolution = horizontalValue;
this.MetaData.VerticalResolution = verticalValue;
+ this.MetaData.ResolutionUnits = UnitConverter.ExifProfileToResolutionUnit(this.MetaData.ExifProfile);
}
}
@@ -628,7 +630,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// The remaining bytes in the segment block.
/// The current frame marker.
/// Whether to parse metadata only
- private void ProcessStartOfFrameMarker(int remaining, PdfJsFileMarker frameMarker, bool metadataOnly)
+ private void ProcessStartOfFrameMarker(int remaining, JpegFileMarker frameMarker, bool metadataOnly)
{
if (this.Frame != null)
{
@@ -643,7 +645,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
throw new ImageFormatException("Only 8-Bit precision supported.");
}
- this.Frame = new PdfJsFrame
+ this.Frame = new JpegFrame
{
Extended = frameMarker.Marker == JpegConstants.Markers.SOF1,
Progressive = frameMarker.Marker == JpegConstants.Markers.SOF2,
@@ -665,7 +667,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
{
// No need to pool this. They max out at 4
this.Frame.ComponentIds = new byte[this.Frame.ComponentCount];
- this.Frame.Components = new PdfJsFrameComponent[this.Frame.ComponentCount];
+ this.Frame.Components = new JpegComponent[this.Frame.ComponentCount];
this.ColorSpace = this.DeduceJpegColorSpace();
for (int i = 0; i < this.Frame.ComponentCount; i++)
@@ -684,7 +686,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
maxV = v;
}
- var component = new PdfJsFrameComponent(this.configuration.MemoryAllocator, this.Frame, this.temp[index], h, v, this.temp[index + 2], i);
+ var component = new JpegComponent(this.configuration.MemoryAllocator, this.Frame, this.temp[index], h, v, this.temp[index + 2], i);
this.Frame.Components[i] = component;
this.Frame.ComponentIds[i] = component.Id;
@@ -707,7 +709,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// The remaining bytes in the segment block.
private void ProcessDefineHuffmanTablesMarker(int remaining)
{
- using (IManagedByteBuffer huffmanData = this.configuration.MemoryAllocator.AllocateCleanManagedByteBuffer(256))
+ using (IManagedByteBuffer huffmanData = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(256, AllocationOptions.Clean))
{
ref byte huffmanDataRef = ref MemoryMarshal.GetReference(huffmanData.GetSpan());
for (int i = 2; i < remaining;)
@@ -715,7 +717,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
byte huffmanTableSpec = (byte)this.InputStream.ReadByte();
this.InputStream.Read(huffmanData.Array, 0, 16);
- using (IManagedByteBuffer codeLengths = this.configuration.MemoryAllocator.AllocateCleanManagedByteBuffer(17))
+ using (IManagedByteBuffer codeLengths = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(17, AllocationOptions.Clean))
{
ref byte codeLengthsRef = ref MemoryMarshal.GetReference(codeLengths.GetSpan());
int codeLengthSum = 0;
@@ -725,7 +727,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
codeLengthSum += Unsafe.Add(ref codeLengthsRef, j) = Unsafe.Add(ref huffmanDataRef, j - 1);
}
- using (IManagedByteBuffer huffmanValues = this.configuration.MemoryAllocator.AllocateCleanManagedByteBuffer(256))
+ using (IManagedByteBuffer huffmanValues = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(256, AllocationOptions.Clean))
{
this.InputStream.Read(huffmanValues.Array, 0, codeLengthSum);
@@ -792,7 +794,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
throw new ImageFormatException("Unknown component selector");
}
- ref PdfJsFrameComponent component = ref this.Frame.Components[componentIndex];
+ ref JpegComponent component = ref this.Frame.Components[componentIndex];
int tableSpec = this.InputStream.ReadByte();
component.DCHuffmanTableId = tableSpec >> 4;
component.ACHuffmanTableId = tableSpec & 15;
@@ -829,9 +831,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// The codelengths
/// The values
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void BuildHuffmanTable(PdfJsHuffmanTables tables, int index, ReadOnlySpan codeLengths, ReadOnlySpan values)
+ private void BuildHuffmanTable(HuffmanTables tables, int index, ReadOnlySpan codeLengths, ReadOnlySpan values)
{
- tables[index] = new PdfJsHuffmanTable(this.configuration.MemoryAllocator, codeLengths, values);
+ tables[index] = new HuffmanTable(this.configuration.MemoryAllocator, codeLengths, values);
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
index 1310d90d2..ada33f2b8 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
@@ -2,11 +2,13 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
using System.IO;
using System.Runtime.CompilerServices;
-
+using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
using SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder;
+using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.MetaData.Profiles.Icc;
using SixLabors.ImageSharp.PixelFormats;
@@ -210,7 +212,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
int componentCount = 3;
// Write the Start Of Image marker.
- this.WriteApplicationHeader((short)image.MetaData.HorizontalResolution, (short)image.MetaData.VerticalResolution);
+ this.WriteApplicationHeader(image.MetaData);
this.WriteProfiles(image);
@@ -425,9 +427,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
///
/// Writes the application header containing the JFIF identifier plus extra data.
///
- /// The resolution of the image in the x- direction.
- /// The resolution of the image in the y- direction.
- private void WriteApplicationHeader(short horizontalResolution, short verticalResolution)
+ /// The image meta data.
+ private void WriteApplicationHeader(ImageMetaData meta)
{
// Write the start of image marker. Markers are always prefixed with with 0xff.
this.buffer[0] = JpegConstants.Markers.XFF;
@@ -445,13 +446,25 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
this.buffer[10] = 0x00; // = "JFIF",'\0'
this.buffer[11] = 0x01; // versionhi
this.buffer[12] = 0x01; // versionlo
- this.buffer[13] = 0x01; // xyunits as dpi
// Resolution. Big Endian
- this.buffer[14] = (byte)(horizontalResolution >> 8);
- this.buffer[15] = (byte)horizontalResolution;
- this.buffer[16] = (byte)(verticalResolution >> 8);
- this.buffer[17] = (byte)verticalResolution;
+ Span hResolution = this.buffer.AsSpan(14, 2);
+ Span vResolution = this.buffer.AsSpan(16, 2);
+
+ if (meta.ResolutionUnits == PixelResolutionUnit.PixelsPerMeter)
+ {
+ // Scale down to PPI
+ this.buffer[13] = (byte)PixelResolutionUnit.PixelsPerInch; // xyunits
+ BinaryPrimitives.WriteInt16BigEndian(hResolution, (short)Math.Round(UnitConverter.MeterToInch(meta.HorizontalResolution)));
+ BinaryPrimitives.WriteInt16BigEndian(vResolution, (short)Math.Round(UnitConverter.MeterToInch(meta.VerticalResolution)));
+ }
+ else
+ {
+ // We can simply pass the value.
+ this.buffer[13] = (byte)meta.ResolutionUnits; // xyunits
+ BinaryPrimitives.WriteInt16BigEndian(hResolution, (short)Math.Round(meta.HorizontalResolution));
+ BinaryPrimitives.WriteInt16BigEndian(vResolution, (short)Math.Round(meta.VerticalResolution));
+ }
// No thumbnail
this.buffer[18] = 0x00; // Thumbnail width
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoder.cs
deleted file mode 100644
index e12278cc7..000000000
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoder.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.IO;
-using SixLabors.ImageSharp.PixelFormats;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
-{
- ///
- /// Image decoder for generating an image out of a jpg stream.
- ///
- internal sealed class PdfJsJpegDecoder : IImageDecoder, IJpegDecoderOptions, IImageInfoDetector
- {
- ///
- /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
- ///
- public bool IgnoreMetadata { get; set; }
-
- ///
- public Image Decode(Configuration configuration, Stream stream)
- where TPixel : struct, IPixel
- {
- Guard.NotNull(stream, nameof(stream));
-
- using (var decoder = new PdfJsJpegDecoderCore(configuration, this))
- {
- return decoder.Decode(stream);
- }
- }
-
- ///
- public IImageInfo Identify(Configuration configuration, Stream stream)
- {
- Guard.NotNull(stream, nameof(stream));
-
- using (var decoder = new PdfJsJpegDecoderCore(configuration, this))
- {
- return decoder.Identify(stream);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/README.md b/src/ImageSharp/Formats/Jpeg/README.md
index 54bc14847..2f766ca0c 100644
--- a/src/ImageSharp/Formats/Jpeg/README.md
+++ b/src/ImageSharp/Formats/Jpeg/README.md
@@ -1,3 +1,8 @@
-Encoder/Decoder adapted and extended from:
+Encoder adapted and extended from:
+https://golang.org/src/image/jpeg/
-https://golang.org/src/image/jpeg/
\ No newline at end of file
+Decoder orchestration code is based on:
+https://github.com/mozilla/pdf.js
+
+Huffmann decoder is based on:
+https://github.com/rds1983/StbSharp
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
index 3b8aea669..f3231fa22 100644
--- a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
@@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using SixLabors.ImageSharp.Processing.Quantization;
+using SixLabors.ImageSharp.Processing.Processors.Quantization;
namespace SixLabors.ImageSharp.Formats.Png
{
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 04d4f057c..83c195eec 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -10,6 +10,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Png.Filters;
using SixLabors.ImageSharp.Formats.Png.Zlib;
using SixLabors.ImageSharp.MetaData;
@@ -233,7 +234,7 @@ namespace SixLabors.ImageSharp.Formats.Png
this.ValidateHeader();
break;
case PngChunkType.Physical:
- this.ReadPhysicalChunk(metadata, chunk.Data.Array);
+ this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan());
break;
case PngChunkType.Data:
if (image == null)
@@ -307,7 +308,7 @@ namespace SixLabors.ImageSharp.Formats.Png
this.ValidateHeader();
break;
case PngChunkType.Physical:
- this.ReadPhysicalChunk(metadata, chunk.Data.Array);
+ this.ReadPhysicalChunk(metadata, chunk.Data.GetSpan());
break;
case PngChunkType.Data:
this.SkipChunkDataAndCrc(chunk);
@@ -369,7 +370,7 @@ namespace SixLabors.ImageSharp.Formats.Png
return false;
}
- buffer = this.MemoryAllocator.AllocateCleanManagedByteBuffer(bytesPerScanline * 8 / bits);
+ buffer = this.MemoryAllocator.AllocateManagedByteBuffer(bytesPerScanline * 8 / bits, AllocationOptions.Clean);
byte[] result = buffer.Array;
int mask = 0xFF >> (8 - bits);
int resultOffset = 0;
@@ -396,9 +397,26 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The data containing physical data.
private void ReadPhysicalChunk(ImageMetaData metadata, ReadOnlySpan data)
{
- // 39.3700787 = inches in a meter.
- metadata.HorizontalResolution = BinaryPrimitives.ReadInt32BigEndian(data.Slice(0, 4)) / 39.3700787d;
- metadata.VerticalResolution = BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4)) / 39.3700787d;
+ // The pHYs chunk specifies the intended pixel size or aspect ratio for display of the image. It contains:
+ // Pixels per unit, X axis: 4 bytes (unsigned integer)
+ // Pixels per unit, Y axis: 4 bytes (unsigned integer)
+ // Unit specifier: 1 byte
+ //
+ // The following values are legal for the unit specifier:
+ // 0: unit is unknown
+ // 1: unit is the meter
+ //
+ // When the unit specifier is 0, the pHYs chunk defines pixel aspect ratio only; the actual size of the pixels remains unspecified.
+ int hResolution = BinaryPrimitives.ReadInt32BigEndian(data.Slice(0, 4));
+ int vResolution = BinaryPrimitives.ReadInt32BigEndian(data.Slice(4, 4));
+ byte unit = data[8];
+
+ metadata.ResolutionUnits = unit == byte.MinValue
+ ? PixelResolutionUnit.AspectRatio
+ : PixelResolutionUnit.PixelsPerMeter;
+
+ metadata.HorizontalResolution = hResolution;
+ metadata.VerticalResolution = vResolution;
}
///
@@ -419,8 +437,8 @@ namespace SixLabors.ImageSharp.Formats.Png
this.bytesPerSample = this.header.BitDepth / 8;
}
- this.previousScanline = this.MemoryAllocator.AllocateCleanManagedByteBuffer(this.bytesPerScanline);
- this.scanline = this.configuration.MemoryAllocator.AllocateCleanManagedByteBuffer(this.bytesPerScanline);
+ this.previousScanline = this.MemoryAllocator.AllocateManagedByteBuffer(this.bytesPerScanline, AllocationOptions.Clean);
+ this.scanline = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(this.bytesPerScanline, AllocationOptions.Clean);
}
///
@@ -1427,7 +1445,7 @@ namespace SixLabors.ImageSharp.Formats.Png
private IManagedByteBuffer ReadChunkData(int length)
{
// We rent the buffer here to return it afterwards in Decode()
- IManagedByteBuffer buffer = this.configuration.MemoryAllocator.AllocateCleanManagedByteBuffer(length);
+ IManagedByteBuffer buffer = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(length, AllocationOptions.Clean);
this.currentStream.Read(buffer.Array, 0, length);
diff --git a/src/ImageSharp/Formats/Png/PngEncoder.cs b/src/ImageSharp/Formats/Png/PngEncoder.cs
index babda2eff..109e6ad77 100644
--- a/src/ImageSharp/Formats/Png/PngEncoder.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoder.cs
@@ -4,7 +4,7 @@
using System.IO;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Quantization;
+using SixLabors.ImageSharp.Processing.Processors.Quantization;
namespace SixLabors.ImageSharp.Formats.Png
{
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 1b3e84b85..e696e1f68 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -6,10 +6,12 @@ using System.Buffers.Binary;
using System.IO;
using System.Linq;
using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Png.Filters;
using SixLabors.ImageSharp.Formats.Png.Zlib;
+using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing.Quantization;
+using SixLabors.ImageSharp.Processing.Processors.Quantization;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Png
@@ -598,19 +600,52 @@ namespace SixLabors.ImageSharp.Formats.Png
private void WritePhysicalChunk(Stream stream, Image image)
where TPixel : struct, IPixel
{
- if (image.MetaData.HorizontalResolution > 0 && image.MetaData.VerticalResolution > 0)
+ // The pHYs chunk specifies the intended pixel size or aspect ratio for display of the image. It contains:
+ // Pixels per unit, X axis: 4 bytes (unsigned integer)
+ // Pixels per unit, Y axis: 4 bytes (unsigned integer)
+ // Unit specifier: 1 byte
+ //
+ // The following values are legal for the unit specifier:
+ // 0: unit is unknown
+ // 1: unit is the meter
+ //
+ // When the unit specifier is 0, the pHYs chunk defines pixel aspect ratio only; the actual size of the pixels remains unspecified.
+ ImageMetaData meta = image.MetaData;
+ Span hResolution = this.chunkDataBuffer.AsSpan(0, 4);
+ Span vResolution = this.chunkDataBuffer.AsSpan(4, 4);
+
+ switch (meta.ResolutionUnits)
{
- // 39.3700787 = inches in a meter.
- int dpmX = (int)Math.Round(image.MetaData.HorizontalResolution * 39.3700787D);
- int dpmY = (int)Math.Round(image.MetaData.VerticalResolution * 39.3700787D);
+ case PixelResolutionUnit.AspectRatio:
- BinaryPrimitives.WriteInt32BigEndian(this.chunkDataBuffer.AsSpan(0, 4), dpmX);
- BinaryPrimitives.WriteInt32BigEndian(this.chunkDataBuffer.AsSpan(4, 4), dpmY);
+ this.chunkDataBuffer[8] = 0;
+ BinaryPrimitives.WriteInt32BigEndian(hResolution, (int)Math.Round(meta.HorizontalResolution));
+ BinaryPrimitives.WriteInt32BigEndian(vResolution, (int)Math.Round(meta.VerticalResolution));
+ break;
+
+ case PixelResolutionUnit.PixelsPerInch:
+
+ this.chunkDataBuffer[8] = 1; // Per meter
+ BinaryPrimitives.WriteInt32BigEndian(hResolution, (int)Math.Round(UnitConverter.InchToMeter(meta.HorizontalResolution)));
+ BinaryPrimitives.WriteInt32BigEndian(vResolution, (int)Math.Round(UnitConverter.InchToMeter(meta.VerticalResolution)));
+ break;
+
+ case PixelResolutionUnit.PixelsPerCentimeter:
- this.chunkDataBuffer[8] = 1;
+ this.chunkDataBuffer[8] = 1; // Per meter
+ BinaryPrimitives.WriteInt32BigEndian(hResolution, (int)Math.Round(UnitConverter.CmToMeter(meta.HorizontalResolution)));
+ BinaryPrimitives.WriteInt32BigEndian(vResolution, (int)Math.Round(UnitConverter.CmToMeter(meta.VerticalResolution)));
+ break;
+
+ default:
- this.WriteChunk(stream, PngChunkType.Physical, this.chunkDataBuffer, 0, 9);
+ this.chunkDataBuffer[8] = 1; // Per meter
+ BinaryPrimitives.WriteInt32BigEndian(hResolution, (int)Math.Round(meta.HorizontalResolution));
+ BinaryPrimitives.WriteInt32BigEndian(vResolution, (int)Math.Round(meta.VerticalResolution));
+ break;
}
+
+ this.WriteChunk(stream, PngChunkType.Physical, this.chunkDataBuffer, 0, 9);
}
///
@@ -643,9 +678,9 @@ namespace SixLabors.ImageSharp.Formats.Png
this.bytesPerScanline = this.width * this.bytesPerPixel;
int resultLength = this.bytesPerScanline + 1;
- this.previousScanline = this.memoryAllocator.AllocateCleanManagedByteBuffer(this.bytesPerScanline);
- this.rawScanline = this.memoryAllocator.AllocateCleanManagedByteBuffer(this.bytesPerScanline);
- this.result = this.memoryAllocator.AllocateCleanManagedByteBuffer(resultLength);
+ this.previousScanline = this.memoryAllocator.AllocateManagedByteBuffer(this.bytesPerScanline, AllocationOptions.Clean);
+ this.rawScanline = this.memoryAllocator.AllocateManagedByteBuffer(this.bytesPerScanline, AllocationOptions.Clean);
+ this.result = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean);
switch (this.pngFilterMethod)
{
@@ -654,29 +689,29 @@ namespace SixLabors.ImageSharp.Formats.Png
case PngFilterMethod.Sub:
- this.sub = this.memoryAllocator.AllocateCleanManagedByteBuffer(resultLength);
+ this.sub = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean);
break;
case PngFilterMethod.Up:
- this.up = this.memoryAllocator.AllocateCleanManagedByteBuffer(resultLength);
+ this.up = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean);
break;
case PngFilterMethod.Average:
- this.average = this.memoryAllocator.AllocateCleanManagedByteBuffer(resultLength);
+ this.average = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean);
break;
case PngFilterMethod.Paeth:
- this.paeth = this.memoryAllocator.AllocateCleanManagedByteBuffer(resultLength);
+ this.paeth = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean);
break;
case PngFilterMethod.Adaptive:
- this.sub = this.memoryAllocator.AllocateCleanManagedByteBuffer(resultLength);
- this.up = this.memoryAllocator.AllocateCleanManagedByteBuffer(resultLength);
- this.average = this.memoryAllocator.AllocateCleanManagedByteBuffer(resultLength);
- this.paeth = this.memoryAllocator.AllocateCleanManagedByteBuffer(resultLength);
+ this.sub = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean);
+ this.up = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean);
+ this.average = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean);
+ this.paeth = this.memoryAllocator.AllocateManagedByteBuffer(resultLength, AllocationOptions.Clean);
break;
}
diff --git a/src/ImageSharp/IConfigurationModule.cs b/src/ImageSharp/IConfigurationModule.cs
index 93c40497d..3ca8ed918 100644
--- a/src/ImageSharp/IConfigurationModule.cs
+++ b/src/ImageSharp/IConfigurationModule.cs
@@ -14,4 +14,4 @@ namespace SixLabors.ImageSharp
/// The configuration that will retain the encoders, decodes and mime type detectors.
void Configure(Configuration configuration);
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/DoubleBufferedStreamReader.cs b/src/ImageSharp/IO/DoubleBufferedStreamReader.cs
similarity index 97%
rename from src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/DoubleBufferedStreamReader.cs
rename to src/ImageSharp/IO/DoubleBufferedStreamReader.cs
index 7aeee43c2..94a2f2cbf 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/DoubleBufferedStreamReader.cs
+++ b/src/ImageSharp/IO/DoubleBufferedStreamReader.cs
@@ -7,8 +7,7 @@ using System.Runtime.CompilerServices;
using SixLabors.Memory;
-// TODO: This could be useful elsewhere.
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+namespace SixLabors.ImageSharp.IO
{
///
/// A stream reader that add a secondary level buffer in addition to native stream buffered reading
@@ -44,7 +43,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
this.stream = stream;
this.length = (int)stream.Length;
- this.managedBuffer = memoryAllocator.AllocateCleanManagedByteBuffer(ChunkLength);
+ this.managedBuffer = memoryAllocator.AllocateManagedByteBuffer(ChunkLength, AllocationOptions.Clean);
this.bufferChunk = this.managedBuffer.Array;
}
diff --git a/src/ImageSharp/Image.WrapMemory.cs b/src/ImageSharp/Image.WrapMemory.cs
index 3988120e6..77432c3ad 100644
--- a/src/ImageSharp/Image.WrapMemory.cs
+++ b/src/ImageSharp/Image.WrapMemory.cs
@@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
+
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
@@ -13,8 +15,6 @@ namespace SixLabors.ImageSharp
///
public static partial class Image
{
- // TODO: This is a WIP API, should be public when finished.
-
///
/// Wraps an existing contigous memory area of 'width'x'height' pixels,
/// allowing to view/manipulate it as an ImageSharp instance.
@@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp
/// The height of the memory image
/// The
/// An instance
- internal static Image WrapMemory(
+ public static Image WrapMemory(
Configuration config,
Memory pixelMemory,
int width,
@@ -34,26 +34,117 @@ namespace SixLabors.ImageSharp
ImageMetaData metaData)
where TPixel : struct, IPixel
{
- var buffer = new ConsumedBuffer(pixelMemory);
- return new Image(config, buffer, width, height, metaData);
+ var memorySource = new MemorySource(pixelMemory);
+ return new Image(config, memorySource, width, height, metaData);
+ }
+
+ ///
+ /// Wraps an existing contigous memory area of 'width'x'height' pixels,
+ /// allowing to view/manipulate it as an ImageSharp instance.
+ ///
+ /// The pixel type
+ /// The
+ /// The pixel memory
+ /// The width of the memory image
+ /// The height of the memory image
+ /// An instance
+ public static Image WrapMemory(
+ Configuration config,
+ Memory pixelMemory,
+ int width,
+ int height)
+ where TPixel : struct, IPixel
+ {
+ return WrapMemory(config, pixelMemory, width, height, new ImageMetaData());
}
///
/// Wraps an existing contigous memory area of 'width'x'height' pixels,
/// allowing to view/manipulate it as an ImageSharp instance.
+ /// The memory is being observed, the caller remains responsible for managing it's lifecycle.
///
/// The pixel type
/// The pixel memory
/// The width of the memory image
/// The height of the memory image
/// An instance
- internal static Image WrapMemory(
+ public static Image WrapMemory(
Memory pixelMemory,
int width,
int height)
where TPixel : struct, IPixel
{
- return WrapMemory(Configuration.Default, pixelMemory, width, height, new ImageMetaData());
+ return WrapMemory(Configuration.Default, pixelMemory, width, height);
+ }
+
+ ///
+ /// Wraps an existing contigous memory area of 'width'x'height' pixels,
+ /// allowing to view/manipulate it as an ImageSharp instance.
+ /// The ownership of the is being transfered to the new instance,
+ /// meaning that the caller is not allowed to dispose .
+ /// It will be disposed together with the result image.
+ ///
+ /// The pixel type
+ /// The
+ /// The that is being transfered to the image
+ /// The width of the memory image
+ /// The height of the memory image
+ /// The
+ /// An instance
+ public static Image WrapMemory(
+ Configuration config,
+ IMemoryOwner pixelMemoryOwner,
+ int width,
+ int height,
+ ImageMetaData metaData)
+ where TPixel : struct, IPixel
+ {
+ var memorySource = new MemorySource(pixelMemoryOwner, false);
+ return new Image(config, memorySource, width, height, metaData);
+ }
+
+ ///
+ /// Wraps an existing contigous memory area of 'width'x'height' pixels,
+ /// allowing to view/manipulate it as an ImageSharp instance.
+ /// The ownership of the is being transfered to the new instance,
+ /// meaning that the caller is not allowed to dispose .
+ /// It will be disposed together with the result image.
+ ///
+ /// The pixel type
+ /// The
+ /// The that is being transfered to the image
+ /// The width of the memory image
+ /// The height of the memory image
+ /// An instance
+ public static Image WrapMemory(
+ Configuration config,
+ IMemoryOwner pixelMemoryOwner,
+ int width,
+ int height)
+ where TPixel : struct, IPixel
+ {
+ return WrapMemory(config, pixelMemoryOwner, width, height, new ImageMetaData());
+ }
+
+ ///
+ /// Wraps an existing contigous memory area of 'width'x'height' pixels,
+ /// allowing to view/manipulate it as an ImageSharp instance.
+ /// The ownership of the is being transfered to the new instance,
+ /// meaning that the caller is not allowed to dispose .
+ /// It will be disposed together with the result image.
+ ///
+ /// The pixel type
+ /// The that is being transfered to the image
+ /// The width of the memory image
+ /// The height of the memory image
+ /// An instance
+ public static Image WrapMemory(
+ IMemoryOwner pixelMemoryOwner,
+ int width,
+ int height)
+ where TPixel : struct, IPixel
+ {
+ return WrapMemory(Configuration.Default, pixelMemoryOwner, width, height);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/ImageFrameCollection.cs b/src/ImageSharp/ImageFrameCollection.cs
index 14a16b691..154ef5014 100644
--- a/src/ImageSharp/ImageFrameCollection.cs
+++ b/src/ImageSharp/ImageFrameCollection.cs
@@ -30,14 +30,14 @@ namespace SixLabors.ImageSharp
this.frames.Add(new ImageFrame(parent.GetConfiguration(), width, height, backgroundColor));
}
- internal ImageFrameCollection(Image parent, int width, int height, IBuffer consumedBuffer)
+ internal ImageFrameCollection(Image parent, int width, int height, MemorySource memorySource)
{
Guard.NotNull(parent, nameof(parent));
this.parent = parent;
// Frames are already cloned within the caller
- this.frames.Add(new ImageFrame(parent.GetConfiguration(), width, height, consumedBuffer));
+ this.frames.Add(new ImageFrame(parent.GetConfiguration(), width, height, memorySource));
}
internal ImageFrameCollection(Image parent, IEnumerable> frames)
diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs
index bd86b7dee..6c04d5aea 100644
--- a/src/ImageSharp/ImageFrame{TPixel}.cs
+++ b/src/ImageSharp/ImageFrame{TPixel}.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
@@ -86,7 +87,7 @@ namespace SixLabors.ImageSharp
this.configuration = configuration;
this.MemoryAllocator = configuration.MemoryAllocator;
- this.PixelBuffer = this.MemoryAllocator.Allocate2D(width, height, false);
+ this.PixelBuffer = this.MemoryAllocator.Allocate2D(width, height);
this.MetaData = metaData;
this.Clear(configuration.ParallelOptions, backgroundColor);
}
@@ -94,8 +95,8 @@ namespace SixLabors.ImageSharp
///
/// Initializes a new instance of the class wrapping an existing buffer.
///
- internal ImageFrame(Configuration configuration, int width, int height, IBuffer consumedBuffer)
- : this(configuration, width, height, consumedBuffer, new ImageFrameMetaData())
+ internal ImageFrame(Configuration configuration, int width, int height, MemorySource memorySource)
+ : this(configuration, width, height, memorySource, new ImageFrameMetaData())
{
}
@@ -106,7 +107,7 @@ namespace SixLabors.ImageSharp
Configuration configuration,
int width,
int height,
- IBuffer consumedBuffer,
+ MemorySource memorySource,
ImageFrameMetaData metaData)
{
Guard.NotNull(configuration, nameof(configuration));
@@ -116,7 +117,7 @@ namespace SixLabors.ImageSharp
this.configuration = configuration;
this.MemoryAllocator = configuration.MemoryAllocator;
- this.PixelBuffer = new Buffer2D(consumedBuffer, width, height);
+ this.PixelBuffer = new Buffer2D(memorySource, width, height);
this.MetaData = metaData;
}
@@ -174,16 +175,10 @@ namespace SixLabors.ImageSharp
public TPixel this[int x, int y]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return this.PixelBuffer[x, y];
- }
+ get => this.PixelBuffer[x, y];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set
- {
- this.PixelBuffer[x, y] = value;
- }
+ set => this.PixelBuffer[x, y] = value;
}
///
@@ -278,7 +273,7 @@ namespace SixLabors.ImageSharp
this.Height,
this.configuration,
this.Width,
- (int y, IBuffer tempRowBuffer) =>
+ (int y, IMemoryOwner tempRowBuffer) =>
{
Span sourceRow = this.GetPixelRowSpan(y);
Span targetRow = target.GetPixelRowSpan(y);
diff --git a/src/ImageSharp/ImageInfoExtensions.cs b/src/ImageSharp/ImageInfoExtensions.cs
index 0f2b2ba97..dca5502d0 100644
--- a/src/ImageSharp/ImageInfoExtensions.cs
+++ b/src/ImageSharp/ImageInfoExtensions.cs
@@ -24,4 +24,4 @@ namespace SixLabors.ImageSharp
/// The
public static Rectangle Bounds(this IImageInfo info) => new Rectangle(0, 0, info.Width, info.Height);
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj
index b40884f4b..eca134101 100644
--- a/src/ImageSharp/ImageSharp.csproj
+++ b/src/ImageSharp/ImageSharp.csproj
@@ -29,7 +29,7 @@
portable
True
IOperation
- 7.3
+ Latest
diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs
index ad754bc75..5a5928d6b 100644
--- a/src/ImageSharp/Image{TPixel}.cs
+++ b/src/ImageSharp/Image{TPixel}.cs
@@ -84,23 +84,14 @@ namespace SixLabors.ImageSharp
///
/// Initializes a new instance of the class
- /// consuming an external buffer instance.
+ /// wrapping an external
///
- internal Image(Configuration configuration, IBuffer consumedBuffer, int width, int height)
- : this(configuration, consumedBuffer, width, height, new ImageMetaData())
- {
- }
-
- ///
- /// Initializes a new instance of the class
- /// consuming an external buffer instance.
- ///
- internal Image(Configuration configuration, IBuffer consumedBuffer, int width, int height, ImageMetaData metadata)
+ internal Image(Configuration configuration, MemorySource memorySource, int width, int height, ImageMetaData metadata)
{
this.configuration = configuration;
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf() * 8);
this.MetaData = metadata;
- this.frames = new ImageFrameCollection(this, width, height, consumedBuffer);
+ this.frames = new ImageFrameCollection(this, width, height, memorySource);
}
///
diff --git a/src/ImageSharp/Memory/AllocationOptions.cs b/src/ImageSharp/Memory/AllocationOptions.cs
new file mode 100644
index 000000000..5eda00505
--- /dev/null
+++ b/src/ImageSharp/Memory/AllocationOptions.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.Memory
+{
+ ///
+ /// Options for allocating buffers.
+ ///
+ public enum AllocationOptions
+ {
+ ///
+ /// Indicates that the buffer should just be allocated.
+ ///
+ None,
+
+ ///
+ /// Indicates that the allocated buffer should be cleaned following allocation.
+ ///
+ Clean
+ }
+}
diff --git a/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs b/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs
index d0f68c9c6..adc8843a3 100644
--- a/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs
+++ b/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs
@@ -14,7 +14,6 @@ namespace SixLabors.Memory
{
///
/// The buffer implementation of .
- /// In this implementation is owned.
///
private class Buffer : ManagedBufferBase
where T : struct
diff --git a/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.cs b/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.cs
index 90950d4b3..32c1c6d1d 100644
--- a/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.cs
+++ b/src/ImageSharp/Memory/ArrayPoolMemoryAllocator.cs
@@ -9,7 +9,7 @@ namespace SixLabors.Memory
///
/// Implements by allocating memory from .
///
- public partial class ArrayPoolMemoryAllocator : MemoryAllocator
+ public sealed partial class ArrayPoolMemoryAllocator : MemoryAllocator
{
///
/// The for small-to-medium buffers which is not kept clean.
@@ -89,7 +89,7 @@ namespace SixLabors.Memory
}
///
- internal override IBuffer Allocate(int length, bool clear)
+ internal override IMemoryOwner Allocate(int length, AllocationOptions options = AllocationOptions.None)
{
int itemSizeBytes = Unsafe.SizeOf();
int bufferSizeInBytes = length * itemSizeBytes;
@@ -98,7 +98,7 @@ namespace SixLabors.Memory
byte[] byteArray = pool.Rent(bufferSizeInBytes);
var buffer = new Buffer(byteArray, length, pool);
- if (clear)
+ if (options == AllocationOptions.Clean)
{
buffer.Clear();
}
@@ -107,13 +107,13 @@ namespace SixLabors.Memory
}
///
- internal override IManagedByteBuffer AllocateManagedByteBuffer(int length, bool clear)
+ internal override IManagedByteBuffer AllocateManagedByteBuffer(int length, AllocationOptions options)
{
ArrayPool pool = this.GetArrayPool(length);
byte[] byteArray = pool.Rent(length);
var buffer = new ManagedByteBuffer(byteArray, length, pool);
- if (clear)
+ if (options == AllocationOptions.Clean)
{
buffer.Clear();
}
diff --git a/src/ImageSharp/Memory/BasicArrayBuffer.cs b/src/ImageSharp/Memory/BasicArrayBuffer.cs
index 5e3893d08..f40df7604 100644
--- a/src/ImageSharp/Memory/BasicArrayBuffer.cs
+++ b/src/ImageSharp/Memory/BasicArrayBuffer.cs
@@ -7,7 +7,7 @@ using System.Runtime.CompilerServices;
namespace SixLabors.Memory
{
///
- /// Wraps an array as an instance. In this implementation is owned.
+ /// Wraps an array as an instance.
///
internal class BasicArrayBuffer : ManagedBufferBase
where T : struct
diff --git a/src/ImageSharp/Memory/BasicByteBuffer.cs b/src/ImageSharp/Memory/BasicByteBuffer.cs
index a8a30b1aa..9f995e347 100644
--- a/src/ImageSharp/Memory/BasicByteBuffer.cs
+++ b/src/ImageSharp/Memory/BasicByteBuffer.cs
@@ -3,7 +3,7 @@
namespace SixLabors.Memory
{
- internal class BasicByteBuffer : BasicArrayBuffer, IManagedByteBuffer
+ internal sealed class BasicByteBuffer : BasicArrayBuffer, IManagedByteBuffer
{
internal BasicByteBuffer(byte[] array)
: base(array)
diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs
index c27752570..be4f0ef15 100644
--- a/src/ImageSharp/Memory/Buffer2DExtensions.cs
+++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs
@@ -18,7 +18,7 @@ namespace SixLabors.Memory
internal static Span GetSpan(this Buffer2D buffer)
where T : struct
{
- return buffer.Buffer.GetSpan();
+ return buffer.MemorySource.GetSpan();
}
///
@@ -61,7 +61,7 @@ namespace SixLabors.Memory
public static Memory GetRowMemory(this Buffer2D buffer, int y)
where T : struct
{
- return buffer.Buffer.Memory.Slice(y * buffer.Width, buffer.Width);
+ return buffer.MemorySource.Memory.Slice(y * buffer.Width, buffer.Width);
}
///
diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs
index f8d75b54c..844ca1ad1 100644
--- a/src/ImageSharp/Memory/Buffer2D{T}.cs
+++ b/src/ImageSharp/Memory/Buffer2D{T}.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Runtime.CompilerServices;
using SixLabors.Primitives;
@@ -12,18 +13,20 @@ namespace SixLabors.Memory
/// interpreted as a 2D region of x elements.
///
/// The value type.
- internal class Buffer2D : IDisposable
+ internal sealed class Buffer2D : IDisposable
where T : struct
{
+ private MemorySource memorySource;
+
///
/// Initializes a new instance of the class.
///
- /// The buffer to wrap
+ /// The buffer to wrap
/// The number of elements in a row
/// The number of rows
- public Buffer2D(IBuffer wrappedBuffer, int width, int height)
+ public Buffer2D(MemorySource memorySource, int width, int height)
{
- this.Buffer = wrappedBuffer;
+ this.memorySource = memorySource;
this.Width = width;
this.Height = height;
}
@@ -39,13 +42,13 @@ namespace SixLabors.Memory
public int Height { get; private set; }
///
- /// Gets the backing
+ /// Gets the backing
///
- public IBuffer Buffer { get; private set; }
+ public MemorySource MemorySource => this.memorySource;
- public Memory Memory => this.Buffer.Memory;
+ public Memory Memory => this.MemorySource.Memory;
- public Span Span => this.Buffer.GetSpan();
+ public Span Span => this.Memory.Span;
///
/// Gets a reference to the element at the specified position.
@@ -60,7 +63,7 @@ namespace SixLabors.Memory
{
ImageSharp.DebugGuard.MustBeLessThan(x, this.Width, nameof(x));
DebugGuard.MustBeLessThan(y, this.Height, nameof(y));
- Span span = this.Buffer.GetSpan();
+ Span span = this.Span;
return ref span[(this.Width * y) + x];
}
}
@@ -70,7 +73,7 @@ namespace SixLabors.Memory
///
public void Dispose()
{
- this.Buffer?.Dispose();
+ this.MemorySource.Dispose();
}
///
@@ -79,36 +82,15 @@ namespace SixLabors.Memory
///
public static void SwapOrCopyContent(Buffer2D destination, Buffer2D source)
{
- if (source.Buffer.IsMemoryOwner && destination.Buffer.IsMemoryOwner)
- {
- SwapContents(destination, source);
- }
- else
- {
- if (destination.Size() != source.Size())
- {
- throw new InvalidOperationException("SwapOrCopyContents(): buffers should both owned or the same size!");
- }
-
- source.Span.CopyTo(destination.Span);
- }
+ MemorySource.SwapOrCopyContent(ref destination.memorySource, ref source.memorySource);
+ SwapDimensionData(destination, source);
}
- ///
- /// Swap the contents (, , ) of the two buffers.
- /// Useful to transfer the contents of a temporary to a persistent
- ///
- /// The first buffer
- /// The second buffer
- private static void SwapContents(Buffer2D a, Buffer2D b)
+ private static void SwapDimensionData(Buffer2D a, Buffer2D b)
{
Size aSize = a.Size();
Size bSize = b.Size();
- IBuffer temp = a.Buffer;
- a.Buffer = b.Buffer;
- b.Buffer = temp;
-
b.Width = aSize.Width;
b.Height = aSize.Height;
diff --git a/src/ImageSharp/Memory/BufferExtensions.cs b/src/ImageSharp/Memory/BufferExtensions.cs
index 8ebf866bc..800e0d975 100644
--- a/src/ImageSharp/Memory/BufferExtensions.cs
+++ b/src/ImageSharp/Memory/BufferExtensions.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -11,8 +12,12 @@ namespace SixLabors.Memory
internal static class BufferExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int Length(this IBuffer buffer)
- where T : struct => buffer.GetSpan().Length;
+ public static Span GetSpan(this IMemoryOwner buffer)
+ => buffer.Memory.Span;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int Length(this IMemoryOwner buffer)
+ => buffer.GetSpan().Length;
///
/// Gets a to an offseted position inside the buffer.
@@ -21,8 +26,7 @@ namespace SixLabors.Memory
/// The start
/// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Span Slice(this IBuffer buffer, int start)
- where T : struct
+ public static Span Slice(this IMemoryOwner buffer, int start)
{
return buffer.GetSpan().Slice(start);
}
@@ -35,8 +39,7 @@ namespace SixLabors.Memory
/// The length of the slice
/// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Span Slice(this IBuffer buffer, int start, int length)
- where T : struct
+ public static Span Slice(this IMemoryOwner buffer, int start, int length)
{
return buffer.GetSpan().Slice(start, length);
}
@@ -46,13 +49,12 @@ namespace SixLabors.Memory
///
/// The buffer
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Clear(this IBuffer buffer)
- where T : struct
+ public static void Clear(this IMemoryOwner buffer)
{
buffer.GetSpan().Clear();
}
- public static ref T GetReference(this IBuffer buffer)
+ public static ref T GetReference(this IMemoryOwner buffer)
where T : struct =>
ref MemoryMarshal.GetReference(buffer.GetSpan());
diff --git a/src/ImageSharp/Memory/ConsumedBuffer.cs b/src/ImageSharp/Memory/ConsumedBuffer.cs
deleted file mode 100644
index 73468a381..000000000
--- a/src/ImageSharp/Memory/ConsumedBuffer.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-
-namespace SixLabors.Memory
-{
- ///
- /// A buffer implementation that consumes an existing instance.
- /// The ownership of the memory remains external.
- ///
- /// The value type
- internal sealed class ConsumedBuffer : IBuffer
- where T : struct
- {
- public ConsumedBuffer(Memory memory)
- {
- this.Memory = memory;
- }
-
- public Memory Memory { get; }
-
- public bool IsMemoryOwner => false;
-
- public Span GetSpan()
- {
- return this.Memory.Span;
- }
-
- public void Dispose()
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Memory/IBuffer{T}.cs b/src/ImageSharp/Memory/IBuffer{T}.cs
deleted file mode 100644
index 847f2741d..000000000
--- a/src/ImageSharp/Memory/IBuffer{T}.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Buffers;
-
-namespace SixLabors.Memory
-{
- ///
- /// Represents a contigous memory buffer of value-type items.
- /// Depending on it's implementation, an can (1) OWN or (2) CONSUME the instance it wraps.
- /// For a deeper understanding of the owner/consumer model, read the following docs:
- /// https://gist.github.com/GrabYourPitchforks/4c3e1935fd4d9fa2831dbfcab35dffc6
- /// TODO: We need more SOC here! For owned buffers we should use .
- /// For the consumption case we should not use buffers at all. We need to refactor Buffer2D{T} for this.
- ///
- /// The value type
- internal interface IBuffer : IDisposable
- where T : struct
- {
- ///
- /// Gets the ownerd/consumed by this buffer.
- ///
- Memory Memory { get; }
-
- ///
- /// Gets a value indicating whether this instance is owning the .
- ///
- bool IsMemoryOwner { get; }
-
- ///
- /// Gets the span to the memory "promised" by this buffer when it's OWNED (1).
- /// Gets `this.Memory.Span` when the buffer CONSUMED (2).
- ///
- /// The
- Span GetSpan();
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Memory/IManagedByteBuffer.cs b/src/ImageSharp/Memory/IManagedByteBuffer.cs
index a977eb68f..91c61424b 100644
--- a/src/ImageSharp/Memory/IManagedByteBuffer.cs
+++ b/src/ImageSharp/Memory/IManagedByteBuffer.cs
@@ -1,12 +1,14 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using System.Buffers;
+
namespace SixLabors.Memory
{
///
/// Represents a byte buffer backed by a managed array. Useful for interop with classic .NET API-s.
///
- internal interface IManagedByteBuffer : IBuffer
+ internal interface IManagedByteBuffer : IMemoryOwner
{
///
/// Gets the managed array backing this buffer instance.
diff --git a/src/ImageSharp/Memory/ManagedBufferBase.cs b/src/ImageSharp/Memory/ManagedBufferBase.cs
index 606d1c962..8aaf199ff 100644
--- a/src/ImageSharp/Memory/ManagedBufferBase.cs
+++ b/src/ImageSharp/Memory/ManagedBufferBase.cs
@@ -7,9 +7,9 @@ using System.Runtime.InteropServices;
namespace SixLabors.Memory
{
///
- /// Provides a base class for implementations by implementing pinning logic for adaption.
+ /// Provides a base class for implementations by implementing pinning logic for adaption.
///
- internal abstract class ManagedBufferBase : System.Buffers.MemoryManager, IBuffer
+ internal abstract class ManagedBufferBase : MemoryManager
where T : struct
{
private GCHandle pinHandle;
diff --git a/src/ImageSharp/Memory/MemoryAllocator.cs b/src/ImageSharp/Memory/MemoryAllocator.cs
index 2195444fd..57b721e48 100644
--- a/src/ImageSharp/Memory/MemoryAllocator.cs
+++ b/src/ImageSharp/Memory/MemoryAllocator.cs
@@ -1,6 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using System.Buffers;
+
namespace SixLabors.Memory
{
///
@@ -9,23 +11,22 @@ namespace SixLabors.Memory
public abstract class MemoryAllocator
{
///
- /// Allocates an of size , optionally
- /// clearing the buffer before it gets returned.
+ /// Allocates an , holding a of length .
///
/// Type of the data stored in the buffer
/// Size of the buffer to allocate
- /// True to clear the backing memory of the buffer
+ /// The allocation options.
/// A buffer of values of type .
- internal abstract IBuffer Allocate(int length, bool clear)
+ internal abstract IMemoryOwner Allocate(int length, AllocationOptions options = AllocationOptions.None)
where T : struct;
///
- /// Allocates an
+ /// Allocates an .
///
/// The requested buffer length
- /// A value indicating whether to clean the buffer
+ /// The allocation options.
/// The
- internal abstract IManagedByteBuffer AllocateManagedByteBuffer(int length, bool clear);
+ internal abstract IManagedByteBuffer AllocateManagedByteBuffer(int length, AllocationOptions options = AllocationOptions.None);
///
/// Releases all retained resources not being in use.
diff --git a/src/ImageSharp/Memory/MemoryAllocatorExtensions.cs b/src/ImageSharp/Memory/MemoryAllocatorExtensions.cs
index ab4fc93b7..d8c1f51f4 100644
--- a/src/ImageSharp/Memory/MemoryAllocatorExtensions.cs
+++ b/src/ImageSharp/Memory/MemoryAllocatorExtensions.cs
@@ -1,4 +1,6 @@
-using SixLabors.Primitives;
+using System.Buffers;
+
+using SixLabors.Primitives;
namespace SixLabors.Memory
{
@@ -7,56 +9,25 @@ namespace SixLabors.Memory
///
internal static class MemoryAllocatorExtensions
{
- ///
- /// Allocates a of size .
- /// Note: Depending on the implementation, the buffer may not cleared before
- /// returning, so it may contain data from an earlier use.
- ///
- /// Type of the data stored in the buffer
- /// The
- /// Size of the buffer to allocate
- /// A buffer of values of type .
- public static IBuffer Allocate(this MemoryAllocator memoryAllocator, int length)
- where T : struct
- {
- return memoryAllocator.Allocate(length, false);
- }
-
- public static IBuffer AllocateClean(this MemoryAllocator memoryAllocator, int length)
- where T : struct
- {
- return memoryAllocator.Allocate(length, true);
- }
-
- public static IManagedByteBuffer AllocateManagedByteBuffer(this MemoryAllocator memoryAllocator, int length)
- {
- return memoryAllocator.AllocateManagedByteBuffer(length, false);
- }
-
- public static IManagedByteBuffer AllocateCleanManagedByteBuffer(this MemoryAllocator memoryAllocator, int length)
- {
- return memoryAllocator.AllocateManagedByteBuffer(length, true);
- }
-
- public static Buffer2D Allocate2D(this MemoryAllocator memoryAllocator, int width, int height, bool clear)
+ public static Buffer2D Allocate2D(
+ this MemoryAllocator memoryAllocator,
+ int width,
+ int height,
+ AllocationOptions options = AllocationOptions.None)
where T : struct
{
- IBuffer