diff --git a/src/ImageSharp/Advanced/IPixelSource.cs b/src/ImageSharp/Advanced/IPixelSource.cs
index d7162bc61..f609b15d3 100644
--- a/src/ImageSharp/Advanced/IPixelSource.cs
+++ b/src/ImageSharp/Advanced/IPixelSource.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Memory;
@@ -6,6 +6,17 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Advanced
{
+ ///
+ /// Encapsulates the basic properties and methods required to manipulate images.
+ ///
+ internal interface IPixelSource
+ {
+ ///
+ /// Gets the pixel buffer.
+ ///
+ Buffer2D PixelBuffer { get; }
+ }
+
///
/// Encapsulates the basic properties and methods required to manipulate images.
///
@@ -18,4 +29,4 @@ namespace SixLabors.ImageSharp.Advanced
///
Buffer2D PixelBuffer { get; }
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs
index c2331c379..5229cf14f 100644
--- a/src/ImageSharp/ColorSpaces/Cmyk.cs
+++ b/src/ImageSharp/ColorSpaces/Cmyk.cs
@@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(InliningOptions.ShortMethod)]
public Cmyk(Vector4 vector)
{
- vector = Vector4.Clamp(vector, Min, Max);
+ vector = Vector4Utilities.FastClamp(vector, Min, Max);
this.C = vector.X;
this.M = vector.Y;
this.Y = vector.Z;
diff --git a/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
index 80b8aee7e..981e32f8e 100644
--- a/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
+++ b/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -35,4 +35,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
public static float Compress(float channel)
=> channel <= CieConstants.Epsilon ? (channel * CieConstants.Kappa) / 100F : (1.16F * MathF.Pow(channel, 0.3333333F)) - 0.16F;
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs
index 892c0d5e3..2b9073814 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs
@@ -1,8 +1,6 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -157,4 +155,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
return this.ToRgb(linearOutput);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
index 273c9be91..69d0c1bed 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
@@ -1,10 +1,9 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
index 7f4abfa7b..52f872430 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -447,4 +445,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
index 6ca40af03..2588561c8 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -447,4 +445,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
index b790712c5..867b44a78 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs
index d03c10a01..344b83254 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -440,4 +438,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs
index 21d576fb4..8362432ab 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -475,4 +473,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
return this.linearRgbToCieXyzConverter = new LinearRgbToCieXyzConverter(workingSpace);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
index 00e20e25b..3ff9ac85f 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -440,4 +438,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
index 76175f1cb..7c7436391 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -440,4 +438,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs
index e64beb3e4..e60ad5e20 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -440,4 +438,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
index 5b312f4f8..b2c23b5a4 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
index fc5665e5c..e83dcb125 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -438,4 +436,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
return this.Adapt(rgb);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
index 68cd34bf2..4ea1d8d8f 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
@@ -1,12 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
-
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
@@ -407,4 +405,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(in Rgb color) => YCbCrAndRgbConverter.Convert(color);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs
index bcbd64c77..05d3b2f2d 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs
@@ -1,8 +1,7 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
@@ -58,4 +57,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
this.cieXyzToLinearRgbConverter = new CieXyzToLinearRgbConverter(this.targetRgbWorkingSpace);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs
index 65fe79994..27dd989ad 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs
@@ -1,8 +1,7 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
@@ -52,4 +51,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
public Matrix4x4 LmsAdaptationMatrix { get; set; } = CieXyzAndLmsConverter.DefaultTransformationMatrix;
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs
similarity index 97%
rename from src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
rename to src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs
index 8e14274f6..1e774fe67 100644
--- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs
@@ -1,11 +1,11 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
// ReSharper disable CompareOfFloatsByEqualityOperator
-namespace SixLabors.ImageSharp.ColorSpaces
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Represents the coordinates of CIEXY chromaticity space.
@@ -76,4 +76,4 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(CieXyChromaticityCoordinates other) => this.X.Equals(other.X) && this.Y.Equals(other.Y);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs
index 40d8c5bc6..014ca1abb 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs
@@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Converts from to .
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs
index 2b859205a..e1bf04aa7 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Converts from to .
@@ -38,4 +38,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieLch(l, c, hDegrees, input.WhitePoint);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs
index dfbbc8f0c..bafd0df47 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Converts from to .
@@ -41,4 +41,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieXyz(xyz);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs
index ba5b8bfb7..2dae2669f 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Converts from to .
@@ -30,4 +30,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieLuv(l, u, v, input.WhitePoint);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs
index 3c7d356a5..29fdae69c 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Converts from to .
@@ -38,4 +38,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieLchuv(l, c, hDegrees, input.WhitePoint);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs
index 33f3ec3d3..09040c98c 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs
@@ -3,7 +3,7 @@
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Converts from to .
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs
index 7767b7b44..f704d1a34 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs
@@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between CIE XYZ and CIE xyY.
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndHunterLabConverterBase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndHunterLabConverterBase.cs
index 1cd511e81..68f6c495d 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndHunterLabConverterBase.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndHunterLabConverterBase.cs
@@ -3,7 +3,7 @@
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// The base class for converting between and color spaces.
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs
index f860652b1..a22b097d2 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs
@@ -4,7 +4,7 @@
using System.Numerics;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between and
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs
index c155087ff..4f4aa8482 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs
@@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Converts from to .
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLuvConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLuvConverter.cs
index 7f2bb0cf6..96ec96b49 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLuvConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLuvConverter.cs
@@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Converts from to .
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToHunterLabConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToHunterLabConverter.cs
index f21235d06..881d3d919 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToHunterLabConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToHunterLabConverter.cs
@@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between and
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs
index 6497e3060..25558537a 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs
@@ -4,7 +4,7 @@
using System.Numerics;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between and
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs
index 0700dab43..8e92ced94 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs
@@ -5,7 +5,7 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between and .
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs
index 97465e526..5dbd23b8b 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs
@@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between HSL and Rgb
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs
index 20ada7e7d..04ab0480b 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs
@@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between HSV and Rgb
@@ -127,4 +127,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new Hsv(h, s, v);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs
index 4d6808e6c..795db7e2c 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between and
@@ -36,4 +36,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieXyz(x, y, z);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs
index bdf451cd3..105817075 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs
@@ -1,9 +1,9 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Provides base methods for converting between and color spaces.
@@ -74,4 +74,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
};
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs
index 21a96071a..adaad50fe 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between and
@@ -50,4 +50,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieXyz(vector);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs
index 845443093..54081b639 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs
@@ -1,9 +1,9 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between and .
@@ -25,4 +25,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
workingSpace: input.WorkingSpace);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs
index 4ddbe42e5..bc8c6f030 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs
@@ -1,9 +1,9 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between Rgb and LinearRgb.
@@ -25,4 +25,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
workingSpace: input.WorkingSpace);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs
index ee15ffa50..0821c05c3 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs
@@ -5,7 +5,7 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Color converter between and
diff --git a/src/ImageSharp/ColorSpaces/Conversion/IChromaticAdaptation.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/IChromaticAdaptation.cs
similarity index 100%
rename from src/ImageSharp/ColorSpaces/Conversion/IChromaticAdaptation.cs
rename to src/ImageSharp/ColorSpaces/Conversion/Implementation/IChromaticAdaptation.cs
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/LmsAdaptationMatrix.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/LmsAdaptationMatrix.cs
index 37e4b1a1a..8b8e4ab57 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/LmsAdaptationMatrix.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/LmsAdaptationMatrix.cs
@@ -1,9 +1,9 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Matrices used for transformation from to , defining the cone response domain.
@@ -131,4 +131,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
M44 = 1F
});
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs
index 8871d0465..03378f431 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs
@@ -1,9 +1,9 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Represents the chromaticity coordinates of RGB primaries.
diff --git a/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs
similarity index 97%
rename from src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs
rename to src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs
index a4d96d19e..7589a1d57 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs
@@ -1,11 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
@@ -99,4 +98,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs
index 6caca54cd..c7020723b 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs
@@ -1,11 +1,11 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Companding;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// The gamma working space.
@@ -63,4 +63,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
this.ChromaticityCoordinates,
this.Gamma);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs
index a2eb42ad0..d9c436527 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Companding;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// L* working space.
@@ -29,4 +29,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => LCompanding.Expand(channel);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs
index a794b3dda..4698534db 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Companding;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Rec. 2020 (ITU-R Recommendation BT.2020F) working space.
@@ -29,4 +29,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => Rec2020Companding.Expand(channel);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs
index ffa9699bc..80b635cad 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Companding;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Rec. 709 (ITU-R Recommendation BT.709) working space.
@@ -29,4 +29,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => Rec709Companding.Expand(channel);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs
index a97ae22b1..2e5a5a4eb 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs
@@ -1,9 +1,9 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// Base class for all implementations of .
@@ -81,4 +81,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return HashCode.Combine(this.WhitePoint, this.ChromaticityCoordinates);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs
index c3d850251..c9246f510 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Companding;
-namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
+namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
///
/// The sRgb working space.
diff --git a/src/ImageSharp/ColorSpaces/LinearRgb.cs b/src/ImageSharp/ColorSpaces/LinearRgb.cs
index 7ef50e9c4..c120ef114 100644
--- a/src/ImageSharp/ColorSpaces/LinearRgb.cs
+++ b/src/ImageSharp/ColorSpaces/LinearRgb.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
+using SixLabors.ImageSharp.ColorSpaces.Conversion;
namespace SixLabors.ImageSharp.ColorSpaces
{
@@ -143,4 +143,4 @@ namespace SixLabors.ImageSharp.ColorSpaces
&& this.B.Equals(other.B);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs
index bb71deba3..3c26b7733 100644
--- a/src/ImageSharp/ColorSpaces/Rgb.cs
+++ b/src/ImageSharp/ColorSpaces/Rgb.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
+using SixLabors.ImageSharp.ColorSpaces.Conversion;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.ColorSpaces
@@ -164,4 +164,4 @@ namespace SixLabors.ImageSharp.ColorSpaces
&& this.B.Equals(other.B);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs
index 3f40fa4f5..152c7ee0b 100644
--- a/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs
+++ b/src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs
@@ -1,8 +1,8 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.ColorSpaces.Companding;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
+using SixLabors.ImageSharp.ColorSpaces.Conversion;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.ColorSpaces
@@ -112,4 +112,4 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
public static readonly RgbWorkingSpace WideGamutRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, 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/Common/Extensions/ComparableExtensions.cs b/src/ImageSharp/Common/Extensions/ComparableExtensions.cs
index 3c8570a2a..1fe2a24c7 100644
--- a/src/ImageSharp/Common/Extensions/ComparableExtensions.cs
+++ b/src/ImageSharp/Common/Extensions/ComparableExtensions.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp
///
/// Restricts a to be within a specified range.
///
- /// The The value to clamp.
+ /// The value to clamp.
/// The minimum value. If value is less than min, min will be returned.
/// The maximum value. If value is greater than max, max will be returned.
///
@@ -137,4 +137,4 @@ namespace SixLabors.ImageSharp
return value;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs b/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs
index bd25a7b44..462eeb302 100644
--- a/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs
+++ b/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs
@@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
vector.W = target.W;
- Vector4Utils.UnPremultiply(ref vector);
+ Vector4Utilities.UnPremultiply(ref vector);
target = vector;
}
@@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp
out Vector4 vector);
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
- Vector4Utils.UnPremultiply(ref vector);
+ Vector4Utilities.UnPremultiply(ref vector);
target = vector;
}
@@ -140,7 +140,7 @@ namespace SixLabors.ImageSharp
{
int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn);
var currentColor = sourceRowSpan[offsetX].ToVector4();
- Vector4Utils.Premultiply(ref currentColor);
+ Vector4Utilities.Premultiply(ref currentColor);
vectorX += matrixX[y, x] * currentColor;
vectorY += matrixY[y, x] * currentColor;
@@ -193,7 +193,7 @@ namespace SixLabors.ImageSharp
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
vector.W = target.W;
- Vector4Utils.UnPremultiply(ref vector);
+ Vector4Utilities.UnPremultiply(ref vector);
target = vector;
}
@@ -238,7 +238,7 @@ namespace SixLabors.ImageSharp
ref vector);
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
- Vector4Utils.UnPremultiply(ref vector);
+ Vector4Utilities.UnPremultiply(ref vector);
target = vector;
}
@@ -270,7 +270,7 @@ namespace SixLabors.ImageSharp
{
int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn);
var currentColor = sourceRowSpan[offsetX].ToVector4();
- Vector4Utils.Premultiply(ref currentColor);
+ Vector4Utilities.Premultiply(ref currentColor);
vector += matrix[y, x] * currentColor;
}
}
diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs
index 92430c915..fb1f88a2d 100644
--- a/src/ImageSharp/Common/Helpers/ImageMaths.cs
+++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs
@@ -359,7 +359,7 @@ namespace SixLabors.ImageSharp
}
}
- return height;
+ return width;
}
topLeft.Y = GetMinY(bitmap);
diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs b/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs
index aaacfdd85..f16c91b40 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -125,10 +125,7 @@ namespace SixLabors.ImageSharp
Vector4 s = Unsafe.Add(ref sBase, i);
s *= maxBytes;
s += half;
-
- // I'm not sure if Vector4.Clamp() is properly implemented with intrinsics.
- s = Vector4.Max(Vector4.Zero, s);
- s = Vector4.Min(maxBytes, s);
+ s = Vector4Utilities.FastClamp(s, Vector4.Zero, maxBytes);
ref ByteVector4 d = ref Unsafe.Add(ref dBase, i);
d.X = (byte)s.X;
diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.cs b/src/ImageSharp/Common/Helpers/SimdUtils.cs
index b58ec900f..0dc45d887 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.cs
@@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static Vector4 PseudoRound(this Vector4 v)
{
- var sign = Vector4.Clamp(v, new Vector4(-1), new Vector4(1));
+ var sign = Vector4Utilities.FastClamp(v, new Vector4(-1), new Vector4(1));
return v + (sign * 0.5f);
}
diff --git a/src/ImageSharp/Common/Helpers/Vector4Utils.cs b/src/ImageSharp/Common/Helpers/Vector4Utilities.cs
similarity index 85%
rename from src/ImageSharp/Common/Helpers/Vector4Utils.cs
rename to src/ImageSharp/Common/Helpers/Vector4Utilities.cs
index 594a5ff10..9fb4eb790 100644
--- a/src/ImageSharp/Common/Helpers/Vector4Utils.cs
+++ b/src/ImageSharp/Common/Helpers/Vector4Utilities.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -11,8 +11,20 @@ namespace SixLabors.ImageSharp
///
/// Utility methods for the struct.
///
- internal static class Vector4Utils
+ internal static class Vector4Utilities
{
+ ///
+ /// Restricts a vector between a minimum and a maximum value.
+ /// 5x Faster then .
+ ///
+ /// The vector to restrict.
+ /// The minimum value.
+ /// The maximum value.
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static Vector4 FastClamp(Vector4 x, Vector4 min, Vector4 max)
+ => Vector4.Min(Vector4.Max(x, min), max);
+
///
/// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
///
@@ -107,4 +119,4 @@ namespace SixLabors.ImageSharp
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index 02267de1a..7919bc148 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -353,7 +353,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.ReadImageDescriptor();
IManagedByteBuffer localColorTable = null;
- IManagedByteBuffer indices = null;
+ Buffer2D indices = null;
try
{
// Determine the color table for this frame. If there is a local one, use it otherwise use the global color table.
@@ -364,11 +364,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.stream.Read(localColorTable.Array, 0, length);
}
- indices = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(this.imageDescriptor.Width * this.imageDescriptor.Height, AllocationOptions.Clean);
+ indices = this.configuration.MemoryAllocator.Allocate2D(this.imageDescriptor.Width, this.imageDescriptor.Height, AllocationOptions.Clean);
- this.ReadFrameIndices(this.imageDescriptor, indices.GetSpan());
+ this.ReadFrameIndices(indices);
ReadOnlySpan colorTable = MemoryMarshal.Cast((localColorTable ?? this.globalColorTable).GetSpan());
- this.ReadFrameColors(ref image, ref previousFrame, indices.GetSpan(), colorTable, this.imageDescriptor);
+ this.ReadFrameColors(ref image, ref previousFrame, indices, colorTable, this.imageDescriptor);
// Skip any remaining blocks
this.SkipBlock();
@@ -383,16 +383,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// Reads the frame indices marking the color to use for each pixel.
///
- /// The .
- /// The pixel array to write to.
+ /// The 2D pixel buffer to write to.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void ReadFrameIndices(in GifImageDescriptor imageDescriptor, Span indices)
+ private void ReadFrameIndices(Buffer2D indices)
{
int dataSize = this.stream.ReadByte();
- using (var lzwDecoder = new LzwDecoder(this.configuration.MemoryAllocator, this.stream))
- {
- lzwDecoder.DecodePixels(imageDescriptor.Width, imageDescriptor.Height, dataSize, indices);
- }
+ using var lzwDecoder = new LzwDecoder(this.configuration.MemoryAllocator, this.stream);
+ lzwDecoder.DecodePixels(dataSize, indices);
}
///
@@ -404,10 +401,9 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The indexed pixels.
/// The color table containing the available colors.
/// The
- private void ReadFrameColors(ref Image image, ref ImageFrame previousFrame, Span indices, ReadOnlySpan colorTable, in GifImageDescriptor descriptor)
+ private void ReadFrameColors(ref Image image, ref ImageFrame previousFrame, Buffer2D indices, ReadOnlySpan colorTable, in GifImageDescriptor descriptor)
where TPixel : unmanaged, IPixel
{
- ref byte indicesRef = ref MemoryMarshal.GetReference(indices);
int imageWidth = this.logicalScreenDescriptor.Width;
int imageHeight = this.logicalScreenDescriptor.Height;
@@ -440,13 +436,20 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.RestoreToBackground(imageFrame);
}
- int i = 0;
int interlacePass = 0; // The interlace pass
int interlaceIncrement = 8; // The interlacing line increment
int interlaceY = 0; // The current interlaced line
-
- for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
+ int descriptorTop = descriptor.Top;
+ int descriptorBottom = descriptorTop + descriptor.Height;
+ int descriptorLeft = descriptor.Left;
+ int descriptorRight = descriptorLeft + descriptor.Width;
+ bool transFlag = this.graphicsControlExtension.TransparencyFlag;
+ byte transIndex = this.graphicsControlExtension.TransparencyIndex;
+
+ for (int y = descriptorTop; y < descriptorBottom && y < imageHeight; y++)
{
+ ref byte indicesRowRef = ref MemoryMarshal.GetReference(indices.GetRowSpan(y - descriptorTop));
+
// Check if this image is interlaced.
int writeY; // the target y offset to write to
if (descriptor.InterlaceFlag)
@@ -482,35 +485,29 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
ref TPixel rowRef = ref MemoryMarshal.GetReference(imageFrame.GetPixelRowSpan(writeY));
- bool transFlag = this.graphicsControlExtension.TransparencyFlag;
if (!transFlag)
{
// #403 The left + width value can be larger than the image width
- for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
+ for (int x = descriptorLeft; x < descriptorRight && x < imageWidth; x++)
{
- int index = Unsafe.Add(ref indicesRef, i);
+ int index = Unsafe.Add(ref indicesRowRef, x - descriptorLeft);
ref TPixel pixel = ref Unsafe.Add(ref rowRef, x);
Rgb24 rgb = colorTable[index];
pixel.FromRgb24(rgb);
-
- i++;
}
}
else
{
- byte transIndex = this.graphicsControlExtension.TransparencyIndex;
- for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
+ for (int x = descriptorLeft; x < descriptorRight && x < imageWidth; x++)
{
- int index = Unsafe.Add(ref indicesRef, i);
+ int index = Unsafe.Add(ref indicesRowRef, x - descriptorLeft);
if (transIndex != index)
{
ref TPixel pixel = ref Unsafe.Add(ref rowRef, x);
Rgb24 rgb = colorTable[index];
pixel.FromRgb24(rgb);
}
-
- i++;
}
}
}
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index 887540930..62410025c 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -6,6 +6,7 @@ using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
@@ -471,7 +472,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
where TPixel : unmanaged, IPixel
{
using var encoder = new LzwEncoder(this.memoryAllocator, (byte)this.bitDepth);
- encoder.Encode(image.GetPixelBufferSpan(), stream);
+ encoder.Encode(((IPixelSource)image).PixelBuffer, stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Gif/LzwDecoder.cs b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
index 0129db0e3..8289ee75b 100644
--- a/src/ImageSharp/Formats/Gif/LzwDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
@@ -65,15 +65,15 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// Decodes and decompresses all pixel indices from the stream.
///
- /// The width of the pixel index array.
- /// The height of the pixel index array.
/// Size of the data.
/// The pixel array to decode to.
- public void DecodePixels(int width, int height, int dataSize, Span pixels)
+ public void DecodePixels(int dataSize, Buffer2D pixels)
{
Guard.MustBeLessThan(dataSize, int.MaxValue, nameof(dataSize));
// The resulting index table length.
+ int width = pixels.Width;
+ int height = pixels.Height;
int length = width * height;
// Calculate the clear code. The value of the clear code is 2 ^ dataSize
@@ -105,17 +105,28 @@ namespace SixLabors.ImageSharp.Formats.Gif
ref int prefixRef = ref MemoryMarshal.GetReference(this.prefix.GetSpan());
ref int suffixRef = ref MemoryMarshal.GetReference(this.suffix.GetSpan());
ref int pixelStackRef = ref MemoryMarshal.GetReference(this.pixelStack.GetSpan());
- ref byte pixelsRef = ref MemoryMarshal.GetReference(pixels);
for (code = 0; code < clearCode; code++)
{
Unsafe.Add(ref suffixRef, code) = (byte)code;
}
- Span buffer = stackalloc byte[255];
+ Span buffer = stackalloc byte[byte.MaxValue];
+ int y = 0;
+ int x = 0;
+ int rowMax = width;
+ ref byte pixelsRowRef = ref MemoryMarshal.GetReference(pixels.GetRowSpan(y));
while (xyz < length)
{
+ // Reset row reference.
+ if (xyz == rowMax)
+ {
+ x = 0;
+ pixelsRowRef = ref MemoryMarshal.GetReference(pixels.GetRowSpan(++y));
+ rowMax = (y * width) + width;
+ }
+
if (top == 0)
{
if (bits < codeSize)
@@ -209,7 +220,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
top--;
// Clear missing pixels
- Unsafe.Add(ref pixelsRef, xyz++) = (byte)Unsafe.Add(ref pixelStackRef, top);
+ xyz++;
+ Unsafe.Add(ref pixelsRowRef, x++) = (byte)Unsafe.Add(ref pixelStackRef, top);
}
}
diff --git a/src/ImageSharp/Formats/Gif/LzwEncoder.cs b/src/ImageSharp/Formats/Gif/LzwEncoder.cs
index 056076bf0..516b82396 100644
--- a/src/ImageSharp/Formats/Gif/LzwEncoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwEncoder.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -41,13 +41,33 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
private const int HashSize = 5003;
+ ///
+ /// The amount to shift each code.
+ ///
+ private const int HashShift = 4;
+
///
/// Mask used when shifting pixel values
///
private static readonly int[] Masks =
{
- 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
- 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
+ 0b0,
+ 0b1,
+ 0b11,
+ 0b111,
+ 0b1111,
+ 0b11111,
+ 0b111111,
+ 0b1111111,
+ 0b11111111,
+ 0b111111111,
+ 0b1111111111,
+ 0b11111111111,
+ 0b111111111111,
+ 0b1111111111111,
+ 0b11111111111111,
+ 0b111111111111111,
+ 0b1111111111111111
};
///
@@ -80,16 +100,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
private readonly byte[] accumulators = new byte[256];
- ///
- /// For dynamic table sizing
- ///
- private readonly int hsize = HashSize;
-
- ///
- /// The current position within the pixelArray.
- ///
- private int position;
-
///
/// Number of bits/code
///
@@ -177,15 +187,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// Encodes and compresses the indexed pixels to the stream.
///
- /// The span of indexed pixels.
+ /// The 2D buffer of indexed pixels.
/// The stream to write to.
- public void Encode(ReadOnlySpan indexedPixels, Stream stream)
+ public void Encode(Buffer2D indexedPixels, Stream stream)
{
// Write "initial code size" byte
stream.WriteByte((byte)this.initialCodeSize);
- this.position = 0;
-
// Compress and write the pixel data
this.Compress(indexedPixels, this.initialCodeSize + 1, stream);
@@ -199,10 +207,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The number of bits
/// See
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int GetMaxcode(int bitCount)
- {
- return (1 << bitCount) - 1;
- }
+ private static int GetMaxcode(int bitCount) => (1 << bitCount) - 1;
///
/// Add a character to the end of the current packet, and if it is 254 characters,
@@ -239,25 +244,16 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// Reset the code table.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void ResetCodeTable()
- {
- this.hashTable.GetSpan().Fill(-1);
- }
+ private void ResetCodeTable() => this.hashTable.GetSpan().Fill(-1);
///
/// Compress the packets to the stream.
///
- /// The span of indexed pixels.
+ /// The 2D buffer of indexed pixels.
/// The initial bits.
/// The stream to write to.
- private void Compress(ReadOnlySpan indexedPixels, int initialBits, Stream stream)
+ private void Compress(Buffer2D indexedPixels, int initialBits, Stream stream)
{
- int fcode;
- int c;
- int ent;
- int hsizeReg;
- int hshift;
-
// Set up the globals: globalInitialBits - initial number of bits
this.globalInitialBits = initialBits;
@@ -265,92 +261,82 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.clearFlag = false;
this.bitCount = this.globalInitialBits;
this.maxCode = GetMaxcode(this.bitCount);
-
this.clearCode = 1 << (initialBits - 1);
this.eofCode = this.clearCode + 1;
this.freeEntry = this.clearCode + 2;
+ this.accumulatorCount = 0; // Clear packet
- this.accumulatorCount = 0; // clear packet
-
- ent = this.NextPixel(indexedPixels);
-
- // TODO: PERF: It looks like hshift could be calculated once statically.
- hshift = 0;
- for (fcode = this.hsize; fcode < 65536; fcode *= 2)
- {
- ++hshift;
- }
-
- hshift = 8 - hshift; // set hash code range bound
-
- hsizeReg = this.hsize;
-
- this.ResetCodeTable(); // clear hash table
-
+ this.ResetCodeTable(); // Clear hash table
this.Output(this.clearCode, stream);
ref int hashTableRef = ref MemoryMarshal.GetReference(this.hashTable.GetSpan());
ref int codeTableRef = ref MemoryMarshal.GetReference(this.codeTable.GetSpan());
- while (this.position < indexedPixels.Length)
- {
- c = this.NextPixel(indexedPixels);
+ int entry = indexedPixels[0, 0];
- fcode = (c << MaxBits) + ent;
- int i = (c << hshift) ^ ent /* = 0 */;
+ for (int y = 0; y < indexedPixels.Height; y++)
+ {
+ ref byte rowSpanRef = ref MemoryMarshal.GetReference(indexedPixels.GetRowSpan(y));
+ int offsetX = y == 0 ? 1 : 0;
- if (Unsafe.Add(ref hashTableRef, i) == fcode)
+ for (int x = offsetX; x < indexedPixels.Width; x++)
{
- ent = Unsafe.Add(ref codeTableRef, i);
- continue;
- }
+ int code = Unsafe.Add(ref rowSpanRef, x);
+ int freeCode = (code << MaxBits) + entry;
+ int hashIndex = (code << HashShift) ^ entry;
- // Non-empty slot
- if (Unsafe.Add(ref hashTableRef, i) >= 0)
- {
- int disp = 1;
- if (i != 0)
+ if (Unsafe.Add(ref hashTableRef, hashIndex) == freeCode)
{
- disp = hsizeReg - i;
+ entry = Unsafe.Add(ref codeTableRef, hashIndex);
+ continue;
}
- do
+ // Non-empty slot
+ if (Unsafe.Add(ref hashTableRef, hashIndex) >= 0)
{
- if ((i -= disp) < 0)
+ int disp = 1;
+ if (hashIndex != 0)
+ {
+ disp = HashSize - hashIndex;
+ }
+
+ do
{
- i += hsizeReg;
+ if ((hashIndex -= disp) < 0)
+ {
+ hashIndex += HashSize;
+ }
+
+ if (Unsafe.Add(ref hashTableRef, hashIndex) == freeCode)
+ {
+ entry = Unsafe.Add(ref codeTableRef, hashIndex);
+ break;
+ }
}
+ while (Unsafe.Add(ref hashTableRef, hashIndex) >= 0);
- if (Unsafe.Add(ref hashTableRef, i) == fcode)
+ if (Unsafe.Add(ref hashTableRef, hashIndex) == freeCode)
{
- ent = Unsafe.Add(ref codeTableRef, i);
- break;
+ continue;
}
}
- while (Unsafe.Add(ref hashTableRef, i) >= 0);
- if (Unsafe.Add(ref hashTableRef, i) == fcode)
+ this.Output(entry, stream);
+ entry = code;
+ if (this.freeEntry < MaxMaxCode)
{
- continue;
+ Unsafe.Add(ref codeTableRef, hashIndex) = this.freeEntry++; // code -> hashtable
+ Unsafe.Add(ref hashTableRef, hashIndex) = freeCode;
+ }
+ else
+ {
+ this.ClearBlock(stream);
}
- }
-
- this.Output(ent, stream);
- ent = c;
- if (this.freeEntry < MaxMaxCode)
- {
- Unsafe.Add(ref codeTableRef, i) = this.freeEntry++; // code -> hashtable
- Unsafe.Add(ref hashTableRef, i) = fcode;
- }
- else
- {
- this.ClearBlock(stream);
}
}
- // Put out the final code.
- this.Output(ent, stream);
-
+ // Output the final code.
+ this.Output(entry, stream);
this.Output(this.eofCode, stream);
}
@@ -366,19 +352,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.accumulatorCount = 0;
}
- ///
- /// Reads the next pixel from the image.
- ///
- /// The span of indexed pixels.
- ///
- /// The
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private int NextPixel(ReadOnlySpan indexedPixels)
- {
- return indexedPixels[this.position++] & 0xFF;
- }
-
///
/// Output the current code to the stream.
///
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
index 033eedb92..8e14ed2c3 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
@@ -99,22 +99,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
var CMax4 = new Vector4(maximum);
var COff4 = new Vector4(MathF.Ceiling(maximum / 2));
- this.V0L = Vector4.Clamp(this.V0L + COff4, CMin4, CMax4);
- this.V0R = Vector4.Clamp(this.V0R + COff4, CMin4, CMax4);
- this.V1L = Vector4.Clamp(this.V1L + COff4, CMin4, CMax4);
- this.V1R = Vector4.Clamp(this.V1R + COff4, CMin4, CMax4);
- this.V2L = Vector4.Clamp(this.V2L + COff4, CMin4, CMax4);
- this.V2R = Vector4.Clamp(this.V2R + COff4, CMin4, CMax4);
- this.V3L = Vector4.Clamp(this.V3L + COff4, CMin4, CMax4);
- this.V3R = Vector4.Clamp(this.V3R + COff4, CMin4, CMax4);
- this.V4L = Vector4.Clamp(this.V4L + COff4, CMin4, CMax4);
- this.V4R = Vector4.Clamp(this.V4R + COff4, CMin4, CMax4);
- this.V5L = Vector4.Clamp(this.V5L + COff4, CMin4, CMax4);
- this.V5R = Vector4.Clamp(this.V5R + COff4, CMin4, CMax4);
- this.V6L = Vector4.Clamp(this.V6L + COff4, CMin4, CMax4);
- this.V6R = Vector4.Clamp(this.V6R + COff4, CMin4, CMax4);
- this.V7L = Vector4.Clamp(this.V7L + COff4, CMin4, CMax4);
- this.V7R = Vector4.Clamp(this.V7R + COff4, CMin4, CMax4);
+ this.V0L = Vector4Utilities.FastClamp(this.V0L + COff4, CMin4, CMax4);
+ this.V0R = Vector4Utilities.FastClamp(this.V0R + COff4, CMin4, CMax4);
+ this.V1L = Vector4Utilities.FastClamp(this.V1L + COff4, CMin4, CMax4);
+ this.V1R = Vector4Utilities.FastClamp(this.V1R + COff4, CMin4, CMax4);
+ this.V2L = Vector4Utilities.FastClamp(this.V2L + COff4, CMin4, CMax4);
+ this.V2R = Vector4Utilities.FastClamp(this.V2R + COff4, CMin4, CMax4);
+ this.V3L = Vector4Utilities.FastClamp(this.V3L + COff4, CMin4, CMax4);
+ this.V3R = Vector4Utilities.FastClamp(this.V3R + COff4, CMin4, CMax4);
+ this.V4L = Vector4Utilities.FastClamp(this.V4L + COff4, CMin4, CMax4);
+ this.V4R = Vector4Utilities.FastClamp(this.V4R + COff4, CMin4, CMax4);
+ this.V5L = Vector4Utilities.FastClamp(this.V5L + COff4, CMin4, CMax4);
+ this.V5R = Vector4Utilities.FastClamp(this.V5R + COff4, CMin4, CMax4);
+ this.V6L = Vector4Utilities.FastClamp(this.V6L + COff4, CMin4, CMax4);
+ this.V6R = Vector4Utilities.FastClamp(this.V6R + COff4, CMin4, CMax4);
+ this.V7L = Vector4Utilities.FastClamp(this.V7L + COff4, CMin4, CMax4);
+ this.V7R = Vector4Utilities.FastClamp(this.V7R + COff4, CMin4, CMax4);
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
index 5370f2704..a1a6b0172 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
+++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
@@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
for (int j = 0; j < 2; j++)
{
char side = j == 0 ? 'L' : 'R';
- Write($"this.V{i}{side} = Vector4.Clamp(this.V{i}{side} + COff4, CMin4, CMax4);\r\n");
+ Write($"this.V{i}{side} = Vector4Utilities.FastClamp(this.V{i}{side} + COff4, CMin4, CMax4);\r\n");
}
}
PopIndent();
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
index 868faceea..70a34ddcf 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
@@ -589,7 +589,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
private static Vector4 DivideRound(Vector4 dividend, Vector4 divisor)
{
// sign(dividend) = max(min(dividend, 1), -1)
- var sign = Vector4.Clamp(dividend, NegativeOne, Vector4.One);
+ var sign = Vector4Utilities.FastClamp(dividend, NegativeOne, Vector4.One);
// AlmostRound(dividend/divisor) = dividend/divisor + 0.5*sign(dividend)
return (dividend / divisor) + (sign * Offset);
diff --git a/src/ImageSharp/Formats/Png/Zlib/DeflaterConstants.cs b/src/ImageSharp/Formats/Png/Zlib/DeflaterConstants.cs
index 67e8c6900..a3a87a32f 100644
--- a/src/ImageSharp/Formats/Png/Zlib/DeflaterConstants.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/DeflaterConstants.cs
@@ -3,15 +3,13 @@
//
using System;
-using System.Collections.Generic;
-using System.Text;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
///
/// This class contains constants used for deflation.
///
- public static class DeflaterConstants
+ internal static class DeflaterConstants
{
///
/// Set to true to enable debugging
diff --git a/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs b/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs
index 7be794b5e..1a8bb4ab0 100644
--- a/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs
@@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
///
/// Strategies for deflater
///
- public enum DeflateStrategy
+ internal enum DeflateStrategy
{
///
/// The default strategy
diff --git a/src/ImageSharp/Formats/Tga/ImageExtensions.cs b/src/ImageSharp/Formats/Tga/ImageExtensions.cs
new file mode 100644
index 000000000..286f04a22
--- /dev/null
+++ b/src/ImageSharp/Formats/Tga/ImageExtensions.cs
@@ -0,0 +1,36 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.IO;
+
+using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.Formats.Tga;
+
+namespace SixLabors.ImageSharp
+{
+ ///
+ /// Extension methods for the type.
+ ///
+ public static partial class ImageExtensions
+ {
+ ///
+ /// Saves the image to the given stream with the tga format.
+ ///
+ /// The image this method extends.
+ /// The stream to save the image to.
+ /// Thrown if the stream is null.
+ public static void SaveAsTga(this Image source, Stream stream) => SaveAsTga(source, stream, null);
+
+ ///
+ /// Saves the image to the given stream with the tga format.
+ ///
+ /// The image this method extends.
+ /// The stream to save the image to.
+ /// The options for the encoder.
+ /// Thrown if the stream is null.
+ public static void SaveAsTga(this Image source, Stream stream, TgaEncoder encoder) =>
+ source.Save(
+ stream,
+ encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TgaFormat.Instance));
+ }
+}
diff --git a/src/ImageSharp/Formats/Tga/TgaDecoder.cs b/src/ImageSharp/Formats/Tga/TgaDecoder.cs
index 2249c86bf..c3b8526ce 100644
--- a/src/ImageSharp/Formats/Tga/TgaDecoder.cs
+++ b/src/ImageSharp/Formats/Tga/TgaDecoder.cs
@@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
index ead004003..816a472fb 100644
--- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
+++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
@@ -12,8 +12,16 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tga
{
+ ///
+ /// Performs the tga decoding operation.
+ ///
internal sealed class TgaDecoderCore
{
+ ///
+ /// A scratch buffer to reduce allocations.
+ ///
+ private readonly byte[] scratchBuffer = new byte[4];
+
///
/// The metadata.
///
@@ -49,6 +57,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
///
private readonly ITgaDecoderOptions options;
+ ///
+ /// Indicates whether there is a alpha channel present.
+ ///
+ private bool hasAlpha;
+
///
/// Initializes a new instance of the class.
///
@@ -80,7 +93,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
{
try
{
- bool inverted = this.ReadFileHeader(stream);
+ TgaImageOrigin origin = this.ReadFileHeader(stream);
this.currentStream.Skip(this.fileHeader.IdLength);
// Parse the color map, if present.
@@ -97,7 +110,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
var image = Image.CreateUninitialized(this.configuration, this.fileHeader.Width, this.fileHeader.Height, this.metadata);
Buffer2D pixels = image.GetRootFramePixelBuffer();
- if (this.fileHeader.ColorMapType is 1)
+ if (this.fileHeader.ColorMapType == 1)
{
if (this.fileHeader.CMapLength <= 0)
{
@@ -115,7 +128,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
{
this.currentStream.Read(palette.Array, this.fileHeader.CMapStart, colorMapSizeInBytes);
- if (this.fileHeader.ImageType is TgaImageType.RleColorMapped)
+ if (this.fileHeader.ImageType == TgaImageType.RleColorMapped)
{
this.ReadPalettedRle(
this.fileHeader.Width,
@@ -123,7 +136,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
pixels,
palette.Array,
colorMapPixelSizeInBytes,
- inverted);
+ origin);
}
else
{
@@ -133,7 +146,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
pixels,
palette.Array,
colorMapPixelSizeInBytes,
- inverted);
+ origin);
}
}
@@ -152,11 +165,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
case 8:
if (this.fileHeader.ImageType.IsRunLengthEncoded())
{
- this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 1, inverted);
+ this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 1, origin);
}
else
{
- this.ReadMonoChrome(this.fileHeader.Width, this.fileHeader.Height, pixels, inverted);
+ this.ReadMonoChrome(this.fileHeader.Width, this.fileHeader.Height, pixels, origin);
}
break;
@@ -165,11 +178,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
case 16:
if (this.fileHeader.ImageType.IsRunLengthEncoded())
{
- this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 2, inverted);
+ this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 2, origin);
}
else
{
- this.ReadBgra16(this.fileHeader.Width, this.fileHeader.Height, pixels, inverted);
+ this.ReadBgra16(this.fileHeader.Width, this.fileHeader.Height, pixels, origin);
}
break;
@@ -177,11 +190,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
case 24:
if (this.fileHeader.ImageType.IsRunLengthEncoded())
{
- this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 3, inverted);
+ this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 3, origin);
}
else
{
- this.ReadBgr24(this.fileHeader.Width, this.fileHeader.Height, pixels, inverted);
+ this.ReadBgr24(this.fileHeader.Width, this.fileHeader.Height, pixels, origin);
}
break;
@@ -189,17 +202,17 @@ namespace SixLabors.ImageSharp.Formats.Tga
case 32:
if (this.fileHeader.ImageType.IsRunLengthEncoded())
{
- this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 4, inverted);
+ this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 4, origin);
}
else
{
- this.ReadBgra32(this.fileHeader.Width, this.fileHeader.Height, pixels, inverted);
+ this.ReadBgra32(this.fileHeader.Width, this.fileHeader.Height, pixels, origin);
}
break;
default:
- TgaThrowHelper.ThrowNotSupportedException("Does not support this kind of tga files.");
+ TgaThrowHelper.ThrowNotSupportedException("ImageSharp does not support this kind of tga files.");
break;
}
@@ -220,56 +233,73 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// The to assign the palette to.
/// The color palette.
/// Color map size of one entry in bytes.
- /// Indicates, if the origin of the image is top left rather the bottom left (the default).
- private void ReadPaletted(int width, int height, Buffer2D pixels, byte[] palette, int colorMapPixelSizeInBytes, bool inverted)
+ /// The image origin.
+ private void ReadPaletted(int width, int height, Buffer2D pixels, byte[] palette, int colorMapPixelSizeInBytes, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel
{
- using (IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(width, AllocationOptions.Clean))
+ TPixel color = default;
+ bool invertX = InvertX(origin);
+
+ for (int y = 0; y < height; y++)
{
- TPixel color = default;
- Span rowSpan = row.GetSpan();
+ int newY = InvertY(y, height, origin);
+ Span pixelRow = pixels.GetRowSpan(newY);
- for (int y = 0; y < height; y++)
+ switch (colorMapPixelSizeInBytes)
{
- this.currentStream.Read(row);
- int newY = Invert(y, height, inverted);
- Span pixelRow = pixels.GetRowSpan(newY);
- switch (colorMapPixelSizeInBytes)
- {
- case 2:
+ case 2:
+ if (invertX)
+ {
+ for (int x = width - 1; x >= 0; x--)
+ {
+ this.ReadPalettedBgra16Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
+ }
+ }
+ else
+ {
for (int x = 0; x < width; x++)
{
- int colorIndex = rowSpan[x];
-
- // Set alpha value to 1, to treat it as opaque for Bgra5551.
- Bgra5551 bgra = Unsafe.As(ref palette[colorIndex * colorMapPixelSizeInBytes]);
- bgra.PackedValue = (ushort)(bgra.PackedValue | 0x8000);
- color.FromBgra5551(bgra);
- pixelRow[x] = color;
+ this.ReadPalettedBgra16Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
+ }
- break;
+ break;
- case 3:
+ case 3:
+ if (invertX)
+ {
+ for (int x = width - 1; x >= 0; x--)
+ {
+ this.ReadPalettedBgr24Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
+ }
+ }
+ else
+ {
for (int x = 0; x < width; x++)
{
- int colorIndex = rowSpan[x];
- color.FromBgr24(Unsafe.As(ref palette[colorIndex * colorMapPixelSizeInBytes]));
- pixelRow[x] = color;
+ this.ReadPalettedBgr24Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
+ }
- break;
+ break;
- case 4:
+ case 4:
+ if (invertX)
+ {
+ for (int x = width - 1; x >= 0; x--)
+ {
+ this.ReadPalettedBgra32Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
+ }
+ }
+ else
+ {
for (int x = 0; x < width; x++)
{
- int colorIndex = rowSpan[x];
- color.FromBgra32(Unsafe.As(ref palette[colorIndex * colorMapPixelSizeInBytes]));
- pixelRow[x] = color;
+ this.ReadPalettedBgra32Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
+ }
- break;
- }
+ break;
}
}
}
@@ -283,8 +313,8 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// The to assign the palette to.
/// The color palette.
/// Color map size of one entry in bytes.
- /// Indicates, if the origin of the image is top left rather the bottom left (the default).
- private void ReadPalettedRle(int width, int height, Buffer2D pixels, byte[] palette, int colorMapPixelSizeInBytes, bool inverted)
+ /// The image origin.
+ private void ReadPalettedRle(int width, int height, Buffer2D pixels, byte[] palette, int colorMapPixelSizeInBytes, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel
{
int bytesPerPixel = 1;
@@ -296,7 +326,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
for (int y = 0; y < height; y++)
{
- int newY = Invert(y, height, inverted);
+ int newY = InvertY(y, height, origin);
Span pixelRow = pixels.GetRowSpan(newY);
int rowStartIdx = y * width * bytesPerPixel;
for (int x = 0; x < width; x++)
@@ -308,10 +338,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
color.FromL8(Unsafe.As(ref palette[bufferSpan[idx] * colorMapPixelSizeInBytes]));
break;
case 2:
- // Set alpha value to 1, to treat it as opaque for Bgra5551.
- Bgra5551 bgra = Unsafe.As(ref palette[bufferSpan[idx] * colorMapPixelSizeInBytes]);
- bgra.PackedValue = (ushort)(bgra.PackedValue | 0x8000);
- color.FromBgra5551(bgra);
+ this.ReadPalettedBgra16Pixel(palette, bufferSpan[idx], colorMapPixelSizeInBytes, ref color);
break;
case 3:
color.FromBgr24(Unsafe.As(ref palette[bufferSpan[idx] * colorMapPixelSizeInBytes]));
@@ -321,7 +348,8 @@ namespace SixLabors.ImageSharp.Formats.Tga
break;
}
- pixelRow[x] = color;
+ int newX = InvertX(x, width, origin);
+ pixelRow[newX] = color;
}
}
}
@@ -334,22 +362,43 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// The width of the image.
/// The height of the image.
/// The to assign the palette to.
- /// Indicates, if the origin of the image is top left rather the bottom left (the default).
- private void ReadMonoChrome(int width, int height, Buffer2D pixels, bool inverted)
+ /// the image origin.
+ private void ReadMonoChrome(int width, int height, Buffer2D pixels, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel
{
- using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 1, 0))
+ bool invertX = InvertX(origin);
+ if (invertX)
{
+ TPixel color = default;
for (int y = 0; y < height; y++)
{
- this.currentStream.Read(row);
- int newY = Invert(y, height, inverted);
+ int newY = InvertY(y, height, origin);
Span pixelSpan = pixels.GetRowSpan(newY);
- PixelOperations.Instance.FromL8Bytes(
- this.configuration,
- row.GetSpan(),
- pixelSpan,
- width);
+ for (int x = width - 1; x >= 0; x--)
+ {
+ this.ReadL8Pixel(color, x, pixelSpan);
+ }
+ }
+
+ return;
+ }
+
+ using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 1, 0))
+ {
+ bool invertY = InvertY(origin);
+ if (invertY)
+ {
+ for (int y = height - 1; y >= 0; y--)
+ {
+ this.ReadL8Row(width, pixels, row, y);
+ }
+ }
+ else
+ {
+ for (int y = 0; y < height; y++)
+ {
+ this.ReadL8Row(width, pixels, row, y);
+ }
}
}
}
@@ -361,30 +410,64 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// The width of the image.
/// The height of the image.
/// The to assign the palette to.
- /// Indicates, if the origin of the image is top left rather the bottom left (the default).
- private void ReadBgra16(int width, int height, Buffer2D pixels, bool inverted)
+ /// The image origin.
+ private void ReadBgra16(int width, int height, Buffer2D pixels, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel
{
+ TPixel color = default;
+ bool invertX = InvertX(origin);
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 2, 0))
{
for (int y = 0; y < height; y++)
{
- this.currentStream.Read(row);
- Span rowSpan = row.GetSpan();
+ int newY = InvertY(y, height, origin);
+ Span pixelSpan = pixels.GetRowSpan(newY);
- // We need to set each alpha component value to fully opaque.
- for (int x = 1; x < rowSpan.Length; x += 2)
+ if (invertX)
{
- rowSpan[x] = (byte)(rowSpan[x] | (1 << 7));
+ for (int x = width - 1; x >= 0; x--)
+ {
+ this.currentStream.Read(this.scratchBuffer, 0, 2);
+ if (!this.hasAlpha)
+ {
+ this.scratchBuffer[1] |= 1 << 7;
+ }
+
+ if (this.fileHeader.ImageType == TgaImageType.BlackAndWhite)
+ {
+ color.FromLa16(Unsafe.As(ref this.scratchBuffer[0]));
+ }
+ else
+ {
+ color.FromBgra5551(Unsafe.As(ref this.scratchBuffer[0]));
+ }
+
+ pixelSpan[x] = color;
+ }
}
+ else
+ {
+ this.currentStream.Read(row);
+ Span rowSpan = row.GetSpan();
- int newY = Invert(y, height, inverted);
- Span pixelSpan = pixels.GetRowSpan(newY);
- PixelOperations.Instance.FromBgra5551Bytes(
- this.configuration,
- rowSpan,
- pixelSpan,
- width);
+ if (!this.hasAlpha)
+ {
+ // We need to set the alpha component value to fully opaque.
+ for (int x = 1; x < rowSpan.Length; x += 2)
+ {
+ rowSpan[x] |= 1 << 7;
+ }
+ }
+
+ if (this.fileHeader.ImageType == TgaImageType.BlackAndWhite)
+ {
+ PixelOperations.Instance.FromLa16Bytes(this.configuration, rowSpan, pixelSpan, width);
+ }
+ else
+ {
+ PixelOperations.Instance.FromBgra5551Bytes(this.configuration, rowSpan, pixelSpan, width);
+ }
+ }
}
}
}
@@ -396,22 +479,44 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// The width of the image.
/// The height of the image.
/// The to assign the palette to.
- /// Indicates, if the origin of the image is top left rather the bottom left (the default).
- private void ReadBgr24(int width, int height, Buffer2D pixels, bool inverted)
+ /// The image origin.
+ private void ReadBgr24(int width, int height, Buffer2D pixels, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel
{
- using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, 0))
+ bool invertX = InvertX(origin);
+ if (invertX)
{
+ TPixel color = default;
for (int y = 0; y < height; y++)
{
- this.currentStream.Read(row);
- int newY = Invert(y, height, inverted);
+ int newY = InvertY(y, height, origin);
Span pixelSpan = pixels.GetRowSpan(newY);
- PixelOperations.Instance.FromBgr24Bytes(
- this.configuration,
- row.GetSpan(),
- pixelSpan,
- width);
+ for (int x = width - 1; x >= 0; x--)
+ {
+ this.ReadBgr24Pixel(color, x, pixelSpan);
+ }
+ }
+
+ return;
+ }
+
+ using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, 0))
+ {
+ bool invertY = InvertY(origin);
+
+ if (invertY)
+ {
+ for (int y = height - 1; y >= 0; y--)
+ {
+ this.ReadBgr24Row(width, pixels, row, y);
+ }
+ }
+ else
+ {
+ for (int y = 0; y < height; y++)
+ {
+ this.ReadBgr24Row(width, pixels, row, y);
+ }
}
}
}
@@ -423,22 +528,52 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// The width of the image.
/// The height of the image.
/// The to assign the palette to.
- /// Indicates, if the origin of the image is top left rather the bottom left (the default).
- private void ReadBgra32(int width, int height, Buffer2D pixels, bool inverted)
+ /// The image origin.
+ private void ReadBgra32(int width, int height, Buffer2D pixels, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel
{
- using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0))
+ TPixel color = default;
+ bool invertX = InvertX(origin);
+ if (this.tgaMetadata.AlphaChannelBits == 8 && !invertX)
{
- for (int y = 0; y < height; y++)
+ using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0))
{
- this.currentStream.Read(row);
- int newY = Invert(y, height, inverted);
- Span pixelSpan = pixels.GetRowSpan(newY);
- PixelOperations.Instance.FromBgra32Bytes(
- this.configuration,
- row.GetSpan(),
- pixelSpan,
- width);
+ if (InvertY(origin))
+ {
+ for (int y = height - 1; y >= 0; y--)
+ {
+ this.ReadBgra32Row(width, pixels, row, y);
+ }
+ }
+ else
+ {
+ for (int y = 0; y < height; y++)
+ {
+ this.ReadBgra32Row(width, pixels, row, y);
+ }
+ }
+ }
+
+ return;
+ }
+
+ for (int y = 0; y < height; y++)
+ {
+ int newY = InvertY(y, height, origin);
+ Span pixelRow = pixels.GetRowSpan(newY);
+ if (invertX)
+ {
+ for (int x = width - 1; x >= 0; x--)
+ {
+ this.ReadBgra32Pixel(x, color, pixelRow);
+ }
+ }
+ else
+ {
+ for (int x = 0; x < width; x++)
+ {
+ this.ReadBgra32Pixel(x, color, pixelRow);
+ }
}
}
}
@@ -451,18 +586,19 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// The height of the image.
/// The to assign the palette to.
/// The bytes per pixel.
- /// Indicates, if the origin of the image is top left rather the bottom left (the default).
- private void ReadRle(int width, int height, Buffer2D pixels, int bytesPerPixel, bool inverted)
+ /// The image origin.
+ private void ReadRle(int width, int height, Buffer2D pixels, int bytesPerPixel, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel
{
TPixel color = default;
+ var alphaBits = this.tgaMetadata.AlphaChannelBits;
using (IMemoryOwner buffer = this.memoryAllocator.Allocate(width * height * bytesPerPixel, AllocationOptions.Clean))
{
Span bufferSpan = buffer.GetSpan();
this.UncompressRle(width, height, bufferSpan, bytesPerPixel);
for (int y = 0; y < height; y++)
{
- int newY = Invert(y, height, inverted);
+ int newY = InvertY(y, height, origin);
Span pixelRow = pixels.GetRowSpan(newY);
int rowStartIdx = y * width * bytesPerPixel;
for (int x = 0; x < width; x++)
@@ -474,19 +610,41 @@ namespace SixLabors.ImageSharp.Formats.Tga
color.FromL8(Unsafe.As(ref bufferSpan[idx]));
break;
case 2:
- // Set alpha value to 1, to treat it as opaque for Bgra5551.
- bufferSpan[idx + 1] = (byte)(bufferSpan[idx + 1] | 128);
- color.FromBgra5551(Unsafe.As(ref bufferSpan[idx]));
+ if (!this.hasAlpha)
+ {
+ // Set alpha value to 1, to treat it as opaque for Bgra5551.
+ bufferSpan[idx + 1] = (byte)(bufferSpan[idx + 1] | 128);
+ }
+
+ if (this.fileHeader.ImageType == TgaImageType.RleBlackAndWhite)
+ {
+ color.FromLa16(Unsafe.As(ref bufferSpan[idx]));
+ }
+ else
+ {
+ color.FromBgra5551(Unsafe.As(ref bufferSpan[idx]));
+ }
+
break;
case 3:
color.FromBgr24(Unsafe.As(ref bufferSpan[idx]));
break;
case 4:
- color.FromBgra32(Unsafe.As(ref bufferSpan[idx]));
+ if (this.hasAlpha)
+ {
+ color.FromBgra32(Unsafe.As(ref bufferSpan[idx]));
+ }
+ else
+ {
+ var alpha = alphaBits == 0 ? byte.MaxValue : bufferSpan[idx + 3];
+ color.FromBgra32(new Bgra32(bufferSpan[idx + 2], bufferSpan[idx + 1], bufferSpan[idx], (byte)alpha));
+ }
+
break;
}
- pixelRow[x] = color;
+ int newX = InvertX(x, width, origin);
+ pixelRow[newX] = color;
}
}
}
@@ -506,6 +664,104 @@ namespace SixLabors.ImageSharp.Formats.Tga
this.metadata);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ReadL8Row(int width, Buffer2D pixels, IManagedByteBuffer row, int y)
+ where TPixel : unmanaged, IPixel
+ {
+ this.currentStream.Read(row);
+ Span pixelSpan = pixels.GetRowSpan(y);
+ PixelOperations.Instance.FromL8Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ReadL8Pixel(TPixel color, int x, Span pixelSpan)
+ where TPixel : unmanaged, IPixel
+ {
+ var pixelValue = (byte)this.currentStream.ReadByte();
+ color.FromL8(Unsafe.As(ref pixelValue));
+ pixelSpan[x] = color;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ReadBgr24Pixel(TPixel color, int x, Span pixelSpan)
+ where TPixel : unmanaged, IPixel
+ {
+ this.currentStream.Read(this.scratchBuffer, 0, 3);
+ color.FromBgr24(Unsafe.As(ref this.scratchBuffer[0]));
+ pixelSpan[x] = color;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ReadBgr24Row(int width, Buffer2D pixels, IManagedByteBuffer row, int y)
+ where TPixel : unmanaged, IPixel
+ {
+ this.currentStream.Read(row);
+ Span pixelSpan = pixels.GetRowSpan(y);
+ PixelOperations.Instance.FromBgr24Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ReadBgra32Pixel(int x, TPixel color, Span pixelRow)
+ where TPixel : unmanaged, IPixel
+ {
+ this.currentStream.Read(this.scratchBuffer, 0, 4);
+ var alpha = this.tgaMetadata.AlphaChannelBits == 0 ? byte.MaxValue : this.scratchBuffer[3];
+ color.FromBgra32(new Bgra32(this.scratchBuffer[2], this.scratchBuffer[1], this.scratchBuffer[0], alpha));
+ pixelRow[x] = color;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ReadBgra32Row(int width, Buffer2D pixels, IManagedByteBuffer row, int y)
+ where TPixel : unmanaged, IPixel
+ {
+ this.currentStream.Read(row);
+ Span pixelSpan = pixels.GetRowSpan(y);
+ PixelOperations.Instance.FromBgra32Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ReadPalettedBgra16Pixel(byte[] palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span pixelRow)
+ where TPixel : unmanaged, IPixel
+ {
+ int colorIndex = this.currentStream.ReadByte();
+ this.ReadPalettedBgra16Pixel(palette, colorIndex, colorMapPixelSizeInBytes, ref color);
+ pixelRow[x] = color;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ReadPalettedBgra16Pixel(byte[] palette, int index, int colorMapPixelSizeInBytes, ref TPixel color)
+ where TPixel : unmanaged, IPixel
+ {
+ Bgra5551 bgra = default;
+ bgra.FromBgra5551(Unsafe.As(ref palette[index * colorMapPixelSizeInBytes]));
+
+ if (!this.hasAlpha)
+ {
+ // Set alpha value to 1, to treat it as opaque.
+ bgra.PackedValue = (ushort)(bgra.PackedValue | 0x8000);
+ }
+
+ color.FromBgra5551(bgra);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ReadPalettedBgr24Pixel(byte[] palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span pixelRow)
+ where TPixel : unmanaged, IPixel
+ {
+ int colorIndex = this.currentStream.ReadByte();
+ color.FromBgr24(Unsafe.As(ref palette[colorIndex * colorMapPixelSizeInBytes]));
+ pixelRow[x] = color;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void ReadPalettedBgra32Pixel(byte[] palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span pixelRow)
+ where TPixel : unmanaged, IPixel
+ {
+ int colorIndex = this.currentStream.ReadByte();
+ color.FromBgra32(Unsafe.As(ref palette[colorIndex * colorMapPixelSizeInBytes]));
+ pixelRow[x] = color;
+ }
+
///
/// Produce uncompressed tga data from a run length encoded stream.
///
@@ -554,18 +810,80 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// Returns the y- value based on the given height.
///
/// The y- value representing the current row.
- /// The height of the bitmap.
- /// Whether the bitmap is inverted.
+ /// The height of the image.
+ /// The image origin.
/// The representing the inverted value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int Invert(int y, int height, bool inverted) => (!inverted) ? height - y - 1 : y;
+ private static int InvertY(int y, int height, TgaImageOrigin origin)
+ {
+ if (InvertY(origin))
+ {
+ return height - y - 1;
+ }
+
+ return y;
+ }
+
+ ///
+ /// Indicates whether the y coordinates needs to be inverted, to keep a top left origin.
+ ///
+ /// The image origin.
+ /// True, if y coordinate needs to be inverted.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool InvertY(TgaImageOrigin origin)
+ {
+ switch (origin)
+ {
+ case TgaImageOrigin.BottomLeft:
+ case TgaImageOrigin.BottomRight:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ ///
+ /// Returns the x- value based on the given width.
+ ///
+ /// The x- value representing the current column.
+ /// The width of the image.
+ /// The image origin.
+ /// The representing the inverted value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int InvertX(int x, int width, TgaImageOrigin origin)
+ {
+ if (InvertX(origin))
+ {
+ return width - x - 1;
+ }
+
+ return x;
+ }
+
+ ///
+ /// Indicates whether the x coordinates needs to be inverted, to keep a top left origin.
+ ///
+ /// The image origin.
+ /// True, if x coordinate needs to be inverted.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool InvertX(TgaImageOrigin origin)
+ {
+ switch (origin)
+ {
+ case TgaImageOrigin.TopRight:
+ case TgaImageOrigin.BottomRight:
+ return true;
+ default:
+ return false;
+ }
+ }
///
/// Reads the tga file header from the stream.
///
/// The containing image data.
- /// true, if the image origin is top left.
- private bool ReadFileHeader(Stream stream)
+ /// The image origin.
+ private TgaImageOrigin ReadFileHeader(Stream stream)
{
this.currentStream = stream;
@@ -577,13 +895,18 @@ namespace SixLabors.ImageSharp.Formats.Tga
this.tgaMetadata = this.metadata.GetTgaMetadata();
this.tgaMetadata.BitsPerPixel = (TgaBitsPerPixel)this.fileHeader.PixelDepth;
- // Bit at position 5 of the descriptor indicates, that the origin is top left instead of bottom right.
- if ((this.fileHeader.ImageDescriptor & (1 << 5)) != 0)
+ var alphaBits = this.fileHeader.ImageDescriptor & 0xf;
+ if (alphaBits != 0 && alphaBits != 1 && alphaBits != 8)
{
- return true;
+ TgaThrowHelper.ThrowImageFormatException("Invalid alpha channel bits");
}
- return false;
+ this.tgaMetadata.AlphaChannelBits = (byte)alphaBits;
+ this.hasAlpha = alphaBits > 0;
+
+ // Bits 4 and 5 describe the image origin.
+ var origin = (TgaImageOrigin)((this.fileHeader.ImageDescriptor & 0x30) >> 4);
+ return origin;
}
}
}
diff --git a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
index d5d7ce49e..94bd367aa 100644
--- a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
+++ b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
@@ -78,8 +78,24 @@ namespace SixLabors.ImageSharp.Formats.Tga
imageType = this.compression is TgaCompression.RunLength ? TgaImageType.RleBlackAndWhite : TgaImageType.BlackAndWhite;
}
- // If compression is used, set bit 5 of the image descriptor to indicate an left top origin.
- byte imageDescriptor = (byte)(this.compression is TgaCompression.RunLength ? 32 : 0);
+ byte imageDescriptor = 0;
+ if (this.compression is TgaCompression.RunLength)
+ {
+ // If compression is used, set bit 5 of the image descriptor to indicate a left top origin.
+ imageDescriptor |= 0x20;
+ }
+
+ if (this.bitsPerPixel is TgaBitsPerPixel.Pixel32)
+ {
+ // Indicate, that 8 bit are used for the alpha channel.
+ imageDescriptor |= 0x8;
+ }
+
+ if (this.bitsPerPixel is TgaBitsPerPixel.Pixel16)
+ {
+ // Indicate, that 1 bit is used for the alpha channel.
+ imageDescriptor |= 0x1;
+ }
var fileHeader = new TgaFileHeader(
idLength: 0,
diff --git a/src/ImageSharp/Formats/Tga/TgaImageOrigin.cs b/src/ImageSharp/Formats/Tga/TgaImageOrigin.cs
new file mode 100644
index 000000000..06d7b5945
--- /dev/null
+++ b/src/ImageSharp/Formats/Tga/TgaImageOrigin.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Formats.Tga
+{
+ internal enum TgaImageOrigin
+ {
+ ///
+ /// Bottom left origin.
+ ///
+ BottomLeft = 0,
+
+ ///
+ /// Bottom right origin.
+ ///
+ BottomRight = 1,
+
+ ///
+ /// Top left origin.
+ ///
+ TopLeft = 2,
+
+ ///
+ /// Top right origin.
+ ///
+ TopRight = 3,
+ }
+}
diff --git a/src/ImageSharp/Formats/Tga/TgaMetadata.cs b/src/ImageSharp/Formats/Tga/TgaMetadata.cs
index 4ce61d2e4..69dee768a 100644
--- a/src/ImageSharp/Formats/Tga/TgaMetadata.cs
+++ b/src/ImageSharp/Formats/Tga/TgaMetadata.cs
@@ -29,6 +29,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
///
public TgaBitsPerPixel BitsPerPixel { get; set; } = TgaBitsPerPixel.Pixel24;
+ ///
+ /// Gets or sets the the number of alpha bits per pixel.
+ ///
+ public byte AlphaChannelBits { get; set; } = 0;
+
///
public IDeepCloneable DeepClone() => new TgaMetadata(this);
}
diff --git a/src/ImageSharp/GeometryUtilities.cs b/src/ImageSharp/GeometryUtilities.cs
index 43c46f181..00fa5b97f 100644
--- a/src/ImageSharp/GeometryUtilities.cs
+++ b/src/ImageSharp/GeometryUtilities.cs
@@ -1,10 +1,10 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
-namespace SixLabors
+namespace SixLabors.ImageSharp
{
///
/// Utility class for common geometric functions.
@@ -31,4 +31,4 @@ namespace SixLabors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float RadianToDegree(float radian) => radian / (MathF.PI / 180F);
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs
index 0850e2213..06b05fe3c 100644
--- a/src/ImageSharp/Image.FromBytes.cs
+++ b/src/ImageSharp/Image.FromBytes.cs
@@ -26,14 +26,55 @@ namespace SixLabors.ImageSharp
///
/// By reading the header on the provided byte array this calculates the images format.
///
- /// The configuration.
+ /// The configuration.
/// The byte array containing encoded image data to read the header from.
/// The mime type or null if none found.
- public static IImageFormat DetectFormat(Configuration config, byte[] data)
+ public static IImageFormat DetectFormat(Configuration configuration, byte[] data)
{
- using (var stream = new MemoryStream(data))
+ Guard.NotNull(configuration, nameof(configuration));
+ using (var stream = new MemoryStream(data, 0, data.Length, false, true))
+ {
+ return DetectFormat(configuration, stream);
+ }
+ }
+
+ ///
+ /// Reads the raw image information from the specified stream without fully decoding it.
+ ///
+ /// The byte array containing encoded image data to read the header from.
+ /// Thrown if the stream is not readable.
+ ///
+ /// The or null if suitable info detector not found.
+ ///
+ public static IImageInfo Identify(byte[] data) => Identify(data, out IImageFormat _);
+
+ ///
+ /// Reads the raw image information from the specified stream without fully decoding it.
+ ///
+ /// The byte array containing encoded image data to read the header from.
+ /// The format type of the decoded image.
+ /// Thrown if the stream is not readable.
+ ///
+ /// The or null if suitable info detector not found.
+ ///
+ public static IImageInfo Identify(byte[] data, out IImageFormat format) => Identify(Configuration.Default, data, out format);
+
+ ///
+ /// Reads the raw image information from the specified stream without fully decoding it.
+ ///
+ /// The configuration.
+ /// The byte array containing encoded image data to read the header from.
+ /// The format type of the decoded image.
+ /// Thrown if the stream is not readable.
+ ///
+ /// The or null if suitable info detector is not found.
+ ///
+ public static IImageInfo Identify(Configuration configuration, byte[] data, out IImageFormat format)
+ {
+ Guard.NotNull(configuration, nameof(configuration));
+ using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
- return DetectFormat(config, stream);
+ return Identify(configuration, stream, out format);
}
}
@@ -68,33 +109,33 @@ namespace SixLabors.ImageSharp
///
/// Load a new instance of from the given encoded byte array.
///
- /// The configuration options.
+ /// The configuration options.
/// The byte array containing encoded image data.
/// The pixel format.
/// A new .
- public static Image Load(Configuration config, byte[] data)
+ public static Image Load(Configuration configuration, byte[] data)
where TPixel : unmanaged, IPixel
{
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
- return Load(config, stream);
+ return Load(configuration, stream);
}
}
///
/// Load a new instance of from the given encoded byte array.
///
- /// The configuration options.
+ /// The configuration options.
/// The byte array containing encoded image data.
/// The of the decoded image.
/// The pixel format.
/// A new .
- public static Image Load(Configuration config, byte[] data, out IImageFormat format)
+ public static Image Load(Configuration configuration, byte[] data, out IImageFormat format)
where TPixel : unmanaged, IPixel
{
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
- return Load(config, stream, out format);
+ return Load(configuration, stream, out format);
}
}
@@ -117,17 +158,17 @@ namespace SixLabors.ImageSharp
///
/// Load a new instance of from the given encoded byte array.
///
- /// The Configuration.
+ /// The Configuration.
/// The byte array containing encoded image data.
/// The decoder.
/// The pixel format.
/// A new .
- public static Image Load(Configuration config, byte[] data, IImageDecoder decoder)
+ public static Image Load(Configuration configuration, byte[] data, IImageDecoder decoder)
where TPixel : unmanaged, IPixel
{
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
- return Load(config, stream, decoder);
+ return Load(configuration, stream, decoder);
}
}
@@ -144,18 +185,18 @@ namespace SixLabors.ImageSharp
///
/// By reading the header on the provided byte array this calculates the images format.
///
- /// The configuration.
+ /// The configuration.
/// The byte array containing encoded image data to read the header from.
/// The mime type or null if none found.
- public static IImageFormat DetectFormat(Configuration config, ReadOnlySpan data)
+ public static IImageFormat DetectFormat(Configuration configuration, ReadOnlySpan data)
{
- int maxHeaderSize = config.MaxHeaderSize;
+ int maxHeaderSize = configuration.MaxHeaderSize;
if (maxHeaderSize <= 0)
{
return null;
}
- foreach (IImageFormatDetector detector in config.ImageFormatsManager.FormatDetectors)
+ foreach (IImageFormatDetector detector in configuration.ImageFormatsManager.FormatDetectors)
{
IImageFormat f = detector.DetectFormat(data);
@@ -203,18 +244,18 @@ namespace SixLabors.ImageSharp
///
/// Load a new instance of from the given encoded byte span.
///
- /// The configuration options.
+ /// The configuration options.
/// The byte span containing encoded image data.
/// The pixel format.
/// A new .
- public static unsafe Image Load(Configuration config, ReadOnlySpan data)
+ public static unsafe Image Load(Configuration configuration, ReadOnlySpan data)
where TPixel : unmanaged, IPixel
{
fixed (byte* ptr = &data.GetPinnableReference())
{
using (var stream = new UnmanagedMemoryStream(ptr, data.Length))
{
- return Load(config, stream);
+ return Load(configuration, stream);
}
}
}
@@ -222,13 +263,13 @@ namespace SixLabors.ImageSharp
///
/// Load a new instance of from the given encoded byte span.
///
- /// The Configuration.
+ /// The Configuration.
/// The byte span containing image data.
/// The decoder.
/// The pixel format.
/// A new .
public static unsafe Image Load(
- Configuration config,
+ Configuration configuration,
ReadOnlySpan data,
IImageDecoder decoder)
where TPixel : unmanaged, IPixel
@@ -237,7 +278,7 @@ namespace SixLabors.ImageSharp
{
using (var stream = new UnmanagedMemoryStream(ptr, data.Length))
{
- return Load(config, stream, decoder);
+ return Load(configuration, stream, decoder);
}
}
}
@@ -245,13 +286,13 @@ namespace SixLabors.ImageSharp
///
/// Load a new instance of from the given encoded byte span.
///
- /// The configuration options.
+ /// The configuration options.
/// The byte span containing image data.
/// The of the decoded image.
/// The pixel format.
/// A new .
public static unsafe Image Load(
- Configuration config,
+ Configuration configuration,
ReadOnlySpan data,
out IImageFormat format)
where TPixel : unmanaged, IPixel
@@ -260,7 +301,7 @@ namespace SixLabors.ImageSharp
{
using (var stream = new UnmanagedMemoryStream(ptr, data.Length))
{
- return Load(config, stream, out format);
+ return Load(configuration, stream, out format);
}
}
}
@@ -285,38 +326,38 @@ namespace SixLabors.ImageSharp
///
/// Load a new instance of from the given encoded byte array.
///
- /// The config for the decoder.
+ /// The configuration for the decoder.
/// The byte array containing encoded image data.
/// The .
- public static Image Load(Configuration config, byte[] data) => Load(config, data, out _);
+ public static Image Load(Configuration configuration, byte[] data) => Load(configuration, data, out _);
///
/// Load a new instance of from the given encoded byte array.
///
- /// The config for the decoder.
+ /// The configuration for the decoder.
/// The byte array containing image data.
/// The decoder.
/// The .
- public static Image Load(Configuration config, byte[] data, IImageDecoder decoder)
+ public static Image Load(Configuration configuration, byte[] data, IImageDecoder decoder)
{
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
- return Load(config, stream, decoder);
+ return Load(configuration, stream, decoder);
}
}
///
/// Load a new instance of from the given encoded byte array.
///
- /// The config for the decoder.
+ /// The configuration for the decoder.
/// The byte array containing image data.
/// The mime type of the decoded image.
/// The .
- public static Image Load(Configuration config, byte[] data, out IImageFormat format)
+ public static Image Load(Configuration configuration, byte[] data, out IImageFormat format)
{
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
- return Load(config, stream, out format);
+ return Load(configuration, stream, out format);
}
}
@@ -348,20 +389,20 @@ namespace SixLabors.ImageSharp
///
/// Decodes a new instance of from the given encoded byte span.
///
- /// The configuration options.
+ /// The configuration options.
/// The byte span containing image data.
/// The .
- public static Image Load(Configuration config, ReadOnlySpan data) => Load(config, data, out _);
+ public static Image Load(Configuration configuration, ReadOnlySpan data) => Load(configuration, data, out _);
///
/// Load a new instance of from the given encoded byte span.
///
- /// The Configuration.
+ /// The Configuration.
/// The byte span containing image data.
/// The decoder.
/// The .
public static unsafe Image Load(
- Configuration config,
+ Configuration configuration,
ReadOnlySpan data,
IImageDecoder decoder)
{
@@ -369,7 +410,7 @@ namespace SixLabors.ImageSharp
{
using (var stream = new UnmanagedMemoryStream(ptr, data.Length))
{
- return Load(config, stream, decoder);
+ return Load(configuration, stream, decoder);
}
}
}
@@ -377,12 +418,12 @@ namespace SixLabors.ImageSharp
///
/// Load a new instance of from the given encoded byte span.
///
- /// The configuration options.
+ /// The configuration options.
/// The byte span containing image data.
/// The of the decoded image.>
/// The .
public static unsafe Image Load(
- Configuration config,
+ Configuration configuration,
ReadOnlySpan data,
out IImageFormat format)
{
@@ -390,7 +431,7 @@ namespace SixLabors.ImageSharp
{
using (var stream = new UnmanagedMemoryStream(ptr, data.Length))
{
- return Load(config, stream, out format);
+ return Load(configuration, stream, out format);
}
}
}
diff --git a/src/ImageSharp/Image.FromFile.cs b/src/ImageSharp/Image.FromFile.cs
index 45ea378cf..1a9fa1546 100644
--- a/src/ImageSharp/Image.FromFile.cs
+++ b/src/ImageSharp/Image.FromFile.cs
@@ -26,15 +26,55 @@ namespace SixLabors.ImageSharp
///
/// By reading the header on the provided file this calculates the images mime type.
///
- /// The configuration.
+ /// The configuration.
/// The image file to open and to read the header from.
/// The mime type or null if none found.
- public static IImageFormat DetectFormat(Configuration config, string filePath)
+ public static IImageFormat DetectFormat(Configuration configuration, string filePath)
{
- config = config ?? Configuration.Default;
- using (Stream file = config.FileSystem.OpenRead(filePath))
+ Guard.NotNull(configuration, nameof(configuration));
+ using (Stream file = configuration.FileSystem.OpenRead(filePath))
{
- return DetectFormat(config, file);
+ return DetectFormat(configuration, file);
+ }
+ }
+
+ ///
+ /// Reads the raw image information from the specified stream without fully decoding it.
+ ///
+ /// The image file to open and to read the header from.
+ /// Thrown if the stream is not readable.
+ ///
+ /// The or null if suitable info detector not found.
+ ///
+ public static IImageInfo Identify(string filePath) => Identify(filePath, out IImageFormat _);
+
+ ///
+ /// Reads the raw image information from the specified stream without fully decoding it.
+ ///
+ /// The image file to open and to read the header from.
+ /// The format type of the decoded image.
+ /// Thrown if the stream is not readable.
+ ///
+ /// The or null if suitable info detector not found.
+ ///
+ public static IImageInfo Identify(string filePath, out IImageFormat format) => Identify(Configuration.Default, filePath, out format);
+
+ ///
+ /// Reads the raw image information from the specified stream without fully decoding it.
+ ///
+ /// The configuration.
+ /// The image file to open and to read the header from.
+ /// The format type of the decoded image.
+ /// Thrown if the stream is not readable.
+ ///
+ /// The or null if suitable info detector is not found.
+ ///
+ public static IImageInfo Identify(Configuration configuration, string filePath, out IImageFormat format)
+ {
+ Guard.NotNull(configuration, nameof(configuration));
+ using (Stream file = configuration.FileSystem.OpenRead(filePath))
+ {
+ return Identify(configuration, file, out format);
}
}
@@ -62,29 +102,30 @@ namespace SixLabors.ImageSharp
///
/// Create a new instance of the class from the given file.
///
- /// The config for the decoder.
+ /// The configuration for the decoder.
/// The file path to the image.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The .
- public static Image Load(Configuration config, string path) => Load(config, path, out _);
+ public static Image Load(Configuration configuration, string path) => Load(configuration, path, out _);
///
/// Create a new instance of the class from the given file.
///
- /// The Configuration.
+ /// The Configuration.
/// The file path to the image.
/// The decoder.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The .
- public static Image Load(Configuration config, string path, IImageDecoder decoder)
+ public static Image Load(Configuration configuration, string path, IImageDecoder decoder)
{
- using (Stream stream = config.FileSystem.OpenRead(path))
+ Guard.NotNull(configuration, nameof(configuration));
+ using (Stream stream = configuration.FileSystem.OpenRead(path))
{
- return Load(config, stream, decoder);
+ return Load(configuration, stream, decoder);
}
}
@@ -133,26 +174,27 @@ namespace SixLabors.ImageSharp
///
/// Create a new instance of the class from the given file.
///
- /// The configuration options.
+ /// The configuration options.
/// The file path to the image.
///
/// Thrown if the stream is not readable nor seekable.
///
/// The pixel format.
/// A new .
- public static Image Load(Configuration config, string path)
+ public static Image Load(Configuration configuration, string path)
where TPixel : unmanaged, IPixel
{
- using (Stream stream = config.FileSystem.OpenRead(path))
+ Guard.NotNull(configuration, nameof(configuration));
+ using (Stream stream = configuration.FileSystem.OpenRead(path))
{
- return Load(config, stream);
+ return Load(configuration, stream);
}
}
///
/// Create a new instance of the class from the given file.
///
- /// The configuration options.
+ /// The configuration options.
/// The file path to the image.
/// The mime type of the decoded image.
///
@@ -160,12 +202,13 @@ namespace SixLabors.ImageSharp
///
/// The pixel format.
/// A new .
- public static Image Load(Configuration config, string path, out IImageFormat format)
+ public static Image Load(Configuration configuration, string path, out IImageFormat format)
where TPixel : unmanaged, IPixel
{
- using (Stream stream = config.FileSystem.OpenRead(path))
+ Guard.NotNull(configuration, nameof(configuration));
+ using (Stream stream = configuration.FileSystem.OpenRead(path))
{
- return Load(config, stream, out format);
+ return Load(configuration, stream, out format);
}
}
@@ -173,18 +216,19 @@ namespace SixLabors.ImageSharp
/// Create a new instance of the class from the given file.
/// The pixel type is selected by the decoder.
///
- /// The configuration options.
+ /// The configuration options.
/// The file path to the image.
/// The mime type of the decoded image.
///
/// Thrown if the stream is not readable nor seekable.
///
/// A new .
- public static Image Load(Configuration config, string path, out IImageFormat format)
+ public static Image Load(Configuration configuration, string path, out IImageFormat format)
{
- using (Stream stream = config.FileSystem.OpenRead(path))
+ Guard.NotNull(configuration, nameof(configuration));
+ using (Stream stream = configuration.FileSystem.OpenRead(path))
{
- return Load(config, stream, out format);
+ return Load(configuration, stream, out format);
}
}
@@ -207,7 +251,7 @@ namespace SixLabors.ImageSharp
///
/// Create a new instance of the class from the given file.
///
- /// The Configuration.
+ /// The Configuration.
/// The file path to the image.
/// The decoder.
///
@@ -215,12 +259,13 @@ namespace SixLabors.ImageSharp
///
/// The pixel format.
/// A new .
- public static Image Load(Configuration config, string path, IImageDecoder decoder)
+ public static Image Load(Configuration configuration, string path, IImageDecoder decoder)
where TPixel : unmanaged, IPixel
{
- using (Stream stream = config.FileSystem.OpenRead(path))
+ Guard.NotNull(configuration, nameof(configuration));
+ using (Stream stream = configuration.FileSystem.OpenRead(path))
{
- return Load(config, stream, decoder);
+ return Load(configuration, stream, decoder);
}
}
}
diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs
index d756ff7ac..52d71409b 100644
--- a/src/ImageSharp/Image.FromStream.cs
+++ b/src/ImageSharp/Image.FromStream.cs
@@ -26,15 +26,15 @@ namespace SixLabors.ImageSharp
///
/// By reading the header on the provided stream this calculates the images format type.
///
- /// The configuration.
+ /// The configuration.
/// The image stream to read the header from.
/// Thrown if the stream is not readable.
/// The format type or null if none found.
- public static IImageFormat DetectFormat(Configuration config, Stream stream)
- => WithSeekableStream(config, stream, s => InternalDetectFormat(s, config));
+ public static IImageFormat DetectFormat(Configuration configuration, Stream stream)
+ => WithSeekableStream(configuration, stream, s => InternalDetectFormat(s, configuration));
///
- /// By reading the header on the provided stream this reads the raw image information.
+ /// Reads the raw image information from the specified stream without fully decoding it.
///
/// The image stream to read the header from.
/// Thrown if the stream is not readable.
@@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp
public static IImageInfo Identify(Stream stream) => Identify(stream, out IImageFormat _);
///
- /// By reading the header on the provided stream this reads the raw image information.
+ /// Reads the raw image information from the specified stream without fully decoding it.
///
/// The image stream to read the header from.
/// The format type of the decoded image.
@@ -57,16 +57,16 @@ namespace SixLabors.ImageSharp
///
/// Reads the raw image information from the specified stream without fully decoding it.
///
- /// The configuration.
+ /// The configuration.
/// The image stream to read the information from.
/// The format type of the decoded image.
/// Thrown if the stream is not readable.
///
/// The or null if suitable info detector is not found.
///
- public static IImageInfo Identify(Configuration config, Stream stream, out IImageFormat format)
+ public static IImageInfo Identify(Configuration configuration, Stream stream, out IImageFormat format)
{
- (IImageInfo info, IImageFormat format) data = WithSeekableStream(config, stream, s => InternalIdentity(s, config ?? Configuration.Default));
+ (IImageInfo info, IImageFormat format) data = WithSeekableStream(configuration, stream, s => InternalIdentity(s, configuration ?? Configuration.Default));
format = data.format;
return data.info;
@@ -108,24 +108,24 @@ namespace SixLabors.ImageSharp
/// Decode a new instance of the class from the given stream.
/// The pixel format is selected by the decoder.
///
- /// The config for the decoder.
+ /// The configuration for the decoder.
/// The stream containing image information.
/// The decoder.
/// Thrown if the stream is not readable.
/// Image cannot be loaded.
/// A new .>
- public static Image Load(Configuration config, Stream stream, IImageDecoder decoder) =>
- WithSeekableStream(config, stream, s => decoder.Decode(config, s));
+ public static Image Load(Configuration configuration, Stream stream, IImageDecoder decoder) =>
+ WithSeekableStream(configuration, stream, s => decoder.Decode(configuration, s));
///
/// Decode a new instance of the class from the given stream.
///
- /// The config for the decoder.
+ /// The configuration for the decoder.
/// The stream containing image information.
/// Thrown if the stream is not readable.
/// Image cannot be loaded.
/// A new .>
- public static Image Load(Configuration config, Stream stream) => Load(config, stream, out _);
+ public static Image Load(Configuration configuration, Stream stream) => Load(configuration, stream, out _);
///
/// Create a new instance of the class from the given stream.
@@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp
/// A new .>
public static Image Load(Stream stream)
where TPixel : unmanaged, IPixel
- => Load(null, stream);
+ => Load(Configuration.Default, stream);
///
/// Create a new instance of the class from the given stream.
@@ -150,7 +150,7 @@ namespace SixLabors.ImageSharp
/// A new .>
public static Image Load(Stream stream, out IImageFormat format)
where TPixel : unmanaged, IPixel
- => Load(null, stream, out format);
+ => Load(Configuration.Default, stream, out format);
///
/// Create a new instance of the class from the given stream.
@@ -168,45 +168,45 @@ namespace SixLabors.ImageSharp
///
/// Create a new instance of the class from the given stream.
///
- /// The Configuration.
+ /// The Configuration.
/// The stream containing image information.
/// The decoder.
/// Thrown if the stream is not readable.
/// Image cannot be loaded.
/// The pixel format.
/// A new .>
- public static Image Load(Configuration config, Stream stream, IImageDecoder decoder)
+ public static Image Load(Configuration configuration, Stream stream, IImageDecoder decoder)
where TPixel : unmanaged, IPixel
- => WithSeekableStream(config, stream, s => decoder.Decode(config, s));
+ => WithSeekableStream(configuration, stream, s => decoder.Decode(configuration, s));
///
/// Create a new instance of the class from the given stream.
///
- /// The configuration options.
+ /// The configuration options.
/// The stream containing image information.
/// Thrown if the stream is not readable.
/// Image cannot be loaded.
/// The pixel format.
/// A new .>
- public static Image Load(Configuration config, Stream stream)
+ public static Image Load(Configuration configuration, Stream stream)
where TPixel : unmanaged, IPixel
- => Load(config, stream, out IImageFormat _);
+ => Load(configuration, stream, out IImageFormat _);
///
/// Create a new instance of the class from the given stream.
///
- /// The configuration options.
+ /// The configuration options.
/// The stream containing image information.
/// The format type of the decoded image.
/// Thrown if the stream is not readable.
/// Image cannot be loaded.
/// The pixel format.
- /// A new .>
- public static Image Load(Configuration config, Stream stream, out IImageFormat format)
+ /// A new .
+ public static Image Load(Configuration configuration, Stream stream, out IImageFormat format)
where TPixel : unmanaged, IPixel
{
- config = config ?? Configuration.Default;
- (Image img, IImageFormat format) data = WithSeekableStream(config, stream, s => Decode(s, config));
+ Guard.NotNull(configuration, nameof(configuration));
+ (Image img, IImageFormat format) data = WithSeekableStream(configuration, stream, s => Decode(s, configuration));
format = data.format;
@@ -218,7 +218,7 @@ namespace SixLabors.ImageSharp
var sb = new StringBuilder();
sb.AppendLine("Image cannot be loaded. Available decoders:");
- foreach (KeyValuePair val in config.ImageFormatsManager.ImageDecoders)
+ foreach (KeyValuePair val in configuration.ImageFormatsManager.ImageDecoders)
{
sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
}
@@ -230,16 +230,16 @@ namespace SixLabors.ImageSharp
/// Decode a new instance of the class from the given stream.
/// The pixel format is selected by the decoder.
///
- /// The configuration options.
+ /// The configuration options.
/// The stream containing image information.
/// The format type of the decoded image.
/// Thrown if the stream is not readable.
/// Image cannot be loaded.
/// A new .
- public static Image Load(Configuration config, Stream stream, out IImageFormat format)
+ public static Image Load(Configuration configuration, Stream stream, out IImageFormat format)
{
- config = config ?? Configuration.Default;
- (Image img, IImageFormat format) data = WithSeekableStream(config, stream, s => Decode(s, config));
+ Guard.NotNull(configuration, nameof(configuration));
+ (Image img, IImageFormat format) data = WithSeekableStream(configuration, stream, s => Decode(s, configuration));
format = data.format;
@@ -251,7 +251,7 @@ namespace SixLabors.ImageSharp
var sb = new StringBuilder();
sb.AppendLine("Image cannot be loaded. Available decoders:");
- foreach (KeyValuePair val in config.ImageFormatsManager.ImageDecoders)
+ foreach (KeyValuePair val in configuration.ImageFormatsManager.ImageDecoders)
{
sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
}
@@ -259,7 +259,7 @@ namespace SixLabors.ImageSharp
throw new UnknownImageFormatException(sb.ToString());
}
- private static T WithSeekableStream(Configuration config, Stream stream, Func action)
+ private static T WithSeekableStream(Configuration configuration, Stream stream, Func action)
{
if (!stream.CanRead)
{
@@ -268,7 +268,7 @@ namespace SixLabors.ImageSharp
if (stream.CanSeek)
{
- if (config.ReadOrigin == ReadOrigin.Begin)
+ if (configuration.ReadOrigin == ReadOrigin.Begin)
{
stream.Position = 0;
}
diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs
index bb3128282..0bdbcc4ab 100644
--- a/src/ImageSharp/ImageExtensions.cs
+++ b/src/ImageSharp/ImageExtensions.cs
@@ -112,12 +112,12 @@ namespace SixLabors.ImageSharp
public static string ToBase64String(this Image source, IImageFormat format)
where TPixel : unmanaged, IPixel
{
- using (var stream = new MemoryStream())
- {
- source.Save(stream, format);
- stream.Flush();
- return $"data:{format.DefaultMimeType};base64,{Convert.ToBase64String(stream.ToArray())}";
- }
+ using var stream = new MemoryStream();
+ source.Save(stream, format);
+
+ // Always available.
+ stream.TryGetBuffer(out ArraySegment buffer);
+ return $"data:{format.DefaultMimeType};base64,{Convert.ToBase64String(buffer.Array, 0, (int)stream.Length)}";
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Quantization/IndexedImageFrame{TPixel}.cs b/src/ImageSharp/IndexedImageFrame{TPixel}.cs
similarity index 83%
rename from src/ImageSharp/Processing/Processors/Quantization/IndexedImageFrame{TPixel}.cs
rename to src/ImageSharp/IndexedImageFrame{TPixel}.cs
index ac737f452..07451029e 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/IndexedImageFrame{TPixel}.cs
+++ b/src/ImageSharp/IndexedImageFrame{TPixel}.cs
@@ -4,19 +4,21 @@
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
+using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing.Processors.Quantization;
-namespace SixLabors.ImageSharp.Processing.Processors.Quantization
+namespace SixLabors.ImageSharp
{
///
/// A pixel-specific image frame where each pixel buffer value represents an index in a color palette.
///
/// The pixel format.
- public sealed class IndexedImageFrame : IDisposable
+ public sealed class IndexedImageFrame : IPixelSource, IDisposable
where TPixel : unmanaged, IPixel
{
- private IMemoryOwner pixelsOwner;
+ private Buffer2D pixelBuffer;
private IMemoryOwner paletteOwner;
private bool isDisposed;
@@ -39,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.Configuration = configuration;
this.Width = width;
this.Height = height;
- this.pixelsOwner = configuration.MemoryAllocator.AllocateManagedByteBuffer(width * height);
+ this.pixelBuffer = configuration.MemoryAllocator.Allocate2D(width, height);
// Copy the palette over. We want the lifetime of this frame to be independant of any palette source.
this.paletteOwner = configuration.MemoryAllocator.Allocate(palette.Length);
@@ -67,16 +69,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
public ReadOnlyMemory Palette { get; }
- ///
- /// Gets the pixels of this .
- ///
- /// The
- [MethodImpl(InliningOptions.ShortMethod)]
- public ReadOnlySpan GetPixelBufferSpan() => this.pixelsOwner.GetSpan(); // TODO: Buffer2D
+ ///
+ Buffer2D IPixelSource.PixelBuffer => this.pixelBuffer;
///
/// Gets the representation of the pixels as a of contiguous memory
- /// at row beginning from the the first pixel on that row.
+ /// at row beginning from the first pixel on that row.
///
/// The row index in the pixel buffer.
/// The pixel row as a .
@@ -87,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
///
///
/// Gets the representation of the pixels as a of contiguous memory
- /// at row beginning from the the first pixel on that row.
+ /// at row beginning from the first pixel on that row.
///
///
/// Note: Values written to this span are not sanitized against the palette length.
@@ -98,7 +96,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// The pixel row as a .
[MethodImpl(InliningOptions.ShortMethod)]
public Span GetWritablePixelRowSpanUnsafe(int rowIndex)
- => this.pixelsOwner.GetSpan().Slice(rowIndex * this.Width, this.Width);
+ => this.pixelBuffer.GetRowSpan(rowIndex);
///
public void Dispose()
@@ -106,9 +104,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
if (!this.isDisposed)
{
this.isDisposed = true;
- this.pixelsOwner.Dispose();
+ this.pixelBuffer.Dispose();
this.paletteOwner.Dispose();
- this.pixelsOwner = null;
+ this.pixelBuffer = null;
this.paletteOwner = null;
}
}
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs
index d5f4c54fb..52f6bcaa1 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs
@@ -373,7 +373,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
- vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs
index 0f2991a35..40c187eb2 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs
@@ -296,7 +296,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
- vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs
index f06831284..bbbf9145c 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs
@@ -162,7 +162,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static ushort Pack(ref Vector4 vector)
{
- vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One);
return (ushort)((((int)Math.Round(vector.W * 15F) & 0x0F) << 12)
| (((int)Math.Round(vector.X * 15F) & 0x0F) << 8)
| (((int)Math.Round(vector.Y * 15F) & 0x0F) << 4)
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs
index 92f2a3f75..d10d10b47 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs
@@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static ushort Pack(ref Vector4 vector)
{
- vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One);
return (ushort)(
(((int)Math.Round(vector.X * 31F) & 0x1F) << 10)
| (((int)Math.Round(vector.Y * 31F) & 0x1F) << 5)
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs
index 728966b00..49b4f4138 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs
@@ -171,7 +171,7 @@ namespace SixLabors.ImageSharp.PixelFormats
const float Max = 255F;
// Clamp the value between min and max values
- vector = Vector4.Clamp(vector, Vector4.Zero, new Vector4(Max));
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, new Vector4(Max));
uint byte4 = (uint)Math.Round(vector.X) & 0xFF;
uint byte3 = ((uint)Math.Round(vector.Y) & 0xFF) << 0x8;
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs b/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs
index 7235abd21..815ae6a4e 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs
@@ -176,7 +176,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
internal void ConvertFromRgbaScaledVector4(Vector4 vector)
{
- vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
vector.X,
vector.Y,
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs b/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs
index c622f1750..37a028db2 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs
@@ -156,7 +156,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
- vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.PackedValue = ImageMaths.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z);
}
}
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs b/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs
index 66cb757c3..104c2be45 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs
@@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
- vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.L = ImageMaths.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z);
this.A = (byte)vector.W;
}
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs
index 4885dae61..98a6cdae4 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs
@@ -233,7 +233,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
internal void ConvertFromRgbaScaledVector4(Vector4 vector)
{
- vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.L = ImageMaths.Get16BitBT709Luminance(
vector.X,
vector.Y,
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs
index 3a4b92ff3..a7b350d55 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs
@@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(ref Vector4 vector)
{
- vector = Vector4.Clamp(vector, MinusOne, Vector4.One) * Half;
+ vector = Vector4Utilities.FastClamp(vector, MinusOne, Vector4.One) * Half;
uint byte4 = ((uint)MathF.Round(vector.X) & 0xFF) << 0;
uint byte3 = ((uint)MathF.Round(vector.Y) & 0xFF) << 8;
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs
index 052e44f71..59433f17e 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs
@@ -177,7 +177,7 @@ namespace SixLabors.ImageSharp.PixelFormats
private static ulong Pack(ref Vector4 vector)
{
vector *= Max;
- vector = Vector4.Clamp(vector, Min, Max);
+ vector = Vector4Utilities.FastClamp(vector, Min, Max);
// Round rather than truncate.
ulong word4 = ((ulong)MathF.Round(vector.X) & 0xFFFF) << 0x00;
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs
index 5eb7b74b2..6e4839fed 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs
@@ -254,7 +254,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
- vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs
index e494ff68e..dff8fe83f 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs
@@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromVector4(Vector4 vector)
{
- vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.R = (ushort)MathF.Round(vector.X);
this.G = (ushort)MathF.Round(vector.Y);
this.B = (ushort)MathF.Round(vector.Z);
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs
index 2b5670778..7ca47f838 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs
@@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(ref Vector4 vector)
{
- vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Multiplier;
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Multiplier;
return (uint)(
(((int)Math.Round(vector.X) & 0x03FF) << 0)
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs
index 8f67f2166..43ec095a1 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs
@@ -452,7 +452,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
- vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
return new Rgba32((byte)vector.X, (byte)vector.Y, (byte)vector.Z, (byte)vector.W);
}
@@ -491,7 +491,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
- vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs
index 88ef1dc98..8e5f8f093 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs
@@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba64(Vector4 vector)
{
- vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.R = (ushort)MathF.Round(vector.X);
this.G = (ushort)MathF.Round(vector.Y);
this.B = (ushort)MathF.Round(vector.Z);
@@ -209,7 +209,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromVector4(Vector4 vector)
{
- vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.R = (ushort)MathF.Round(vector.X);
this.G = (ushort)MathF.Round(vector.Y);
this.B = (ushort)MathF.Round(vector.Z);
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs
index 8a6bc94a7..8a6f882c3 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs
@@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromVector4(Vector4 vector)
{
- vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
+ vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One);
this.R = vector.X;
this.G = vector.Y;
this.B = vector.Z;
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs
index e709cd04f..135aa8d58 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs
@@ -183,7 +183,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static ulong Pack(ref Vector4 vector)
{
- vector = Vector4.Clamp(vector, Min, Max);
+ vector = Vector4Utilities.FastClamp(vector, Min, Max);
// Clamp the value between min and max values
ulong word4 = ((ulong)Math.Round(vector.X) & 0xFFFF) << 0x00;
diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs
index 447869a7d..ba676b3b8 100644
--- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs
+++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs
@@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
if (modifiers.IsDefined(PixelConversionModifiers.Premultiply))
{
- Vector4Utils.Premultiply(vectors);
+ Vector4Utilities.Premultiply(vectors);
}
}
@@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
{
if (modifiers.IsDefined(PixelConversionModifiers.Premultiply))
{
- Vector4Utils.UnPremultiply(vectors);
+ Vector4Utilities.UnPremultiply(vectors);
}
if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand))
diff --git a/src/ImageSharp/Processing/AdaptiveThresholdExtensions.cs b/src/ImageSharp/Processing/AdaptiveThresholdExtensions.cs
new file mode 100644
index 000000000..3279d96e3
--- /dev/null
+++ b/src/ImageSharp/Processing/AdaptiveThresholdExtensions.cs
@@ -0,0 +1,74 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.Processing.Processors.Binarization;
+
+namespace SixLabors.ImageSharp.Processing
+{
+ ///
+ /// Extensions to perform AdaptiveThreshold through Mutator.
+ ///
+ public static class AdaptiveThresholdExtensions
+ {
+ ///
+ /// Applies Bradley Adaptive Threshold to the image.
+ ///
+ /// The image this method extends.
+ /// The .
+ public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source)
+ => source.ApplyProcessor(new AdaptiveThresholdProcessor());
+
+ ///
+ /// Applies Bradley Adaptive Threshold to the image.
+ ///
+ /// The image this method extends.
+ /// Threshold limit (0.0-1.0) to consider for binarization.
+ /// The .
+ public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source, float thresholdLimit)
+ => source.ApplyProcessor(new AdaptiveThresholdProcessor(thresholdLimit));
+
+ ///
+ /// Applies Bradley Adaptive Threshold to the image.
+ ///
+ /// The image this method extends.
+ /// Upper (white) color for thresholding.
+ /// Lower (black) color for thresholding.
+ /// The .
+ public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source, Color upper, Color lower)
+ => source.ApplyProcessor(new AdaptiveThresholdProcessor(upper, lower));
+
+ ///
+ /// Applies Bradley Adaptive Threshold to the image.
+ ///
+ /// The image this method extends.
+ /// Upper (white) color for thresholding.
+ /// Lower (black) color for thresholding.
+ /// Threshold limit (0.0-1.0) to consider for binarization.
+ /// The .
+ public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source, Color upper, Color lower, float thresholdLimit)
+ => source.ApplyProcessor(new AdaptiveThresholdProcessor(upper, lower, thresholdLimit));
+
+ ///
+ /// Applies Bradley Adaptive Threshold to the image.
+ ///
+ /// The image this method extends.
+ /// Upper (white) color for thresholding.
+ /// Lower (black) color for thresholding.
+ /// Rectangle region to apply the processor on.
+ /// The .
+ public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source, Color upper, Color lower, Rectangle rectangle)
+ => source.ApplyProcessor(new AdaptiveThresholdProcessor(upper, lower), rectangle);
+
+ ///
+ /// Applies Bradley Adaptive Threshold to the image.
+ ///
+ /// The image this method extends.
+ /// Upper (white) color for thresholding.
+ /// Lower (black) color for thresholding.
+ /// Threshold limit (0.0-1.0) to consider for binarization.
+ /// Rectangle region to apply the processor on.
+ /// The .
+ public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source, Color upper, Color lower, float thresholdLimit, Rectangle rectangle)
+ => source.ApplyProcessor(new AdaptiveThresholdProcessor(upper, lower, thresholdLimit), rectangle);
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor.cs
new file mode 100644
index 000000000..3558a9489
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor.cs
@@ -0,0 +1,77 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Binarization
+{
+ ///
+ /// Performs Bradley Adaptive Threshold filter against an image.
+ ///
+ ///
+ /// Implements "Adaptive Thresholding Using the Integral Image",
+ /// see paper: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.420.7883&rep=rep1&type=pdf
+ ///
+ public class AdaptiveThresholdProcessor : IImageProcessor
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public AdaptiveThresholdProcessor()
+ : this(Color.White, Color.Black, 0.85f)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Threshold limit.
+ public AdaptiveThresholdProcessor(float thresholdLimit)
+ : this(Color.White, Color.Black, thresholdLimit)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Color for upper threshold.
+ /// Color for lower threshold.
+ public AdaptiveThresholdProcessor(Color upper, Color lower)
+ : this(upper, lower, 0.85f)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Color for upper threshold.
+ /// Color for lower threshold.
+ /// Threshold limit.
+ public AdaptiveThresholdProcessor(Color upper, Color lower, float thresholdLimit)
+ {
+ this.Upper = upper;
+ this.Lower = lower;
+ this.ThresholdLimit = thresholdLimit;
+ }
+
+ ///
+ /// Gets or sets upper color limit for thresholding.
+ ///
+ public Color Upper { get; set; }
+
+ ///
+ /// Gets or sets lower color limit for threshold.
+ ///
+ public Color Lower { get; set; }
+
+ ///
+ /// Gets or sets the value for threshold limit.
+ ///
+ public float ThresholdLimit { get; set; }
+
+ ///
+ public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
+ where TPixel : unmanaged, IPixel
+ => new AdaptiveThresholdProcessor(configuration, this, source, sourceRectangle);
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs
new file mode 100644
index 000000000..dd8833ad9
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs
@@ -0,0 +1,160 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.Memory;
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Binarization
+{
+ ///
+ /// Performs Bradley Adaptive Threshold filter against an image.
+ ///
+ internal class AdaptiveThresholdProcessor : ImageProcessor
+ where TPixel : unmanaged, IPixel
+ {
+ private readonly AdaptiveThresholdProcessor definition;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The configuration which allows altering default behaviour or extending the library.
+ /// The defining the processor parameters.
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ public AdaptiveThresholdProcessor(Configuration configuration, AdaptiveThresholdProcessor definition, Image source, Rectangle sourceRectangle)
+ : base(configuration, source, sourceRectangle)
+ {
+ this.definition = definition;
+ }
+
+ ///
+ protected override void OnFrameApply(ImageFrame source)
+ {
+ var intersect = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
+
+ Configuration configuration = this.Configuration;
+ TPixel upper = this.definition.Upper.ToPixel();
+ TPixel lower = this.definition.Lower.ToPixel();
+ float thresholdLimit = this.definition.ThresholdLimit;
+
+ int startY = intersect.Y;
+ int endY = intersect.Bottom;
+ int startX = intersect.X;
+ int endX = intersect.Right;
+
+ int width = intersect.Width;
+ int height = intersect.Height;
+
+ // ClusterSize defines the size of cluster to used to check for average. Tweaked to support up to 4k wide pixels and not more. 4096 / 16 is 256 thus the '-1'
+ byte clusterSize = (byte)Math.Truncate((width / 16f) - 1);
+
+ // Using pooled 2d buffer for integer image table and temp memory to hold Rgb24 converted pixel data.
+ using (Buffer2D intImage = this.Configuration.MemoryAllocator.Allocate2D(width, height))
+ {
+ Rgba32 rgb = default;
+ for (int x = startX; x < endX; x++)
+ {
+ ulong sum = 0;
+ for (int y = startY; y < endY; y++)
+ {
+ Span row = source.GetPixelRowSpan(y);
+ ref TPixel rowRef = ref MemoryMarshal.GetReference(row);
+ ref TPixel color = ref Unsafe.Add(ref rowRef, x);
+ color.ToRgba32(ref rgb);
+
+ sum += (ulong)(rgb.R + rgb.G + rgb.G);
+ if (x - startX != 0)
+ {
+ intImage[x - startX, y - startY] = intImage[x - startX - 1, y - startY] + sum;
+ }
+ else
+ {
+ intImage[x - startX, y - startY] = sum;
+ }
+ }
+ }
+
+ var operation = new RowOperation(intersect, source, intImage, upper, lower, thresholdLimit, clusterSize, startX, endX, startY);
+ ParallelRowIterator.IterateRows(
+ configuration,
+ intersect,
+ in operation);
+ }
+ }
+
+ private readonly struct RowOperation : IRowOperation
+ {
+ private readonly Rectangle bounds;
+ private readonly ImageFrame source;
+ private readonly Buffer2D intImage;
+ private readonly TPixel upper;
+ private readonly TPixel lower;
+ private readonly float thresholdLimit;
+ private readonly int startX;
+ private readonly int endX;
+ private readonly int startY;
+ private readonly byte clusterSize;
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public RowOperation(
+ Rectangle bounds,
+ ImageFrame source,
+ Buffer2D intImage,
+ TPixel upper,
+ TPixel lower,
+ float thresholdLimit,
+ byte clusterSize,
+ int startX,
+ int endX,
+ int startY)
+ {
+ this.bounds = bounds;
+ this.source = source;
+ this.intImage = intImage;
+ this.upper = upper;
+ this.lower = lower;
+ this.thresholdLimit = thresholdLimit;
+ this.startX = startX;
+ this.endX = endX;
+ this.startY = startY;
+ this.clusterSize = clusterSize;
+ }
+
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Invoke(int y)
+ {
+ Rgba32 rgb = default;
+ Span pixelRow = this.source.GetPixelRowSpan(y);
+
+ for (int x = this.startX; x < this.endX; x++)
+ {
+ TPixel pixel = pixelRow[x];
+ pixel.ToRgba32(ref rgb);
+
+ var x1 = Math.Max(x - this.startX - this.clusterSize + 1, 0);
+ var x2 = Math.Min(x - this.startX + this.clusterSize + 1, this.bounds.Width - 1);
+ var y1 = Math.Max(y - this.startY - this.clusterSize + 1, 0);
+ var y2 = Math.Min(y - this.startY + this.clusterSize + 1, this.bounds.Height - 1);
+
+ var count = (uint)((x2 - x1) * (y2 - y1));
+ var sum = (long)Math.Min(this.intImage[x2, y2] - this.intImage[x1, y2] - this.intImage[x2, y1] + this.intImage[x1, y1], long.MaxValue);
+
+ if ((rgb.R + rgb.G + rgb.B) * count <= sum * this.thresholdLimit)
+ {
+ this.source[x, y] = this.lower;
+ }
+ else
+ {
+ this.source[x, y] = this.upper;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
index 493218cde..cf97751be 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
@@ -304,7 +304,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
for (int x = 0; x < this.bounds.Width; x++)
{
ref Vector4 v = ref Unsafe.Add(ref sourceRef, x);
- var clamp = Vector4.Clamp(v, low, high);
+ var clamp = Vector4Utilities.FastClamp(v, low, high);
v.X = MathF.Pow(clamp.X, this.inverseGamma);
v.Y = MathF.Pow(clamp.Y, this.inverseGamma);
v.Z = MathF.Pow(clamp.Z, this.inverseGamma);
diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
index a2c8fc1fb..8201b8e23 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
@@ -58,9 +58,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
var operation = new RowOperation(interest, targetPixels, source.PixelBuffer, this.KernelXY, this.Configuration, this.PreserveAlpha);
ParallelRowIterator.IterateRows(
- this.Configuration,
- interest,
- in operation);
+ this.Configuration,
+ interest,
+ in operation);
Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs
index bdcf3cbc0..8bb60286a 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs
@@ -52,6 +52,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
protected override void BeforeImageApply()
{
+ using (IImageProcessor opaque = new OpaqueProcessor(this.Configuration, this.Source, this.SourceRectangle))
+ {
+ opaque.Execute();
+ }
+
if (this.Grayscale)
{
new GrayscaleBt709Processor(1F).Execute(this.Configuration, this.Source, this.SourceRectangle);
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
index 159c67b5c..1b07589b5 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
@@ -40,6 +40,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
protected override void BeforeImageApply()
{
+ using (IImageProcessor opaque = new OpaqueProcessor(this.Configuration, this.Source, this.SourceRectangle))
+ {
+ opaque.Execute();
+ }
+
if (this.Grayscale)
{
new GrayscaleBt709Processor(1F).Execute(this.Configuration, this.Source, this.SourceRectangle);
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs
index c49d03eb5..8ca548d97 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs
@@ -43,6 +43,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
protected override void BeforeImageApply()
{
+ using (IImageProcessor opaque = new OpaqueProcessor(this.Configuration, this.Source, this.SourceRectangle))
+ {
+ opaque.Execute();
+ }
+
if (this.Grayscale)
{
new GrayscaleBt709Processor(1F).Execute(this.Configuration, this.Source, this.SourceRectangle);
diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
index 7da4eb1b1..dee9d2ff6 100644
--- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
@@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.Length);
PixelOperations.Instance.ToVector4(this.configuration, rowSpan, span);
- Vector4Utils.Transform(span, ref Unsafe.AsRef(this.matrix));
+ Vector4Utilities.Transform(span, ref Unsafe.AsRef(this.matrix));
PixelOperations.Instance.FromVector4Destructive(this.configuration, span, rowSpan);
}
diff --git a/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs
new file mode 100644
index 000000000..95a099106
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs
@@ -0,0 +1,67 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.PixelFormats;
+
+namespace SixLabors.ImageSharp.Processing.Processors.Filters
+{
+ internal sealed class OpaqueProcessor : ImageProcessor
+ where TPixel : unmanaged, IPixel
+ {
+ public OpaqueProcessor(
+ Configuration configuration,
+ Image source,
+ Rectangle sourceRectangle)
+ : base(configuration, source, sourceRectangle)
+ {
+ }
+
+ protected override void OnFrameApply(ImageFrame source)
+ {
+ var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
+
+ var operation = new OpaqueRowOperation(this.Configuration, source, interest);
+ ParallelRowIterator.IterateRows(this.Configuration, interest, in operation);
+ }
+
+ private readonly struct OpaqueRowOperation : IRowOperation
+ {
+ private readonly Configuration configuration;
+ private readonly ImageFrame target;
+ private readonly Rectangle bounds;
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public OpaqueRowOperation(
+ Configuration configuration,
+ ImageFrame target,
+ Rectangle bounds)
+ {
+ this.configuration = configuration;
+ this.target = target;
+ this.bounds = bounds;
+ }
+
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Invoke(int y, Span span)
+ {
+ Span targetRowSpan = this.target.GetPixelRowSpan(y).Slice(this.bounds.X);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span, PixelConversionModifiers.Scale);
+ ref Vector4 baseRef = ref MemoryMarshal.GetReference(span);
+
+ for (int x = 0; x < this.bounds.Width; x++)
+ {
+ ref Vector4 v = ref Unsafe.Add(ref baseRef, x);
+ v.W = 1F;
+ }
+
+ PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan, PixelConversionModifiers.Scale);
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs
index 4583b7cff..386caf1be 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs
@@ -68,21 +68,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows)
{
- ReadOnlySpan quantizedPixelSpan = this.quantized.GetPixelBufferSpan();
ReadOnlySpan paletteSpan = this.quantized.Palette.Span;
int offsetY = this.bounds.Top;
int offsetX = this.bounds.Left;
- int width = this.bounds.Width;
for (int y = rows.Min; y < rows.Max; y++)
{
Span row = this.source.GetPixelRowSpan(y);
- int rowStart = (y - offsetY) * width;
+ ReadOnlySpan quantizedRow = this.quantized.GetPixelRowSpan(y - offsetY);
for (int x = this.bounds.Left; x < this.bounds.Right; x++)
{
- int i = rowStart + x - offsetX;
- row[x] = paletteSpan[quantizedPixelSpan[i]];
+ row[x] = paletteSpan[quantizedRow[x - offsetX]];
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtilities.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtilities.cs
index 04aaa1102..0a00cf8e9 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtilities.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtilities.cs
@@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
MathF.Floor(maxXY.X),
MathF.Floor(maxXY.Y));
- sourceExtents = Vector4.Clamp(sourceExtents, Vector4.Zero, maxSourceExtents);
+ sourceExtents = Vector4Utilities.FastClamp(sourceExtents, Vector4.Zero, maxSourceExtents);
int left = (int)sourceExtents.X;
int top = (int)sourceExtents.Y;
@@ -78,13 +78,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
// Values are first premultiplied to prevent darkening of edge pixels.
var current = sourcePixels[x, y].ToVector4();
- Vector4Utils.Premultiply(ref current);
+ Vector4Utilities.Premultiply(ref current);
sum += current * xWeight * yWeight;
}
}
// Reverse the premultiplication
- Vector4Utils.UnPremultiply(ref sum);
+ Vector4Utilities.UnPremultiply(ref sum);
targetRow[column] = sum;
}
diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets
index 3c3b3b5ec..df153c08b 100644
--- a/tests/Directory.Build.targets
+++ b/tests/Directory.Build.targets
@@ -29,7 +29,7 @@
-
+
diff --git a/tests/ImageSharp.Benchmarks/Codecs/DecodeTga.cs b/tests/ImageSharp.Benchmarks/Codecs/DecodeTga.cs
index 3c8f45edb..072bd53ed 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/DecodeTga.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/DecodeTga.cs
@@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
private byte[] data;
- [Params(TestImages.Tga.Bit24)]
+ [Params(TestImages.Tga.Bit24BottomLeft)]
public string TestImage { get; set; }
[GlobalSetup]
diff --git a/tests/ImageSharp.Benchmarks/Codecs/EncodeTga.cs b/tests/ImageSharp.Benchmarks/Codecs/EncodeTga.cs
index 7100ca6b7..f10eacb28 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/EncodeTga.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/EncodeTga.cs
@@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
- [Params(TestImages.Tga.Bit24)]
+ [Params(TestImages.Tga.Bit24BottomLeft)]
public string TestImage { get; set; }
[GlobalSetup]
diff --git a/tests/ImageSharp.Benchmarks/General/BasicMath/ClampVector4.cs b/tests/ImageSharp.Benchmarks/General/BasicMath/ClampVector4.cs
new file mode 100644
index 000000000..145b98b0f
--- /dev/null
+++ b/tests/ImageSharp.Benchmarks/General/BasicMath/ClampVector4.cs
@@ -0,0 +1,61 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+using BenchmarkDotNet.Attributes;
+
+namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath
+{
+ public class ClampVector4
+ {
+ private readonly float min = -1.5f;
+ private readonly float max = 2.5f;
+ private static readonly float[] Values = { -10, -5, -3, -1.5f, -0.5f, 0f, 1f, 1.5f, 2.5f, 3, 10 };
+
+ [Benchmark(Baseline = true)]
+ public Vector4 UsingVectorClamp()
+ {
+ Vector4 acc = Vector4.Zero;
+
+ for (int i = 0; i < Values.Length; i++)
+ {
+ acc += ClampUsingVectorClamp(Values[i], this.min, this.max);
+ }
+
+ return acc;
+ }
+
+ [Benchmark]
+ public Vector4 UsingVectorMinMax()
+ {
+ Vector4 acc = Vector4.Zero;
+
+ for (int i = 0; i < Values.Length; i++)
+ {
+ acc += ClampUsingVectorMinMax(Values[i], this.min, this.max);
+ }
+
+ return acc;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static Vector4 ClampUsingVectorClamp(float x, float min, float max)
+ {
+ return Vector4.Clamp(new Vector4(x), new Vector4(min), new Vector4(max));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static Vector4 ClampUsingVectorMinMax(float x, float min, float max)
+ {
+ return Vector4.Min(new Vector4(max), Vector4.Max(new Vector4(min), new Vector4(x)));
+ }
+
+ // RESULTS
+ // | Method | Mean | Error | StdDev | Ratio |
+ // |------------------ |---------:|---------:|---------:|------:|
+ // | UsingVectorClamp | 75.21 ns | 1.572 ns | 4.057 ns | 1.00 |
+ // | UsingVectorMinMax | 15.35 ns | 0.356 ns | 0.789 ns | 0.20 |
+ }
+}
diff --git a/tests/ImageSharp.Tests/Colorspaces/CieXyChromaticityCoordinatesTests.cs b/tests/ImageSharp.Tests/Colorspaces/CieXyChromaticityCoordinatesTests.cs
index 4811a66d4..418893f35 100644
--- a/tests/ImageSharp.Tests/Colorspaces/CieXyChromaticityCoordinatesTests.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/CieXyChromaticityCoordinatesTests.cs
@@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using SixLabors.ImageSharp.ColorSpaces;
+using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Colorspaces
diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/ApproximateColorspaceComparer.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/ApproximateColorspaceComparer.cs
index feb3b38f0..2046cdfdc 100644
--- a/tests/ImageSharp.Tests/Colorspaces/Conversion/ApproximateColorspaceComparer.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/ApproximateColorspaceComparer.cs
@@ -3,7 +3,7 @@
using System.Collections.Generic;
using SixLabors.ImageSharp.ColorSpaces;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
+using SixLabors.ImageSharp.ColorSpaces.Conversion;
namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion
{
diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieLchConversionTests.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieLchConversionTests.cs
index 38c0c21bc..50d831fd9 100644
--- a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieLchConversionTests.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieLchConversionTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -92,4 +92,4 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion
}
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieLchuvConversionTests.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieLchuvConversionTests.cs
index 96628977f..471610eba 100644
--- a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieLchuvConversionTests.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieLchuvConversionTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -80,4 +80,4 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion
}
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieXyyConversionTests.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieXyyConversionTests.cs
index f7dc365b8..e00765832 100644
--- a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieXyyConversionTests.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieLabAndCieXyyConversionTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -76,4 +76,4 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion
}
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/ColorConverterAdaptTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/ColorConverterAdaptTest.cs
index 326777f3c..104b1f4b2 100644
--- a/tests/ImageSharp.Tests/Colorspaces/Conversion/ColorConverterAdaptTest.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/ColorConverterAdaptTest.cs
@@ -3,7 +3,6 @@
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
-using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion
@@ -178,4 +177,4 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion
Assert.Equal(expected, actual, ColorSpaceComparer);
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/ImageSharp.Tests/Colorspaces/StringRepresentationTests.cs b/tests/ImageSharp.Tests/Colorspaces/StringRepresentationTests.cs
index 211b98abb..df9659994 100644
--- a/tests/ImageSharp.Tests/Colorspaces/StringRepresentationTests.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/StringRepresentationTests.cs
@@ -3,6 +3,7 @@
using System.Numerics;
using SixLabors.ImageSharp.ColorSpaces;
+using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Colorspaces
diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
index e6b6e43c1..ca236e914 100644
--- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
+++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
@@ -15,7 +15,7 @@ using SixLabors.ImageSharp.Processing.Processors.Quantization;
using Xunit;
-namespace SixLabors.ImageSharp.Tests
+namespace SixLabors.ImageSharp.Tests.Formats
{
public class GeneralFormatTests : FileTestBase
{
@@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Tests
{
using (Image image = file.CreateRgba32Image())
{
- string filename = path + "/" + file.FileNameWithoutExtension + ".txt";
+ string filename = Path.Combine(path, $"{file.FileNameWithoutExtension}.txt");
File.WriteAllText(filename, image.ToBase64String(PngFormat.Instance));
}
}
@@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Tests
{
using (Image image = file.CreateRgba32Image())
{
- image.Save($"{path}/{file.FileName}");
+ image.Save(Path.Combine(path, file.FileName));
}
}
}
@@ -103,25 +103,30 @@ namespace SixLabors.ImageSharp.Tests
{
using (Image image = file.CreateRgba32Image())
{
- using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.bmp"))
+ using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.bmp")))
{
image.SaveAsBmp(output);
}
- using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.jpg"))
+ using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.jpg")))
{
image.SaveAsJpeg(output);
}
- using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.png"))
+ using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.png")))
{
image.SaveAsPng(output);
}
- using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.gif"))
+ using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.gif")))
{
image.SaveAsGif(output);
}
+
+ using (FileStream output = File.OpenWrite(Path.Combine(path, $"{file.FileNameWithoutExtension}.tga")))
+ {
+ image.SaveAsTga(output);
+ }
}
}
}
diff --git a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs
index d011a6330..9dba7179d 100644
--- a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs
+++ b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs
@@ -10,10 +10,11 @@ using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
+using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
-namespace SixLabors.ImageSharp.Tests
+namespace SixLabors.ImageSharp.Tests.Formats
{
public class ImageFormatManagerTests
{
@@ -34,11 +35,13 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count());
+ Assert.Equal(1, this.DefaultFormatsManager.ImageEncoders.Select(item => item.Value).OfType().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count());
Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count());
+ Assert.Equal(1, this.DefaultFormatsManager.ImageDecoders.Select(item => item.Value).OfType().Count());
}
[Fact]
diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs
index bcd98d714..840bb55f2 100644
--- a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs
@@ -6,7 +6,9 @@ using Microsoft.DotNet.RemoteExecutor;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Tests.TestUtilities;
+using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using Xunit;
// ReSharper disable InconsistentNaming
@@ -19,8 +21,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
private static TgaDecoder TgaDecoder => new TgaDecoder();
[Theory]
- [WithFile(Grey, PixelTypes.Rgba32)]
- public void TgaDecoder_CanDecode_Uncompressed_MonoChrome(TestImageProvider provider)
+ [WithFile(Gray8BitTopLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_Gray_WithTopLeftOrigin_8Bit(TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
using (Image image = provider.GetImage(TgaDecoder))
@@ -30,9 +32,213 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
}
+ [Theory]
+ [WithFile(Gray8BitBottomLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_Gray_WithBottomLeftOrigin_8Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray8BitTopRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_Gray_WithTopRightOrigin_8Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray8BitBottomRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_Gray_WithBottomRightOrigin_8Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray8BitRleTopLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithTopLeftOrigin_8Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray8BitRleTopRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithTopRightOrigin_8Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray8BitRleBottomLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomLeftOrigin_8Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray8BitRleBottomRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomRightOrigin_8Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray16BitTopLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_Gray_16Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+
+ // Using here the reference output instead of the the reference decoder,
+ // because the reference decoder output seems not to be correct for 16bit gray images.
+ image.CompareToReferenceOutput(ImageComparer.Exact, provider);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray16BitBottomLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_Gray_WithBottomLeftOrigin_16Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+
+ // Using here the reference output instead of the the reference decoder,
+ // because the reference decoder output seems not to be correct for 16bit gray images.
+ image.CompareToReferenceOutput(ImageComparer.Exact, provider);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray16BitBottomRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_Gray_WithBottomRightOrigin_16Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+
+ // Using here the reference output instead of the the reference decoder,
+ // because the reference decoder output seems not to be correct for 16bit gray images.
+ image.CompareToReferenceOutput(ImageComparer.Exact, provider);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray16BitTopRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_Gray_WithTopRightOrigin_16Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+
+ // Using here the reference output instead of the the reference decoder,
+ // because the reference decoder output seems not to be correct for 16bit gray images.
+ image.CompareToReferenceOutput(ImageComparer.Exact, provider);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray16BitRleTopLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_16Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+
+ // Using here the reference output instead of the the reference decoder,
+ // because the reference decoder output seems not to be correct for 16bit gray images.
+ image.CompareToReferenceOutput(ImageComparer.Exact, provider);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray16BitRleBottomLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomLeftOrigin_16Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+
+ // Using here the reference output instead of the the reference decoder,
+ // because the reference decoder output seems not to be correct for 16bit gray images.
+ image.CompareToReferenceOutput(ImageComparer.Exact, provider);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray16BitRleBottomRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomRightOrigin_16Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+
+ // Using here the reference output instead of the the reference decoder,
+ // because the reference decoder output seems not to be correct for 16bit gray images.
+ image.CompareToReferenceOutput(ImageComparer.Exact, provider);
+ }
+ }
+
+ [Theory]
+ [WithFile(Gray16BitRleTopRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithTopRightOrigin_16Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+
+ // Using here the reference output instead of the the reference decoder,
+ // because the reference decoder output seems not to be correct for 16bit gray images.
+ image.CompareToReferenceOutput(ImageComparer.Exact, provider);
+ }
+ }
+
[Theory]
[WithFile(Bit15, PixelTypes.Rgba32)]
- public void TgaDecoder_CanDecode_Uncompressed_15Bit(TestImageProvider provider)
+ public void TgaDecoder_CanDecode_15Bit(TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
using (Image image = provider.GetImage(TgaDecoder))
@@ -55,8 +261,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
- [WithFile(Bit16, PixelTypes.Rgba32)]
- public void TgaDecoder_CanDecode_Uncompressed_16Bit(TestImageProvider provider)
+ [WithFile(Bit16BottomLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_WithBottomLeftOrigin_16Bit(TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
using (Image image = provider.GetImage(TgaDecoder))
@@ -79,8 +285,44 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
- [WithFile(Bit24, PixelTypes.Rgba32)]
- public void TgaDecoder_CanDecode_Uncompressed_24Bit(TestImageProvider provider)
+ [WithFile(Bit24TopLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_WithTopLeftOrigin_24Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit24BottomLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_WithBottomLeftOrigin_24Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit24TopRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_WithTopRightOrigin_24Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit24BottomRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_WithBottomRightOrigin_24Bit(TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
using (Image image = provider.GetImage(TgaDecoder))
@@ -102,6 +344,30 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
}
+ [Theory]
+ [WithFile(Bit24RleTopRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_WithTopRightOrigin_24Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit24RleBottomRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_WithBottomRightOrigin_24Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
[Theory]
[WithFile(Bit24TopLeft, PixelTypes.Rgba32)]
public void TgaDecoder_CanDecode_Palette_WithTopLeftOrigin_24Bit(TestImageProvider provider)
@@ -115,8 +381,152 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
}
[Theory]
- [WithFile(Bit32, PixelTypes.Rgba32)]
- public void TgaDecoder_CanDecode_Uncompressed_32Bit(TestImageProvider provider)
+ [WithFile(Bit32TopLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_WithTopLeftOrigin_32Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit32TopRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_WithTopRightOrigin_32Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit32BottomLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_WithBottomLeftOrigin_32Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit32BottomRight, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_WithBottomRightOrigin_32Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit16RleBottomLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_WithBottomLeftOrigin_16Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit24RleBottomLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_WithBottomLeftOrigin_24Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit32RleTopLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_WithTopLeftOrigin_32Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel
+ {
+ using (Image image = provider.GetImage(TgaDecoder))
+ {
+ image.DebugSave(provider);
+ TgaTestUtils.CompareWithReferenceDecoder(provider, image);
+ }
+ }
+
+ [Theory]
+ [WithFile(Bit32RleBottomLeft, PixelTypes.Rgba32)]
+ public void TgaDecoder_CanDecode_RunLengthEncoded_WithBottomLeftOrigin_32Bit(TestImageProvider provider)
+ where TPixel : unmanaged, IPixel